通过反射动态创建对象
创建类的对象:调用Class对象的newInstance()方法
- 类必须要有一个无参构造器
- 类的访问权限需要足够
package com.yuanyu.annandre;
//通过反射动态获取对象
public class Test10 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//获取Class对象
Class c1 = Class.forName("com.yuanyu.annandre.User");
User user = (User) c1.newInstance(); //本质调用类的无参构造器
System.out.println(user);
}
}
程序运行结果:
User{name='null', id=0, age=0}
若把User类中的无参构造器删除则:
若类中没有无参构造器,则可以
- 通过getDeclaredConstructor(Class ... parameterTypes)获得本类指定形参类型的构造器
- 向构造器的形参中传递 一个对象数组进去,里面包含了构造器中所需的各个参数
- 通过Constructor实例化对象
package com.yuanyu.annandre;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//通过反射动态获取对象
public class Test10 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获取Class对象
Class c1 = Class.forName("com.yuanyu.annandre.User");
//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User user2 = (User) constructor.newInstance("原语", 01, 21);
System.out.println(user2);
//通过反射调用普通方法
User user3 = (User) c1.newInstance();
Method setName = c1.getDeclaredMethod("setName", String.class);
setName.invoke(user3,"上弦"); //invoke(对象,“方法的值”)激活
System.out.println(user3.getName());
//通过反射操作一个属性
User user4 = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有属性,需要关闭程序的安全检测,通过属性的setAccessible(true)关闭
name.setAccessible(true);
name.set(user4,"濔昫");
System.out.println(user4.getName());
}
}
若未关闭程序的安全检测则:
程序运行结果:
User{name='原语', id=1, age=21}
上弦
濔昫
Method、Field、Constructor对象都有setAccessible()方法
setAccessible作用是启动和禁用访问安全检查的开关(true则表示取消Java语言访问检查)
- 提高反射的效率
- 使得原本无法访问的私有成员也可以访问
性能测试分析:
package com.yuanyu.annandre;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//测试性能分析
public class Test11 {
//普通方法调用
public static void test1(){
User user = new User();
long startime = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
user.getName();
}
long endtime = System.currentTimeMillis();
System.out.println("普通方式执行时间"+(endtime-startime)+"ms");
}
//反射方法调用
public static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
Class c1=User.class;
User user= (User) c1.newInstance();
Method getName = c1.getDeclaredMethod("setName", String.class);
long startime = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
getName.invoke(user,"yuanyu");
}
long endtime = System.currentTimeMillis();
System.out.println("反射方式执行时间" + (endtime - startime) + "ms");
}
//反射方法调用(关闭检测)
public static void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
Class c1=User.class;
User user= (User) c1.newInstance();
Method getName = c1.getDeclaredMethod("setName", String.class);
getName.setAccessible(true);
long startime = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
getName.invoke(user,"yuanyu");
}
long endtime = System.currentTimeMillis();
System.out.println("反射方式(关闭检测)执行时间" + (endtime - startime) + "ms");
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
test1();
test2();
test3();
}
}
程序运行结果: