七、注解,反射,字节码,类加载机制
一、 注解
- 介绍:注解是JDK5.0开始引入的新技术,注解并不是程序本身,只是对程序做出某种解释(与注释不同是可以被其他程序读取)。
- 内置注解:
@Override :表示重写该方法,如果该方法不存在,则报错。
@Deprecated:遗弃废弃,被它修饰的方法,属性,类不鼓励程序员再使用,eclipse在调用被修饰的代码时会有删除线,但不影响使用。
@SuppressWarnings :忽略警告
- 元注解 :对注解做进一步的解释
@Target : 描述注解的使用范围(包,类,接口,枚举, 属性,方法等)
@Retention : 表示需要在什么级别保存该注释信息,用于描述注解的生命周期
二、JAVA动态性:反射机制
- 动态语言:程序运行时可以改变程序的结构或变量类型。(python,ruby,js)
c,c++,java不是动态语言,但是可以通过反射机制,字节码操作等获得类似动态语言的特性。 - 反射机制:程序已经跑起来了,在运行时依然可以再加载一些新的类。
Class c = Class.forName("com.as.test.User");
对于任意一个已加载的类都可以知道这个类的所有属性的方法,对于任意一个对象,都能调用它的任意一个属性和方法。
public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException {
String path = "com.example.annotation.bean.User";
Class<?> clazz = Class.forName(path);
System.out.println(clazz);
System.out.println(clazz.hashCode());
Class<?> clazz2 = Class.forName(path);
System.out.println(clazz.hashCode());
Class strClass = String.class;
Class strClass2 = path.getClass();
System.out.println(strClass == strClass2);
int[] a = new int[10];
int[] a2 = new int[30];
System.out.println(a.getClass().hashCode());
System.out.println(a2.getClass().hashCode());
int[][] a3 = new int[2][3];
System.out.println(a3.getClass().hashCode());
}
}
- 利用反射API获取类的信息(类名,属性,方法,构造器等)
public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
String path = "com.example.annotation.bean.User";
Class<?> clazz = Class.forName(path);
System.out.println(clazz.getName());
System.out.println(clazz.getSimpleName());
Field[] fields = clazz.getFields();
System.out.println(fields.length);
Field[] fields1 = clazz.getDeclaredFields();
System.out.println(fields1.length);
for (Field temp : fields1){
System.out.println(temp);
}
Field a = clazz.getDeclaredField("uname");
System.out.println(a);
Method[] methods = clazz.getDeclaredMethods();
Method method1 = clazz.getDeclaredMethod("getUname",null);
Method method2 = clazz.getDeclaredMethod("setUname",String.class);
System.out.println(method1);
System.out.println(method2);
Constructor[] constructors = clazz.getDeclaredConstructors();
for (Constructor temp : constructors){
System.out.println(temp);
}
Constructor constructor1 = clazz.getDeclaredConstructor(null);
Constructor constructor2 = clazz.getDeclaredConstructor(int.class,int.class,String.class);
System.out.println(constructor1);
System.out.println(constructor2);
}
}
- 通过反射api动态的操作构造器,方法和属性
public class Demo01 {
public static void main(String[] args) throws Exception{
String path = "com.example.annotation.bean.User";
Class<?> clazz = Class.forName(path);
User user = (User) clazz.newInstance();
System.out.println(user);
Constructor c = clazz.getDeclaredConstructor(int.class,int.class,String.class);
User tsc = (User) c.newInstance(1001,18,"tsc");
System.out.println(tsc.getUname());
User dkm = (User) clazz.newInstance();
Method method = clazz.getDeclaredMethod("setUname", String.class);
method.invoke(dkm,"dkm");
System.out.println(dkm.getUname());
Field f = clazz.getDeclaredField("uname");
f.setAccessible(true);
f.set(dkm,"dsb");
System.out.println(dkm.getUname());
System.out.println(f.get(dkm));
}
}
- 反射的性能问题
尽量把setAccessible设为true,减少安全检查提高性能。 - 反射操作泛型
泛型是针对编译器的,免去了强制类型转化的麻烦,一旦编译完成泛型就会擦除。(不是重点) - 反射操作注解