目录
一、什么是反射
反射是java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法。
二、类类
举例:
所有狗 狗类 Dog 狗对象 旺财
所有猫 猫类 Cat 猫对象 肥波
所有类 类类 java.lang.Class 类对象 特定类
三、反射的三种类对象的获取方式
一切反射相关的代码都从获得类对象开始。
例:我有一个Student学生类。
第一种:Class.forName(完整类名)
// 通过完整类名/权限定名(包名 + 类名)找到对应的类对象(例:获取学生类)
Class c = Class.forName("com.zking.test.Student");
// c现在就是学生对象,实例化学生对象(强转)
Student s = (Student)c.newInstance();
第二种:类名.class
Class<Student> c = Student.class;
// 调用默认的无参构造方法进行对象的实例化
c.newInstance();
第三种:对象.getClass()
Student s = new Student();
Class c = s.getClass();// 不需要再c.newInstance(),因为new学生对象已经调用了无参的构造方法了
四、反射三大作用(java.lang.reflect.*)
-
4.1.实例化对象/构造方法 getConstructor
首先,获取类对象
Class c = Class.forName("com.zking.test.Student");
1.无参的构造方法
方法:
public Student() {
super();
System.out.println("调用无参构造方法创建了一个学生对象");
}
调用:
Constructor con = c.getConstructor();// 不写参数,调用的是无参的构造方法
// 调用(实例化)运行
con.newInstance();
2.带一个参数的构造方法(数据类型.class)
方法:
public Student(String sid) {
super();
this.sid = sid;
System.out.println("调用带一个参数的构造方法创建了一个学生对象");
}
调用:
// 获取带参的构造方法
Constructor con = c.getConstructor(String.class);
// 调用运行
con.newInstance("WQ");
3.带两个参数的构造方法(数据类型.class, 数据类型.class)
方法:
public Student(String sid, String sname) {
super();
this.sid = sid;
this.sname = sname;
System.out.println("调用带两个参数的构造方法创建了一个学生对象");
}
调用:
// 获取带参的构造方法
Constructor con = c.getConstructor(String.class, String.class);
// 调用运行
con.newInstance("G2101","WQ");
调用带三个参数(数据类型.class, 数据类型.class, 数据类型.class)...以此类推。
4.私有的构造方法 + Declared
方法:
@SuppressWarnings("unused")
private Student(Integer age) {
System.out.println("调用Student类私有的构造方法创建一个学生对象");
this.age = age;
}
调用:
Constructor con = c.getDeclaredConstructor(Integer.class);
// 授权运行
con.setAccessible(true);
// 调用运行
con.newInstance(1);
补充:
看到传参带三个点的方法,代表这个参数是由0(可以不写)或N(想写多少个就写多少个)个组成的。
-
4.2.动态调用方法 getMethod
首先,获取类对象
Class c = Class.forName("com.zking.test.Student");
实例化对象
Object o = c.newInstance();// 实例化对象(相当于调用类对象里面的方法)
1.不带参的方法
方法:
public void hello() {
System.out.println("你好!我是" + this.sname);
}
调用:
Method m = c.getMethod("hello");// 该方法不在类对象里面
// 运行(必须要运行类对象里面的方法)
m.invoke(o);
2.带参的方法(方法名, 参数类型)
方法:
public void hello(String name) {
System.out.println(name + "你好!我是" + this.sname);
}
调用:
Method m = c.getMethod("hello", String.class);
m.invoke(o, "WQ");
3.私有的方法 + Declared
方法:
@SuppressWarnings("unused")
private Integer add(Integer a, Integer b) {
return new Integer(a.intValue() + b.intValue());
}
调用:
Method m = c.getDeclaredMethod("add", Integer.class, Integer.class);
// 授权运行
m.setAccessible(true);
// 运行
System.out.println(m.invoke(o, 1,1));// 因为这个方法有返回值,没有输出效果,所以要自行输出
-
4.3.读写属性 getField
获取类对象
Class c = Class.forName("com.zking.test.Student");
Student s = (Student)c.newInstance();
1.公开的属性
属性:
// 公开的
public Integer age;
调用:
Field f = c.getField("age");
f.set(s, 20);
// 输出
System.out.println(s.getAge());
2.私有的属性 + Declared
属性:
// 私有的
private String sname;
调用:
Field f = c.getDeclaredField("sname");
// 授权运行
f.setAccessible(true);
f.set(s, "WQ");
// 输出
System.out.println(s.getSname());
五、获取访问修饰符 getModifiers
例:以获取属性的修饰符为例。
获取属性:
// 私有的
private String sname;
// 公开的
public Integer age;
// 默认的/友好的friendly/default
String remarks;
// 受保护的
protected String address;
// 静态的
static String sex;
// 常量:不能更改,必须初始化
final Integer tel = 123;
private static final String URL = "www.baidu.com";
调用:
// 获取属性
Field f = c.getDeclaredField("sname");
Field f2 = c.getField("age");
Field f3 = c.getDeclaredField("remarks");
Field f4 = c.getDeclaredField("address");
Field f5 = c.getDeclaredField("sex");
Field f6 = c.getDeclaredField("tel");
Field f7 = c.getDeclaredField("URL");
int pri = f.getModifiers();
int pub = f2.getModifiers();
int def = f3.getModifiers();// friendly
int pro = f4.getModifiers();
int sta = f5.getModifiers();
int fin = f6.getModifiers();
int URL = f7.getModifiers();
System.out.println("private:" + pri);
System.out.println("public:" + pub);
System.out.println("default:" + def);
System.out.println("private:" + pro);
System.out.println("static:" + sta);
System.out.println("final:" + fin);
System.out.println("URL:" + URL);
输出:
完。