定义
动态获取类的内容与动态调用对象的属性和方法和属性的机制,叫做反射。在java运行状态中
- 对于一个给定的类(class)对象,可以获取这个类的所有属性和方法。
- 对于一个给定的对象(new xxxObject()),可以调用它的任意一个属性和方法。
缺点 -很慢
每次newInstance都会做安全检查
获取类对象的4种方式
//new 对象获取
User user = new User();
Class<? extends User> clazz1 = user.getClass();
System.out.println(clazz1);
//通过Class提供的静态方法
try {
Class clazz2 = Class.forName("com.javaDemo.reflection.User");
System.out.println(clazz2);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//通过class文件获取
Class clazz3 = User.class;
System.out.println(clazz3);
//通过类加载器
Class class4 = ReflectionDemo.class.getClassLoader().loadClass("com.javaDemo.reflection.User");
System.out.println(class4);
获取类中的属性并赋值
定义一个属性类 与 父类
public class User extends SuperEnty{
public String age;
public static String pubStaticName;
private String userName;
private static String priStaticName;
}
public class SuperEnty {
public String id;
private String sid;
}
测试类
public class OptionTest {
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
//通过反射实例化一个对象
Class<User> userClass = User.class;
User user = userClass.newInstance();
//2中获取类中属性的方法的区别
//1.
Field[] fields = userClass.getFields();
for (Field field : fields){
System.out.println(field.getModifiers() + "-" + field.getName());
}
System.out.println("----------------");
//2
Field[] declaredFields = userClass.getDeclaredFields();
for (Field field : declaredFields){
System.out.println(field.getModifiers() + "-" + field.getName());
}
}
}
返回结果
1-age
9-pubStaticName
1-id
----------------
1-age
9-pubStaticName
2-userName
10-priStaticName
Process finished with exit code 0
通过返回结果得到
- getFields() 获取的是本类与父类中 public修饰的属性。
- getDeclaredFields()获取的是本类中所有修饰的方法,但不包括父类。
那么如何获取父类中的私有属性呢
clazz.getSuperclass()获取父类的class对象,在获取属性
Class<User> clazz = User.class;
User user = clazz.newInstance();
Class superClass = clazz.getSuperclass();
Field[] fields = superClass.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
}
Field field = superClass.getDeclaredField("sid");
//私有属性需要强吻
field.setAccessible(true);
field.set(user,"1");
System.out.println(user.getSid());
操作静态属性
field.set()中对象设置为null就可以了
Class<User> clazz = User.class;
Field field = clazz.getDeclaredField("priStaticName");
field.setAccessible(true);
field.set(null,"testStaticName");
System.out.println(User.getPriStaticName());
操作方法
与Field一样
getMethod()获取本类与父类的共有方法
getDeclaredMethods()获取本类的所有的方法
//.vr
Class<User> userClass = User.class;
//获取父类与本类中的pub方法
Method[] methods = userClass.getMethods();
for (Method method : methods){
System.out.println(method.getName());
}
System.out.println("-----------");
//获取本类中所有的方法
Method[] declaredMethods = userClass.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method.getName());
}
//调用私有方法
Method method = userClass.getDeclaredMethod("setPriStaticName", String.class);
method.setAccessible(true);
method.invoke(null, "testMethod");
System.out.println(User.getPriStaticName());
构造器
与上面一样
getConstructors() 只能获取本类的公共的构造器
getDeclaredConstructors() 获取本类的所有的构造器
Class<User> userClass = User.class;
//获取本类与父类的构造方法
Constructor<?>[] constructors = userClass.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor.toString());
}
System.out.println("--------");
//获取本类所有的构造方法
Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();
for (Constructor constructor : declaredConstructors) {
System.out.println(constructor.toString());
}
//使用
//1. newInstance 源码就是调用的默认的null构造器创建对象
User user = userClass.newInstance();
//2 带参数构造器
Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class, String.class);
declaredConstructor.setAccessible(true);
User user1 = declaredConstructor.newInstance("test", "test");
System.out.println(user1.toString());
public class User extends SuperEnty{
public User() {
}
private User(String age,String userName) {
this.age = age;
this.userName = userName;
}
public String age;
public static String pubStaticName;
private String userName;
private static String priStaticName;
@Override
public String toString() {
return "User{" +
"age='" + age + '\'' +
", userName='" + userName + '\'' +
", id='" + id + '\'' +
'}';
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public static String getPubStaticName() {
return pubStaticName;
}
public static void setPubStaticName(String pubStaticName) {
User.pubStaticName = pubStaticName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public static String getPriStaticName() {
return priStaticName;
}
public static void setPriStaticName(String priStaticName) {
User.priStaticName = priStaticName;
}
}
通过反射破坏单例模式
单例模式之所以在系统中只存在一个对象,是因为构造器私有了,不能通过new的方式创建出来,只能通过暴露出来的静态方法来获取对象。但是反射是可以获取到私有构造器从而创建对象的从而破坏了单例模式全局唯一的特性。
单例模式(不考虑多线程环境)
public class SimpleTest {
private static SimpleTest simpleTest;
private SimpleTest() {
}
public static SimpleTest getInstance() {
if (null == simpleTest) {
return new SimpleTest();
}
return simpleTest;
}
//每一次都是返回同一个对象
public static void main(String[] args) {
SimpleTest simpleTest1 = SimpleTest.getInstance();
SimpleTest simpleTest2 = SimpleTest.getInstance();
SimpleTest simpleTest3 = SimpleTest.getInstance();
System.out.println(simpleTest1);
System.out.println(simpleTest2);
System.out.println(simpleTest3);
}
}
结果
com.javaDemo.reflection.SimpleTest@2503dbd3
com.javaDemo.reflection.SimpleTest@2503dbd3
com.javaDemo.reflection.SimpleTest@2503dbd3
反射获取私有构造器生成对象,从而破坏单例
System.out.println("_______________");
Class<SimpleTest> simpleTestClass = SimpleTest.class;
//获取默认的构造器
Constructor<SimpleTest> declaredConstructor = simpleTestClass.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
SimpleTest simpleTest = declaredConstructor.newInstance();
System.out.println(simpleTest);
如何防止反射破坏单例
private SimpleTest() {
if (null != simpleTest) {
throw new RuntimeException("已经存在不可以再创建");
}
}
在私有构造器中加入判断,如果已经实例化那么不可以通过任何的方式再次调用构造器创建对象。