反射
反射概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
获取Class对象
如何找到对应的Class<?>模型对象 一共有三种方法
- 1.通过类名
- 2.通过对象名
- 3.通过全路径
public static void main(String[] args) throws Exception {
//1. 对象名.getClass();
Person p = new Person();
Class clazz = p.getClass();
//2. p.load(类名.class.getClassLoader().getResourceAsStream("config.properties");
//类名.class
Class clazz2 = Person.class;
//3. Class.forName(全类名);
Class clazz3 = Class.forName("reflect.Person");
System.out.println(clazz == clazz2);//同一个类的Class对象只有一个
System.out.println(clazz2 == clazz3);
}
反射获取构造方法
public Constructor[] getConstructors(); 获取所有用public修饰的构造方法
public Constructor getConstructor(Class…args); 获取单个的用public修饰构造方法
public Constructor[] getDeclaredConstructors (); 获取所有的构造方法
public Constructor getDeclaredConstructor (Class…args); 获取单个构造方法
/**
* 反射获取构造方法
*/
public class ReflectDemo2 {
public static void main(String[] args) {
try {
//1. 得到Class对象
Class clazz = Class.forName("reflect.Person");
//2. 获取构造方法
//只能获取用public修饰的构造方法
Constructor[] cs = clazz.getConstructors();
for (Constructor c : cs) {
System.out.println(c);
}
System.out.println("--------");
Constructor[] ds = clazz.getDeclaredConstructors();
for (Constructor c : ds) {
System.out.println(c);
}
System.out.println("--------");
//得到单个的构造方法:
Constructor c1 = clazz.getConstructor(String.class,int.class);
System.out.println(c1);
System.out.println("--------");
//得到单个的构造方法:
Constructor c2 = clazz.getConstructor();//null, 无参
System.out.println(c2);
System.out.println("--------");
//得到单个的构造方法: 用public修饰
// Constructor c3 = clazz.getConstructor(String.class);//java.lang.NoSuchMethodException:
// System.out.println(c3);
Constructor c4 =clazz.getDeclaredConstructor(String.class);
System.out.println(c4);
System.out.println("----");
Constructor c5 =clazz.getDeclaredConstructor(int.class);
//构造方法创建对象
Object o = c1.newInstance("Jack",45);
System.out.println(o);
Object o2 = c4.newInstance("Rose");
System.out.println(o2);
//默认无法访问私有构造方法,如果非要访问,需要暴力破解
c5.setAccessible(true);
Object o3 = c5.newInstance(14);//Class
System.out.println(o3);
} catch (Exception e) {
e.printStackTrace();
}
}
}
反射获取成员变量
Field[] fs getFields
Field[] fs getDeclaredFields
Field getField
Field getDeclaredField
/**
* 反射获取成员变量
*/
public class ReflectDemo3 {
public static void main(String[] args) {
try {
//1. Class
Class clazz = Class.forName("reflect.Person");
//2. 获取变量:
//只能获取用public修饰的变量, 包括父类的
Field[] fs = clazz.getFields();
for (Field f : fs) {
System.out.println(f);
}
System.out.println("------");
Field[] dfs = clazz.getDeclaredFields();//得到所有
for (Field f : dfs) {
System.out.println(f);
}
//得到单个的变量
Field f1 = clazz.getField("name");//public
//Field f2 = clazz.getField("age");//不是public
Field f3 = clazz.getDeclaredField("age");
Field f4 = clazz.getDeclaredField("gender");
//给对象中的变量赋值: p.name = "zhaangsan"
//创建对象
Object o = clazz.newInstance();//调用无参构造,保证类中有无参构造
f1.set(o, "张三");// 把o对象中的名字设置为张三 o.name="张三"
//私有默认访问不了,暴力破解
f3.setAccessible(true);
f3.set(o, 18);
f4.set(o, '男');
//给静态属性赋值
Field f5 = clazz.getDeclaredField("a");
f5.set(null, 123);//把 a变量设置成了123
System.out.println(o);
} catch (Exception e) {
e.printStackTrace();
}
}
}
反射获取成员方法
Method[] getMethods
Method [] getDeclaredMethods
Method getMethod
Method getDeclaredMethod
/**
* 使用反射获取方法
*/
public class ReflectDemo4 {
public static void main(String[] args) {
try {
//1. Class
Class clazz = Class.forName("reflect.Person");
Method[] ms = clazz.getMethods();// 得到用public修饰的方法(自己类中和父类中)
for (Method m : ms) {
System.out.println(m);
}
//本类中所有的方法,不包含父类中的方法
Method[] ds = clazz.getDeclaredMethods();
System.out.println("-----");
for (Method d : ds) {
System.out.println(d);
}
//获取单个"
Method m = clazz.getMethod("test1",null);
System.out.println(m);
Method m2 = clazz.getDeclaredMethod("test2", null);
//调用方法,需要有一个对象
Object o = clazz.newInstance();
Object re = m.invoke(o, null);
m2.setAccessible(true);
m2.invoke(o, null);
//调用一个有参数有返回值的方法
Method m3 = clazz.getDeclaredMethod("getSum", int.class,int.class);
Object sum = m3.invoke(o, 100,200);
System.out.println(sum);
} catch (Exception e) {
e.printStackTrace();
}
}
}
反射练习
ArrayList的一个对象,我想在这个集合中添加一个整型数据,如何实现呢?
/**
* ArrayList<String>的一个对象,我想在这个集合中添加一个整型数据,如何实现呢?
*/
public class ReflectTest {
public static void main(String[] args) {
try {
ArrayList<String> list = new ArrayList<>();
list.add("abc");
//填整数: 泛型只在编译时期有效
//1. 先获取Class对象: ArrayList 的对象
Class clazz = list.getClass();
//2. 获取add方法 Object
Method m = clazz.getMethod("add", Object.class);
//3. 调用add方法,用哪个对象调用? list调用
m.invoke(list, 12);
m.invoke(list, 12.5);
System.out.println(list);
} catch (Exception e) {
e.printStackTrace();
}
}
}
反射解耦合
程序的耦合
- 耦合:程序间的依赖关系
- 包括:
- 类之间的依赖
- 方法间的依赖
- 包括:
- 解耦:降低程序间的依赖关系
- 实际开发中应该做到:
- 编译期不依赖,运行时才依赖
- 解耦的思路:
- 第一步:通过读取配置文件来获取要创建的对象全限定类名
- 第二步:使用反射来创建对象,而避免使用
new
关键字
public interface Teachable {
public void teach();
}
public class Teacher implements Teachable {
@Override
public void teach() {
System.out.println("教的挺水........");
}
}
public class SuperTeacher implements Teachable{
@Override
public void teach() {
System.out.println("教的贼6......");
}
}
public class TeacherTest {
public static void main(String[] args) {
/*Teachable t = new Teacher();
t.teach();*/
try {
Properties p = new Properties();
p.load(TeacherTest.class.getClassLoader().getResourceAsStream("config.properties"));
String value = p.getProperty("class.name");//全类名
Class clazz = Class.forName(value);
Object o = clazz.newInstance();
Teachable tt = (Teachable)o;//
tt.teach();
} catch (Exception e) {
e.printStackTrace();
}
}
}