早上8点半就到了。全天犯困。
今天讲了java基础增强知识:
单元测试
1. @Test:定义单元测试方法
2. @Before:定义前处理方法,会在每个单元测试方法之前执行。
3. @After:定义后处理方法,会在每个单元测试方法之后执行。
===================
===================
===================
自动拆装箱
1. 自动拆装箱的概念:基本类型和对应包装类型可以自动转换!
byte <--> Byte
short <--> Short
int <--> Integer
long <--> Long
float <--> Float
double <--> Double
boolean <--> Boolean
char <--> Character
也就是说,可以把int当成Integer来用,也可以把Integer当成int来用!
Integer a = 100;//自动装箱
int i = new Integer(100);//自动拆箱
Object o = 100;//自动装箱
2. 自动拆装箱原理
其实
Integer a = 100;等同于Integer a = Integer.valueOf(100);
int i = a;等同于int i = a.intValue();
3. 变态小题目
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
Integer类内部有一个缓存,其实就是一个Integer[],大小为256,它存储了-128 ~ 127之间的所有Integer对象。
当使用valueOf(100)方法时,该方法判断100在-128~127之间,说明缓存中存在这个Integer,所以它会直接把缓存中的Integer返回。
也就是说,valueOf(100)两次,获取的都是缓存中的Integer!
如果valueOf(200),因为200超出了-128~127范围,valueOf()方法会创建Integer对象返回。即return new Integer(200);
所以valueOf(200)一次,创建一个Integer,valueOf(200)两次,那么两个Integer对象。
i1和i2是缓存中Integer对象的两个引用,也就是说i1和i2引用的是同一对象;
i3和i4是不同的对象,它会范围超出了缓存大小。
===================
可变参数方法
1. 定义可变参数方法:
public void add(int... arr) {
// 其实arr就是int[]类型
int sum = 0;
for(int i = 0; i < arr.length; i++) {
sum += arr[i];
}
}
等同于
public void add(int[] arr) {
...
}
2. 调用可变参数方法
int[] array = {1,2,3};
add(array);//传递数组
add(1,2,3);//等同与传递new int[]{1,2,3}数组
add(1);//等同与传递new int[]{1}数组
add();//等同与传递new int[]{}数组,即没有元素的数组。
3. 可变参数限制
* 一个方法最多只能有一个可变参数
* 可变参数必须是方法的最后一个参数
===================
增强for循环
1. 可以遍历数组、Iterable(包含List、Set)接口的实现类。
2. 增强for内部使用的是迭代器方式
3. 增强for没有原始for强大,但比原始for语法简捷。
==遍历数组==
int[] arr = {1,2,3};
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);//1,2,3
}
for(int e : arr) {
System.out.println(e);//1,2,3
}
==遍历List==
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
for(int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
for(String s : list) {
System.out.println(s);
}
==遍历Set==
Set<String> set = new HashSet<String>();
set.add("aaa");
set.add("bbb");
set.add("ccc");
Iterator it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
for(String s : set) {
System.out.println(s);
}
==遍历Map==
Map<String,String> map = new HashMap<String,String>();
map.put("a", "aaa");
map.put("b", "bbb");
map.put("c", "ccc");
Set<Entry<String,String>> entrySet = map.entrySet();
for(Entry<String,String> entry : entrySet) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
=====================================
=====================================
=====================================
泛型
1. 什么是泛型:类型变量就是泛型。
在没有泛型时,一个ArrayList类的实例可以存储多种类型的元素,例如:
ArrayList list = new ArrayList();
list.add(new Integer(100));
list.add("hello");
list.add(new Object());
在JDK5.0后,ArrayList定义为泛型类:ArrayList<E>,其中E就是泛型,泛型就是类型变量。
在创建泛型类时,需要指定E的值,E需要一个类型,例如:ArrayList<String> list = new ArrayList<String>();
list对象相当与被帖上了一个标签,上面写着String,这个list只能用来存储String类型。
list.add("hello");
list.add(new Integer(100));//编译错误。
2. 泛型类
Java集合类基本上都是泛型类。
ArrayList就是泛型类
在创建泛型类实例时需要给泛型变量指定值:ArrayList<String> list = new ArrayList<String>();在ArrayList中的E都是String类型。
3. 自定义泛型类
class MyClass<T> {
}
其中泛型T可以在MyClass类中的非static成员中使用,例如:
class MyClass<T> {
private T bean;
public MyClass(T bean) {
this.bean = bean;
}
public T getBean() {
return bean;
}
public void setBean(T bean) {
this.bean = bean;
}
}
4. 自定义泛型方法
public <T> T get(T[] arr) {
if(arr.length > 0) {
T t = arr[0];
return t;
}
return null;
}
定义泛型方法时,泛型必须在返回值之前给出。
泛型方法中的泛型T,只能在当前方法中使用。
调用泛型方法:
String[] strs = {"a", "b"};
String s = get(strs);//通过传递的参数自动识别传递给T的类型。因为strs是String[],所以T是String类型。
=====================================
=====================================
=====================================
枚举
1. 枚举就是多例类
单例类是一个类只有一个实例
多例类是一个类有多个实例,但不是无限个数的实例,而是有限个数的实例,例如星期类有七个实例,它就是枚举类了。
2. 多例类
public class Direction {
public static final Direction FRONT = new Direction("front");
public static final Direction BEHIND = new Direction("behind");
public static final Direction LEFT = new Direction("left");
public static final Direction RIGHT = new Direction("right");
private String name;
private Direction(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Direction d1 = Direction.FRONT;
String name = d1.getName();
System.out.println(name);
3. 定义枚举类
只有枚举项的枚举类
public enum Direction {
FRONT, BEHIND, LEFT, RIGHT;//枚举项
}
有成员的枚举类
public enum Direction {
FRONT("front"), BEHIND("behind"), LEFT("left"), RIGHT("right");//枚举项必须在最上面
private String name;
private Direction(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
4. 枚举与switch
switch中可以是枚举类型。
Direction d = Direction.FRONT;
switch(d) {
case FRONT: System.out.println("前面");break;
case BEHIND:System.out.println("后面");break;
case LEFT: System.out.println("左面");break;
case RIGHT: System.out.println("右面");break;
default:System.out.println("错误的方向");
}
5. 枚举中可以有抽象方法
public enum Direction {
FRONT("front") {
public void fun() {
System.out.println("--front--");
}
},
BEHIND("behind") {
public void fun() {
System.out.println("--behind--");
}
},
LEFT("left") {
public void fun() {
System.out.println("--left--");
}
},
RIGHT("right") {
public void fun() {
System.out.println("--right--");
}
};
private String name;
private Direction(String name) {
this.name = name;
}
public String getName() {
return name;
}
public abstract void fun();//抽象方法
}
6. 枚举类的祖先:Enum
所有枚举类的父类:Enum
int compareTo(E e):比较两个枚举常量谁大谁小,其实比较的就是枚举常量在枚举类中声明的顺序,例如FRONT的下标为0,BEHIND下标为1,那么FRONT小于BEHIND;
boolean equals(Object o):比较两个枚举常量是否相等;
int hashCode():返回枚举常量的hashCode;
String name():返回枚举常量的名字;
int ordinal():返回枚举常量在枚举类中声明的序号,第一个枚举常量序号为0;
String toString():把枚举常量转换成字符串;
static T valueOf(Class enumType, String name):把字符串转换成枚举常量。
7. 枚举小结
* 定义枚举类使用enum关键字
* 所有枚举的公共父类Enum
* 只有枚举项的枚举类,最后一个枚举项后面的分号可以省略
* 枚举类可以有成员
* 枚举类的构造器默认是private,也必须是private
* 枚举类可以有抽象方法
* 枚举类可以在switch中使用
=====================================
=====================================
=====================================
反射
1. 什么是反射
Class、Method、Field、Constructor,它们是反射对象。它们是类、方法、成员变量、构造器,在内存中的形式。
也就是万物皆对象!类是类型、方法是类型、成员变量是类型、构造器也是类型。
可以把Class当作类的元神;Method是方法的元神;Field是成员的元神;Constructor是构造器的元神。
得到了元神就可以来操作宿主。
2. 获取Class类的对象
Class表示一个类型,即描述类的类型。
* 类名.class:Class c1 = Object.class;
* 对象.getClass():Class c2 = obj.getClass();
* Class.forName("类全名"):Class c3 = Class.forName("java.lang.String");
Class的用途:
* getName():获取类名
* Class getSupperClass():获取父类类型,即获取父类的元神
* Class[] getInterces():获取所有实现的接口的类型,即获取所有实现接口的元神。
* T newInstance():创建该类的实例(通过默认构造器创建,如果该类型没有默认构造器,那么抛出异常)。
3. 通过Class获取Constructor类对象
* Constructor[] getConstructors():获取本类中所有public构造器
* Constructor getConstructor(Class... parameterTypes):获取指定参数类型的公有构造器对象
* Constructor[] getDeclaredConstructors():获取本类中所有构造器,包含所有访问级别
* Constructor getDeclaredConstructor(Class... parameterTypes):获取指定参数类型的构造器,包含所有访问级别
Construtor的用途:
* T newInstance(Object... params):调用构造器
4. 通过Class获取Method类对象
* Method[] getMethods():获取本类和父类中所有public方法
* Method getMethod(String name, Class... parameterTypes):获取指定名称及参数类型的公有方法,包括父类中的公有方法
* Method[] getDeclaredMethods():获取本类所有方法,包含所有访问级别;
* Mehtod getDeclaredMethod(String name, Class... parameterTypes):获取指定名称及参数类型的,包括所有访问级别,但不包含父类中的方法。
Method的用途:
* Object invoke(Object obj, Object... params):调用方法,其中obj是当前对象,parmas是参数。如果当前方法是static方法,那么在调用invoke方法时,第一个参数为null。
5. 通过Class获取Field类对象
* Field[] getFields():获取本类和父类中所有public成员变量
* Field getField(String name):获取本类或父类中的指定名称的public成员变量
* Field[] getDeclaredFields():获取本类中所有访问级别的成员变量,不包括父类中的。
* Field getDeclaredField(String name):获取本类中指定名称的成员变量,可以是所有访问级别,不包括父类中的。
Field的用途:
* void set(Object obj, Object value):给出指定对象的成员变量赋值,obj为当前对象,value为值
* Object get(Object obj):获取指定对象的成员变量值,obj为当前对象。
下午讲课讲到6点20,然后就阶段测验。磨磨唧唧20分钟才开考。晚饭都不让吃了。全尼玛是犄角旮旯的题。
晚上8点半左右,7辆557连着奔过。前面6辆都爆满了。