------Java培训、Android培训、iOS培训、.Net培训、期待与您交流------
1. java的反射机制:
就是在程序的运行过程中,我们可以获取到任意一个类的字节码文件对象,然后剖析该字节码文件的成员
类中的组成:
成员变量 Field
构造方法 Constructor
成员方法 Method
首先需要获取字节码文件对象:
a: Object类中的getClass()方法
b: 其实每一种数据类型java都给我们提供了一个静态的class属性,可以通过这个静态的class属性来获取该类中的字节码文件对象
c: 可以通过Class类中的一个静态的方法获取该类的字节码文件对象: forName(String className) ,className: 要是指定的类对应的全类名;
2. 通过反射来获取对应的构造方法以及创建对象
获取字节码文件对象 Class clazz = Class.forName("ReflectTest01.Student") ;
public Constructor[] getConstructors() : 获取所有公有的构造方法
public Constructor[] getDeclaredConstructors() : 获取所有的构造方法,包含私有的
public Constructor getConstructor(Class
... parameterTypes): 获取指定的公有的构造方法
public Constructor
getDeclaredConstructor(Class
... parameterTypes)获取指定的任意一种构造方法,包含私有的
Class类中给我们提供了一个方法,用来直接创建该类的实例:public T newInstance()
Object newInstance = clazz.newInstance() ;
System.out.println(newInstance);
注意当我们使用public Constructor
getDeclaredConstructor(Class
... parameterTypes)
获取指定的私有的构造方法时,在创建对象之时会报错:私有的只能在本类中使用,所有就报错了!
为了解决这个问题我们可以使用public void setAccessible(boolean flag):
将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
3.剖析指定字节码文件中的成员变量
获取Student对应的字节码文件对象:Class clazz = Class.forName("ReflectTest01.Student") ;
public Field[] getFields(): 获取公有的字段,包含从父类中继承过来的
public Field[] getDeclaredFields(): 获取本类中所有的字段,包含私有的,但是不包含从父类中继承过来的
public Field getField(String name): 获取指定的公有的字段,name为Student中的成员变量的名字:name,age
public void set(Object obj, Object value): obj: 指定的对象 value: 就是要设置的值
4.通过反射剖析指定的字节码文件中的成员方法
public Method[] getMethods(): 获取公共的成员方法,包含从父类中继承过来的
public Method[] getDeclaredMethods(): 本类中所有的成员方法,不包含从父类中继承过来的
public Method getMethod(String name, Class
... parameterTypes): 获取公有的指定成员方法
name: 表示方法名称 parameterTypes: 这个方法中的参数对应的class类型
public Object invoke(Object obj, Object... args): 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
5 .动态代理: 本来应该自己做的事情,却请了别人来做,被请的人就是代理对象
动态代理: 本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。
Proxy
public static Object newProxyInstance(ClassLoader loader,
Class[] interfaces,
InvocationHandler h)
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
参数含义:
loader - 定义代理类的类加载器
interfaces - 代理类要实现的接口列表
h - 指派方法调用的调用处理程序
InvocationHandler:
InvocationHandler 是代理实例的调用处理程序 实现的接口。
Object invoke(Object proxy, Method method, Object[] args)
参数含义:
proxy - 在其上调用方法的代理实例
method: method - 对应于在代理实例上调用的接口方法的 Method 实例。
args: args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,
6 . 枚举的注意事项
定义枚举类要用关键字enum
所有枚举类都是Enum的子类
枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略
枚举类可以有构造器,但必须是private的,它默认的也是private的。枚举项的用法比较特殊:枚举(“”);
枚举类也可以有抽象方法,但是枚举项必须重写该方法
枚举在switch语句中的使用
public enum Direction {
FRONT , AFTER ,LEFT , RIGHT ;
}
public enum Direction2 {
FRONT("前") , AFTER("后") ,LEFT("左") , RIGHT("右");
public String name ;
private Direction2(String name) {
this.name = name ;
}
}
public enum Direction3 {
FRONT("前"){
@Override
public void show() {
System.out.println(name);
}
} , AFTER("后"){
@Override
public void show() {
System.out.println(name);
}
} ,LEFT("左"){
@Override
public void show() {
System.out.println(name);
}
} , RIGHT("右"){
@Override
public void show() {
System.out.println(name);
}
};
public String name ;
private Direction3(String name) {
this.name = name ;
}
public abstract void show() ;
}
public class DirectionTest {
public static void main(String[] args) {
// 访问这四个枚举项
Direction front = Direction.FRONT ;
Direction after = Direction.AFTER ;
Direction left = Direction.LEFT ;
Direction right = Direction.RIGHT ;
System.out.println(front);
System.out.println(after);
System.out.println(left);
System.out.println(right);
System.out.println("-----------------------------------");
Direction2 front2 = Direction2.FRONT ;
Direction2 after2 = Direction2.AFTER ;
Direction2 left2 = Direction2.LEFT ;
Direction2 right2 = Direction2.RIGHT ;
System.out.println(front2);
System.out.println(after2);
System.out.println(left2);
System.out.println(right2);
System.out.println(front2.name);
System.out.println(after2.name);
System.out.println(left2.name);
System.out.println(right2.name);
System.out.println("-------------------------------------");
Direction3 front3 = Direction3.FRONT ;
Direction3 after3 = Direction3.AFTER ;
Direction3 left3 = Direction3.LEFT ;
Direction3 right3 = Direction3.RIGHT ;
System.out.println(front3);
System.out.println(after3);
System.out.println(left3);
System.out.println(right3);
System.out.println(front3.name);
System.out.println(after3.name);
System.out.println(left3.name);
System.out.println(right3.name);
System.out.println("------------------------");
// 调用方法
front3.show() ;
after3.show() ;
left3.show() ;
right3.show() ;
}
}
7. Jdk1.7的新特性
Jdk1.7的新特性
A:二进制字面量
JDK7开始,终于可以用二进制来表示整数(byte,short,int和long)。
使用二进制字面量的好处是,可以使代码更容易被理解。语法非常简单,只要在二进制数值前面加 0b或者0B
int x = 0b110110
B:数字字面量可以出现下划线
为了增强对数值的阅读性,如我们经常把数据用逗号分隔一样。JDK7提供了_对数据分隔。
举例:
int x = 100_1000;
注意事项:
不能出现在进制标识和数值之间
不能出现在数值开头和结尾
不能出现在小数点旁边
C:switch 语句可以用字符串
D:泛型简化
E:异常的多个catch合并
F:try-with-resources 语句
try(必须是java.lang.AutoCloseable的子类对象){…}catch{...}
好处:
资源自动释放,不需要close()了
把需要关闭资源的部分都定义在这里就ok了
主要是流体系的对象是这个接口的子类(看JDK7的API)