第一天:JavaSE基础加强
一、基础回顾
- 集合
1.1 集合的类型与各自的特性
集合: 存储对象数据 的集合容器。
单例集合
----------| Collection 单例集合 的根接口
----------------| List 如果是实现了List接口的集合类,具备的特点: 有序,可重复。
-------------------| ArrayList ArrayList底层是使用了Object数组实现 的。 特点: 查询速度快,增删慢。
-------------------| LinkedList LinkedList底层是使用了链表数据结构实现的。特点: 查询速度慢,增删快
-------------------| Vector 底层是使用了Object数组实现 的, 实现原理与ArrayList 是一致的,但是是线程安全的,操作效率低。
----------------| Set 如果是实现了Set接口的集合类,具备的特点: 无序,不可重复。
-------------------| HashSet 底层是使用了哈希表实现 的。 特点: 存取速度快。
HashSet存储元素的原理:
往hashSet添加元素的时候,首先会调用元素的hashCode方法得到元素的哈希码值,然后把哈希码值经过运算算出该元素存在哈希表中的位置。
情况1:如果算出的位置目前还没有存在任何的元素,那么该元素可以直接添加到哈希表中。
情况2: 如果算出的位置目前已经存在其他的元素,那么还会调用元素 的equals方法再与这个位置上 的元素比较一次。
如果equals方法返回的是true,那么该元素被视为重复元素,不允许添加。如果equals方法返回 的是false,那么该元素也可以被添加。
------------------| TreeSet 底层是使用了红黑树(二叉树)数据结构实现的。 特点: 对集合中的元素进行排序存储、。
TreeSet要注意的事项:
1. 往TreeSet添加元素 的时候,如果元素具备自然顺序的特点,那么TreeSet会根据元素 的自然顺序特性进行排序 存储。
2. 往TreeSet添加元素 的时候,如果元素不具备自然顺序的特点,那么元素所属的类就必须要实现Comparable接口,把比较的规则定义在CompareTo方法上。
3. 往TreeSet添加元素 的时候,如果元素不具备自然顺序的特点,那么元素所属的类就也没有实现Comparable接口,那么在创建TreeSet对象的时候必须要传入比较器对象。
比较器 的定义格式:
class 类名 implements Comparator{
}
双列集合
----------| Map 存储的数据都是以键值对的形式存在的,键可以不重复,值可重复。
-------------| HashMap 底层也是使用了哈希表实现的。
-------------| TreeMap 底层也是使用了红黑树数据结构实现的。
1.2遍历集合
public static void main(String[] args) {
String[] arr = new String[] { "xx", "yy", "zz" };
for (String elt : arr) {
System.out.println(elt);
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
----------------------------------------
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("aa");
list.add("bb");
list.add("cc");
for (String elt : list) {
System.out.println(elt);
}
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
for (Iterator<String> iter = list.iterator(); iter.hasNext();) {
String elt = iter.next();
System.out.println(elt);
}
}
--------------------------------------------
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("dd");
set.add("ee");
set.add("ff");
for (String elt : set) {
System.out.println(elt);
}
for(Iterator<String> iter = set.iterator(); iter.hasNext() ; ){
String elt = iter.next();
System.out.println(elt);
}
}
--------------------------------------
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("aa", "xx");
map.put("bb", "yy");
map.put("cc", "zz");
for (Entry<String, String> entry : map.entrySet()) {
System.out.println(entry);
}
for(String key : map.keySet()){
System.out.println(key + " = " + map.get(key));
}
for(String value : map.values()){
System.out.println(value);
}
}
2.泛型(Generic)
2.1当集合中存储的对象类型不同时,那么会导致程序在运行的时候的转型异常/
泛型 的好处:
1. 把运行时出现 的问题提前至了编译时。
2. 避免了无谓的强制类型转换。
泛型在集合中的应用:
ArrayList<String> list = new ArrayList<String>(); true
ArrayList<Object> list = new ArrayList<String>(); false
ArrayList<String> list = new ArrayList<Object>(); false
考虑到新老系统兼用性:
ArrayList list = new ArrayList<String>(); true
ArrayList<String> list = new ArrayList(); true
注意: 在泛型中没有多态的概念,两边的数据必须要一致。或者是只写一边的泛型类型。
推荐使用: 两边的数据类型都写上一致的。
package cn.itcast.genecity;
import java.util.ArrayList;
public class Demo1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
for(int i = 0 ; i < list.size() ; i++){
String str = list.get(i);
System.out.println(str.toUpperCase());
}
}
}
package cn.itcast.genecity;
public class Demo2 {
public static void main(String[] args) {
Integer i= print(12);
String str = print("abc");
}
public static <abc> abc print(abc o){
return o;
}
}
package cn.itcast.genecity;
import java.util.ArrayList;
import java.util.Comparator;
class Worker implements Comparator<Worker>{
@Override
public int compare(Worker o1, Worker o2) {
return 0;
}
}
class MyList<T>{
Object[] arr = new Object[10];
int index = 0;
public MyList(){
}
public void add(T o){
arr[index++] = o;
}
}
public class Demo3 {
public static void main(String[] args) {
MyList<String> list= new MyList<String>();
list.add("123");
MyList list2 = new MyList();
new ArrayList<String>();
}
}
package cn.itcast.genecity;
interface Dao<T>{
public void add(T t);
public void remove(T t);
}
public class Demo4<T> implements Dao<T>{
public static void main(String[] args) {
new Demo4<String>();
}
@Override
public void add(T t) {
}
@Override
public void remove(T t) {
}
}
- IO流
package cn.itcast.io;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.Socket;
public class Demo1 {
public static void main(String[] args) throws Exception {
readFile();
}
public static void readFile() throws IOException{
FileInputStream fileInputStream = new FileInputStream("F:\\a.txt");
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"utf-8");
int content = 0;
while((content = inputStreamReader.read())!=-1){
System.out.println((char)content);
}
inputStreamReader.close();
}
public static void writeFile() throws IOException{
FileOutputStream fileOutputStream = new FileOutputStream("F:\\a.txt");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"utf-8");
outputStreamWriter.write("大家好");
outputStreamWriter.close();
}
public static void testOutput() throws Exception{
Socket socket = new Socket(InetAddress.getLocalHost(),9090);
OutputStream outputStream = socket.getOutputStream();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
outputStreamWriter.write("不饿!");
}
public static void testInput() throws Exception{
InputStream in = System.in;
InputStreamReader inputStreamReader = new InputStreamReader(in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
System.out.println(bufferedReader.readLine());
}
}
4.多线程
启动线程的方式 1.自定义的类继承Thread类。 使用代码为new MyThread().start() 2.自定义的类实现Runnable接口。 使用代码为new Thread(new MyRunnable()).start
package cn.itcast.thread;
public class Demo1 extends Thread {
public Demo1(String name){
super(name);
}
@Override
public void run() {
for(int i = 0 ; i< 100 ; i++){
System.out.println(Thread.currentThread().getName()+":"+ i);
}
}
public static void main(String[] args) {
Demo1 d = new Demo1("狗娃");
d.start();
for(int i = 0 ; i< 100 ; i++){
System.out.println(Thread.currentThread().getName()+":"+ i);
}
}
}
二、Junit单元测试
1.Junit单元测试框架的基本使用
一、搭建环境: 导入junit.jar包(junit4) 二、写测试类: 0,一般一个类对应一个测试类。 1,测试类与被测试类最好是放到同一个包中(可以是不同的源文件夹) 2,测试类的名字为被测试类的名字加Test后缀。 三:写测试方法: 0,一般一个方法对应一个单元测试方法。 1,测试方法的名字为test前缀加被测试方法的名字,如testAddPerson()。 2,单元测试方法上面要加上@Test注解(org.junit.Test)! 3,单元测试方法不能有参数,也不能有返回值(返回void)!测试的方法不能是静态的方法。 四、测试方法的基本使用: 1,可以单独执行一个测试方法,也可以一次执行所有的、一个包的、一个类中所有的测试方法。 2,执行完后,显示绿色表示测试成功;显示红色表示测试失败(抛异常后会测试失败)。
package cn.itcsat.junit;
import static org.junit.Assert.*;
import java.util.Arrays;
import javax.management.RuntimeErrorException;
import org.junit.Test;
public class Demo1 {
@Test
public void getMax(int a, int b){
int max = a>b?a:b;
System.out.println("最大值:"+max);
}
@Test
public void sort(){
int[] arr = {12,4,1,19};
for(int i = 0 ; i < arr.length-1 ; i++){
for(int j = i+1 ; j<arr.length ; j++){
if(arr[i]>arr[j]){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
System.out.println("数组的元素:"+Arrays.toString(arr));
}
}
2.用于准备环境、清理环境的方法
@Test 表示单元测试方法。 @Before 所修饰的方法应是非static的(且没有参数,返回值为void)。 表示这个方法会在本类中的每个单元测试方法之前都执行一次。 @After 所修饰的方法应是非static的(且没有参数,返回值为void)。 表示这个方法会在本类中的每个单元测试方法之后都执行一次。 @BeforeClass 所修饰的方法应是static的(且没有参数,返回值为void)。 表示这个方法会在本类中的所有单元测试方法之前执行,只执行一次。 @AfterClass 所修饰的方法应是static的(且没有参数,返回值为void)。 表示这个方法会在本类中的所有单元测试方法之后执行,只执行一次。
package cn.itcsat.junit;
import java.io.FileInputStream;
import java.io.IOException;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class Demo2 {
@BeforeClass
public static void beforeRead(){
System.out.println("准备测试环境成功...");
}
@Test
public void readFile() throws IOException{
FileInputStream fileInputStream = new FileInputStream("F:\\a.txt");
int content = fileInputStream.read();
System.out.println("内容:"+content);
}
@Test
public void sort(){
System.out.println("读取文件数据排序..");
}
@AfterClass
public static void afterRead(){
System.out.println("清理测试环境..");
}
}
- Assert断言工具类
其中有一些静态的工具方法(不符合期望就抛异常):
assertTrue(...) 参数的值应是true
assertFalse(...) 参数的值应是false
assertNull(...) 应是null值
assertNotNull(...) 应是非null的值
assertSame(...) 使用==比较的结果为true(表示同一个对象)
AssertNotSame(...) 使用==比较的结果为false
assertEquals(...) 两个对象equals()方法比较结果为true
package cn.itcsat.junit;
public class Tool {
public static int getMax(){
int a = 3;
int b =5;
int max = a>b?a:b;
return max;
}
public static int getMin(){
int a = 3;
int b = 5;
int min = a<b?a:b;
return min;
}
}
package cn.itcsat.junit;
import junit.framework.Assert;
import org.junit.Test;
public class ToolTest {
@Test
public void testGetMax(){
int max = Tool.getMax();
if(max!=5){
throw new RuntimeException();
}else{
System.out.println("最大值:"+ max);
}
}
@Test
public void testGetMin(){
int min = Tool.getMin();
if(min!=3){
throw new RuntimeException();
}else{
System.out.println("最小值:"+ min);
}
}
}
三、内省(Introspector)
为什么要学内省?
开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性。
内省是用于操作java对象的属性的,那么以下问题我们必须要清楚。
问题一: 什么是Java对象的属性和属性的读写方法?
问题二: 如何通过内省访问到javaBean的属性 ?
1. 通过PropertyDescriptor类操作Bean的属性.
public static void testPropertyDescriptor() throws Exception{
Person p = new Person();
PropertyDescriptor propertyDescriptor = new PropertyDescriptor("id",Person.class);
Method writeMethod = propertyDescriptor.getWriteMethod();
Method readMethod = propertyDescriptor.getReadMethod();
propertyDescriptor.getReadMethod();
writeMethod.invoke(p, 12);
System.out.println(readMethod.invoke(p, null));
}
2. 通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法。
public static void testIntrospector() throws Exception{
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
PropertyDescriptor[] descriptor = beanInfo.getPropertyDescriptors();
for(PropertyDescriptor itemProperty : descriptor){
System.out.println(itemProperty.getReadMethod().getName());
}
}
存在的问题: sun公司的内省API过于繁琐,所以Apache组织结合很多实际开发中的应用场景开发了一套简单、易用的API操作Bean的属性——BeanUtils。
public static void main(String[] args) throws Exception {
Person p = new Person();
ConvertUtils.register(new Converter() {
@Override
public Object convert(Class type, Object value) {
try {
if(value!=null){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy MM dd");
Date d = dateFormat.parse((String) value);
return d;
}
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}, Date.class);
BeanUtils.setProperty(p,"id","110");
BeanUtils.setProperty(p,"name","狗娃");
BeanUtils.setProperty(p, "birthDay","1992 12 12");
System.out.println(p.getId() +"=="+ p.getName()+"======"+p.getBirthDay());
}
package cn.itcast.introspector;
import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class Demo1 {
public static void main(String[] args) throws Exception {
Person p = (Person) getInstance();
System.out.println(p);
}
public static Object getInstance() throws Exception{
BufferedReader bufferedReader = new BufferedReader(new FileReader("obj.txt"));
String className = bufferedReader.readLine();
Class clazz = Class.forName(className);
Constructor constructor = clazz.getConstructor(null);
Object o = constructor.newInstance(null);
String line = null;
while((line = bufferedReader.readLine())!=null){
String[] datas = line.split("=");
Field field = clazz.getDeclaredField(datas[0]);
if(field.getType()==int.class){
field.set(o, Integer.parseInt(datas[1]));
}else{
field.set(o, datas[1]);
}
}
return o;
}
}
package cn.itcast.introspector;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import org.junit.Test;
public class Demo2 {
@Test
public void getAllProperty() throws IntrospectionException{
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
for(PropertyDescriptor p : descriptors){
System.out.println(p.getReadMethod());
}
}
@Test
public void testProperty() throws Exception{
Person p = new Person();
PropertyDescriptor descriptor = new PropertyDescriptor("id", Person.class);
Method m = descriptor.getWriteMethod();
m.invoke(p,110);
Method readMethod = descriptor.getReadMethod();
System.out.println(readMethod.invoke(p, null));
}
}
package cn.itcast.introspector;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.crypto.Data;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
public class Demo3 {
public static void main(String[] args) throws Exception {
String id ="110";
String name="陈其";
String salary = "1000.0";
String birthday = "2013-12-10";
ConvertUtils.register(new Converter() {
@Override
public Object convert(Class type, Object value) {
Date date = null;
try{
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
date = dateFormat.parse((String)value);
}catch(Exception e){
e.printStackTrace();
}
return date;
}
}, Date.class);
Emp e = new Emp();
BeanUtils.setProperty(e, "id", id);
BeanUtils.setProperty(e, "name",name);
BeanUtils.setProperty(e, "salary",salary);
BeanUtils.setProperty(e, "birthday",birthday);
System.out.println(e);
}
}
package cn.itcast.introspector;
import java.util.Date;
public class Emp {
private int id;
private String name;
private double salary;
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Emp(int id, String name, double salary) {
super();
this.id = id;
this.name = name;
this.salary = salary;
}
public Emp(){}
@Override
public String toString() {
return "编号:"+this.id+" 姓名:"+ this.name+ " 薪水:"+ this.salary+" 生日:"+ birthday;
}
}
package cn.itcast.introspector;
public class Person {
private int id;
private String name;
public Person(int id, String name) {
super();
this.id = id;
this.name = name;
}
public Person(){}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "编号:"+ this.id+" 姓名:"+ this.name;
}
}
四、Properties类与配置文件
Properties配置文件说明
Properties类对应.properties文件。文件内容是键值对,键值对之间使用"="或空格隔开。开头是"#"的表示注释
Properties类在加载.properties文件时使用的iso8859-1的编码。所以这个文件中的中文要特殊处理:如果这个配置文件中有中文就必须要进行转义,使用native2ascii.exe命令操作:
native2ascii d:/my.properties d:/my2.properties
使用Properties类中的load(InputStream) 方法可以加载配置文件,使用其中的store(OutputStream) 方法可以保存配置到指定文件。
更多的信息可以看Properties类的API文档。
加载配置文件
public static void testLoadProperties() throws Exception {
Properties properties = new Properties();
InputStream in = new FileInputStream("E:/itcast/config.properties");
properties.load(in);
in.close();
System.out.println(properties);
写配置文件
public static void testStoreProperties() throws Exception {
Properties properties = new Properties();
properties.setProperty("name", "李四");
properties.setProperty("age", "20");
OutputStream out = new FileOutputStream("d:/my.properties");
String comments = "这是我的配置文件";
properties.store(out, comments);
out.close();
}
使用Properties类
public class DBUtil {
static Properties properties = new Properties();
static{
try {
Class clazz = DBUtil.class;
InputStreamReader fileReader =
new InputStreamReader(clazz.getResourceAsStream("/db.properties"));
properties.load(fileReader);
} catch (IOException e) {
e.printStackTrace();
}
}
public static String getUserName(){
String userName =properties.getProperty("userName");
return userName;
}
public static String getPassword(){
return properties.getProperty("password");
}
public static void main(String[] args) {
System.out.println("用户名:"+ getUserName());
System.out.println("密码: "+ getPassword());
}
}
五、文件路径
绝对路径
以根目录或某盘符开头的路径(或者说完整的路径)
例如:
c:/a.txt (Windows操作系统中)
c:/xxx/a.txt (Windows操作系统中)
/var/xx/aa.txt (Linux操作系统中)
绝对路径的问题: 比如C:\abc\a.properties文件路径,该路径在windows上执行没有 问题,但是如果把该项目移动到linux上面执行 ,该路径就会出现问题了,因为在linux上面没有c盘的,只有根目录\。
相对路径
相对于当前路径的一个路径。例如当前文件夹为c:/abc时:相对路径a.txt表示c:/abc/a.txt,相对路径xx/a.txt = c:/abc/xx/a.txt
. 表示当前文件夹
.. 表示上级文件夹
相对路径存在的问题:相对路径是相对于目前执行class文件的时候,控制台所在的路径,这样子也会导致出现问题。
Java程序中的相对路径
在Java程序中使用File时写相对路径,是指相对于执行java命令时当前所在的文件夹。
public class PathTest {
public static void main(String[] args) throws Exception {
System.out.println(new File("a.txt").getAbsolutePath());
}
}
在命令行中使用cd命令切换到不同的路径下试试,可以看到以上所说的效果。
在Eclipse中,当前路径是工程的根目录。
classpath路径
classpath路径说明
在Java程序中,一般情况下使用绝对路径还是相对路径都不太合适,因为Java程序的jar包所放的位置不确定,执行java程序时当前的路径也不确定,所以不合适。一般在Java程序中我们会把资源放到classpath中,然后使用classpath路径查找资源。
Classpath路径:就是使用classpath目前的路径。
获取classpath中的资源(InputStream)
public static void main(String[] args) throws Exception {
Class clazz = new ClassPathTest().getClass();
InputStream in = clazz.getResourceAsStream("/cn/itcast/my.properties");
InputStream in2 = clazz.getResourceAsStream("my.properties");
}
package cn.itcast.path;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class DBUtil {
static Properties properties ;
static{
try {
properties = new Properties();
Class clazz = DBUtil.class;
InputStream inputStream = clazz.getResourceAsStream("/db.properties");
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println("当前路径:"+ new File(".").getAbsolutePath() );
System.out.println("用户名:"+ properties.getProperty("userName")+" 密码:"+properties.getProperty("password"));
}
}
package cn.itcast.path;
public class Demo1 {
static String userName = "root";
static String password = "123";
public static void main(String[] args) {
System.out.println("用户名:"+ userName+" 密码:"+password);
}
}
|