反射
反射是发生在程序运行期间的行为,在一个类加载到内存时,就会存在一个当前类的Class对象,Class对象是唯一的,不变的,包含此类中的所用内容,所以反射的源头就是Class对象。反射大量运用在框架,组件,服务器等的底层。
1. 获取Class
获取Class对象有以下三种方式:
- 类名.class
- 对象.getClass()
- Class.forName(“包名.类名”)
代码:
import java.io.IOException;
import java.util.Properties;
public class ReflectDemo01 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//获取Class对象的三种方式
//1. 类名.class
Class<String> c1 = String.class;
System.out.println(c1);//class java.lang.String
//2. 对象.getClass
String str = "";
Class c2 = str.getClass();
System.out.println(c2);//class java.lang.String
//3. Class.forName("包名.类名") 推荐
Properties pro = new Properties();
pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("classtest.properties"));
Class c3 = Class.forName(pro.getProperty("classname"));
System.out.println(c3);//class java.lang.Math
//基本数据类型获取类(2种方式)
//1. 基本数据类型.class
Class c4 = int.class;
//2. 基本数据类型包装类.TYPE
Class c5 = Integer.TYPE;
System.out.println(c4);//int
System.out.println(c5);//int
System.out.println(c4==c5);//true
}
}
配置文件:
classname=java.lang.Math
2. 创建对象
通过反射创建对象有以下两种方式:
- 使用Class类的newInstance()方法,该方法已过时
- 获取指定的构造器,使用指定的构造器创建对象,并为对象初始化信息
代码:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ReflectDemo02 {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//获取Person类型的Class对象
Class<Person> c1 = Person.class;
System.out.println(c1);
//newInstance() 被弃用不推荐
Person p1 = c1.newInstance();
System.out.println(p1);
//getConstructor(类<?>... parameterTypes) 返回一个构造器对象,该对象反映此类对象所表示的类的指定公共构造函数
Constructor<Person> con1 = c1.getConstructor(int.class,String.class,int.class);
Person p2 = con1.newInstance(102,"赵六",24);
System.out.println(p2);
//getConstructors() 返回一个构造器对象,该对象反映此类对象所表示的类的指定公共构造函数
Constructor[] con2 = c1.getConstructors();
for (Constructor c:con2){
System.out.println(c);
}
Person p3 = (Person) con2[0].newInstance(101,"李四",25);
System.out.println(p3);
//getDeclaredConstructor(类<?>... parameterTypes) 返回一个构造器对象,该对象反映此类对象所表示的类或接口的指定构造函数
Constructor<Person> con3 = c1.getDeclaredConstructor(String.class);
//忽略权限
con3.setAccessible(true);
Person p4 = con3.newInstance("张三");
System.out.println(p4);
//getDeclaredConstructors() 返回构造器对象的数组,构造器对象反映由此类对象表示的类声明的所有构造函数
Constructor[] con4 = c1.getDeclaredConstructors();
for (Constructor c:con4){
System.out.println(c);
}
//忽略权限
con4[1].setAccessible(true);
Person p5 = (Person) con4[1].newInstance("王五");
System.out.println(p5);
}
}
//定义Person类
class Person{
private int id;
private String name;
private int age;
public Person() {
}
private Person(String name) {
this.name = name;
}
public Person(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
3. 操作属性
代码:
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class ReflectDemo03 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
//Class对象
Class<Student> cls = Student.class;
//对象
Student s1 = cls.getConstructor(String.class,int.class).newInstance("小明",15);
System.out.println(s1);//Student{name='小明', age=15}
//获取每一个类型的属性
Field field = cls.getDeclaredField("name");
//忽略权限
field.setAccessible(true);
//操作属性
field.set(s1,"小红");
System.out.println(s1);//Student{name='小红', age=15}
}
}
//定义Student类
class Student{
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
4. 操作方法
代码:
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
public class ReflectDemo04 {
public static void main(String[] args) throws Exception {
testMethod(Student.class);
}
public static void testMethod(Class<Student> cls) throws Exception {
//可以获取到从父类继承的方法,要求是公共的
Method[] method1 = cls.getMethods();
System.out.println(Arrays.toString(method1));
//所有权限,但是只能获取本类中有的
Method[] method2 = cls.getDeclaredMethods();
System.out.println(Arrays.toString(method2));
//获取指定的一个方法
Method method3 = cls.getDeclaredMethod("getName");
//创建一个对象
Student stu = new Student("张三",18);
//操作
System.out.println(method3.invoke(stu));
Method method4 = cls.getDeclaredMethod("test",int.class,String.class);
//设置权限
method4.setAccessible(true);
System.out.println(method4.invoke(stu,10,"haha"));
Type[] arr = method4.getGenericParameterTypes();
System.out.println(Arrays.toString(arr));
for(Type t:arr){
System.out.println(t.getTypeName());
}
}
}
//定义Student类
class Student{
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = 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;
}
private void test(int i,String s){
System.out.println("测试方法");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}