对反射的简单理解

149 阅读2分钟

起初对反射的理解是毫无概念,回看《Java核心技术》,书中明确指出了反射的各种用法以及使用事项。

先上两个代码:

public class Person {
	public  String name ;
	//定义一个私有属性
	private int 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;
	}
	@Override
	public String toString() {
		return "Person{" +"name='" + name + '\'' +", age=" + age +
				'}';
	}
	public Person() {
	}
	public Person(String name,int age) {
		this.name = name;
		this.age =age;
	}
	//定义一个私有构造
	private Person(String name) {
		this.name = name;
	}
	public void eat(){
		System.out.println("rice");
	}
	//定义私有方法
	private String study(String str){
		System.out.println("I am reading "+ str);
		return str;
	}
}

使用反射的运用;

import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Reflection {
	@Test
	public void test1(){
	    Person p1 =  new Person("Mousn",24);
	    p1.name = "Emousn";
	    p1.setAge(22);
        System.out.println(p1.toString());
        p1.eat();
    }
    @Test
    public void test2() throws Exception {
	    Class clazz = Person.class;
        Constructor constructor = clazz.getConstructor(String.class, int.class);
        Object obj = constructor.newInstance("Tom", 24);
        Person p2 = (Person) obj;
        System.out.println(p2);
//        调用属性
        Field name = clazz.getDeclaredField("name");
        name.set(p2,"Tomer");
        System.out.println(p2);
//        调用方法
        Method method = clazz.getDeclaredMethod("eat");
        method.invoke(p2);
//        调用私有构造
        Constructor constructor1 = clazz.getDeclaredConstructor(String.class);
//        开启限制
        constructor1.setAccessible(true);
        Object obj1 = constructor1.newInstance("Jerry");
        Person p3 = (Person) obj1;
        System.out.println(p3);
//        调用私有属性
        Field age = clazz.getDeclaredField("age");
        age.setAccessible(true);
        age.set(p3,12);
        System.out.println(p3);
//         获取所有属性、修饰符
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            int modifiers = field.getModifiers();
         if( Modifier.isPrivate(modifiers)) {
           System.out.println(field + "  private");
         }else if(Modifier.isPublic(modifiers)){
            System.out.println(field + "  public");
         }else if(Modifier.isProtected(modifiers)){
            System.out.println(field + "  Protected");
         }else {
           System.out.println(field + "  final");
         }
        }
//        调用私有方法
        Method study = clazz.getDeclaredMethod("study", String.class);
        study.setAccessible(true);
        String st = (String)study.invoke(p3, "book");
        System.out.println(st);
//        获取所有的方法
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method1 : methods) {
            System.out.println(method1.toString());
        }
    }
//   思考: 反射机制与面向对象中的封装性有冲突?怎么看待这两种技术?
}
输出结果
Person{name='Tom', age=24}
Person{name='Tomer', age=24}
rice
Person{name='Jerry', age=0}
Person{name='Jerry', age=12}
public java.lang.String com.example.demo.Person.name  public
private int com.example.demo.Person.age  private
I am reading book
book
public java.lang.String com.example.demo.Person.toString()
public java.lang.String com.example.demo.Person.getName()
public void com.example.demo.Person.setName(java.lang.String)
public void com.example.demo.Person.setAge(int)
public void com.example.demo.Person.eat()
private java.lang.String com.example.demo.Person.study(java.lang.String)
public int com.example.demo.Person.getAge()

那些类可以有Class对象? 外部类,内部类(成员内部类、静态内部类)、局部内部类、匿名内部类 接口、数组、枚举类、void类、注解类、基本数据类型 获得Class实例的四种方式:

    //    获取Class实例的方式
/**
 Class的实例对应一个运行时类;
 运行时类会在内存中停留,此时Class会拥有地址值,通过不同方式获得的Class实例的地址值一样(同一个运行时类)
 */
@Test
public void test3() throws Exception {
   //	    方式一:调用运行时属性.class
    Class<Person> personClass1 = Person.class;
   //	    方式二:通过运行时类的对象
    Person person = new Person();
    Class personClass2 = person.getClass();
    //      方式三:调用Class的静态方法 :forName(String classpath)   (常用)
    Class personClass3 = Class.forName("com.example.demo.Person");
    //      方式四:使用类的加载器ClassLoader
    ClassLoader classLoader = Reflection.class.getClassLoader();
    Class personClass4 = classLoader.loadClass("com.example.demo.Person");
    Class personClass4 = classLoader.loadClass("com.example.demo.Person");
    System.out.println(personClass1);//class com.example.demo.Person
    System.out.println(personClass2);//class com.example.demo.Person
    System.out.println(personClass3);//class com.example.demo.Person
    System.out.println(personClass4);//class com.example.demo.Person
}

检查类的结构:

引用于《Java核心技术》