Java 因为存在反射(Class),所以Java 也被称为"准动态语言"。
反射的优点:
1.在运行时判断任意一个对象所属的类。
2.在运行时构造任意一个类的对象。
3.在运行时获取泛型的信息。
4.在运行时调用任意一个对象变量和方法。
5.在运行时处理注解。
6.生成动态代理。
7.在运行时判断任意一个类所具有的成员变量和方法。
.......
反射每次通过forname("类")获取的相同类的实例化对象是相同的,说明其符合单例模式。
对应的例子为下:
public class Test01 {
public static void main(String[] args) {
//通过反射获取对应的类对象
//结果都为true
try {
//似乎符合单例模式
Class aClass = forName("com.ClassTest.User");
Class aClass2 = forName("com.ClassTest.User");
System.out.println(aClass == aClass2);
System.out.println(aClass.hashCode() == aClass2.hashCode());
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
class User{
private String name;
private int age;
private int id;
}
Class的常用方法
获取Class的方法
1.Class,forName
2.new "类"().getClass(
3."类".class
4.基本内置类中的包装类中都有一个TYPE属性。
且这三种获取的class的对象是相同的。获取Class的方法属于单例模式,所以只要数据类型相同,所获取的对象的实例是同一个。
例子如下:
public class Test04 {
public static void main(String[] args) {
//返回结果为: true,所以new出来的对象是否相同与数组的长度无关
//只要元素类型和维度相同,那么就是同一个Class
int[] a = new int[100];
int[] b = new int[10];
System.out.println(a.getClass().hashCode() == b.getClass().hashCode());
}
}
发生类初始化的阶段:
获取类的基本属性: 普通的get方法只能获取到public 修饰的属性和方法,如果想要获取所有方法就要在get的后面加上Declared。
invoke()
此方法用于激活方法,在括号中添加的参数为(对象, Value值)。在通过类获取方法时, 我们可以通过invoke()方法来传递参数从而激活此方法。
权限问题
当遇到权限问题时,我们可以使用:setAccessible(true),关闭安全检测,且在默认时是开起安全检测setAccessible(false)。
反射获取方法和普通获取方法两者效率对比
例子为下:
public class Test12 {
public static void Test01(){
UserT userT = new UserT();
long l = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
userT.getName();
}
long l1 = System.currentTimeMillis();
System.out.println("普通方法所使用的时间 : " + (l1 - l) + "min");
}
public static void Test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
UserT userT = new UserT();
Class c1 = userT.getClass();
Method getName = c1.getDeclaredMethod("getName", null);
getName.setAccessible(true);
long l = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(userT, null);//激活
}
long l1 = System.currentTimeMillis();
System.out.println("通过反射方法所使用的时间 : " + (l1 - l) + "min");
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
Test12.Test01();
Test12.Test02();
}
}
//UserT
public class UserT {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
执行结果为:
通过反射操作泛型