如何理解反射?

反射:
程序运行过程中,可以获取到类的构造方法,成员变量(包括私有的)方法,对象使用类成员,我们把获取类成员和对象调用类成员机制,叫反射。

Class:封装了大量的方法,通过方法可以获取到构造方法,方法,成员变量
Class类的对象——.class文件 只加载一次 唯一的标识:包名.类名

获取Class类的对象3种方法:

  • 对象.getClass()

  • 类名.class

  • forName(“包名.类名”)

//获取Class类的对象3种方法
	public static void test1() throws ClassNotFoundException {
		//通过 对象.getClass()
		Class<? extends Student> clazz=new Student().getClass();
		//通过 类名.class
		Class<Student> clazz1=Student.class;
		System.out.println(clazz==clazz1);
	    //forame(”包名+类名“)
		Class clazz3=Class.forName("day_18.Student");
		System.out.println(clazz==clazz3);
	}

结果:

true
true

由上面的运行结果可以看出,内存中加载的字节码文件只有一个,所以获取的Class对象都是同一个

获取和使用构造方法

//获取和使用构造方法
	public static void test2() {
		Class<Student> clazz1=Student.class;
		@SuppressWarnings("rawtypes")
		Constructor[] constructors=clazz1.getDeclaredConstructors();
		for(Constructor<?> construct : constructors) {
			//1  -  public  
			//获取访问修饰符
			System.out.println(construct.getModifiers()+"->"+Modifier.toString(construct.getModifiers()));
			System.out.println(construct.getName());
			//返回参数列表的Class类型的数组
			Class[] pClazz=construct.getParameterTypes();
			for(Class c:pClazz) {
				System.out.println(c.getName());
			}
			System.out.println("=============");
		}
	}
public class Student {
	public String name;
	private int age;
	public Student() {
		
	}
    public Student(String name) {
		this.name=name;
	}
    private Student(String name,int age) {//String.class,Integer.class
    	this.name=name;
    	this.age=age;
	}
    public void eat(String food) {
    	System.out.println(name+"吃"+food);
    }
    public void sleep() {
    	System.out.println("睡觉");
    }
    private int getAge() {
    	return age;
    }
    private void setAge() {
    	this.age=age;
    }

}

结果:

2->private
day_18.Student
java.lang.String
int
=============
1->public
day_18.Student
java.lang.String
=============
1->public
day_18.Student
=============

获取无参的构造方法,创建对象

//获取无参的构造方法,创建对象
	public static void test2_1() throws Exception {
		Class clazz=Student.class;
		//得到无参的构造方法对象
		//Constructor con=clazz.getDeclaredConstructor();
		//使用无参构造方法的对象创建对象
		//Student stu=(Student) con.newInstance();//new Student();
		//调用无参的构造方法创建对象,不用获取Constructor对象,可以使用下面的
		//方式直接由Class类型的对象调用
		Student stu=(Student) clazz.newInstance();
		stu.name="张三";
		stu.eat("饺子");
	}

结果:

张三吃饺子

获取带参的构造方法,创建对象

//获取带参的构造方法,创建对象
		public static void test2_2() throws Exception {
			Class<Student> clazz=Student.class;
			//获取带String类型参数的构造方法的对象
			Constructor construct=clazz.getDeclaredConstructor(new Class[]{String.class});
			//使用构造方法创建对象
			Student stu =(Student) construct.newInstance(new Object[]{"李四"});
			stu.eat("芒果");
		}
		//获取私有带参的构造方法,创建对象
				public static void test2_3() throws Exception {
					Class<Student> clazz=Student.class;
					//获取带2个参数的构造方法的对象
					Constructor construct=clazz.getDeclaredConstructor(new Class[]{String.class,int.class});
					//设置私有的构造方法的可访问性
					construct.setAccessible(true);
					//使用构造方法创建对象
					Student stu =(Student) construct.newInstance(new Object[]{"李四",18});
					stu.eat("芒果");
				}
李四吃芒果

工具方法
Method[] getDeclaredMethods();获取本类的所有的方法
Method[] getMethods():获取非私有的方法(父类)

获取和使用功能方法(返回的是非私有的方法)

//getDeclaredMethods获取本类的方法
//getMethods()获取本类及父类的非私有的方法
public static void test3(){
	Class<Student> clazz = Student.class;
	//Method[] methods = clazz.getDeclaredMethods();
	//getDeclaredMethods()获取本类的所有方法
	Method[] methods = clazz.getMethods();
	for(Method m : methods){
		System.out.println(m.getName());
		System.out.println(m.getReturnType());
		System.out.println("=======================");
	}
}
public static void test3_1() throws Exception{
	Class<Student> clazz = Student.class;
	Student stu = clazz.newInstance();
	//获取sleep方法对象(无参)
	Method method = clazz.getDeclaredMethod("sleep");
	//使用方法
	method.invoke(stu);//stu.sleep();
	//练习:获取eat方法,并调用(有参)
	Method methodEat = clazz.getDeclaredMethod("eat",
			new Class[]{String.class});
	methodEat.invoke(stu,new Object[]{"馒头"});
	//    获取setAge/getAge方法并调用(私有)
	Method methodSet = clazz.getDeclaredMethod("setAge",
			new Class[]{int.class});
	methodSet.setAccessible(true);
	methodSet.invoke(stu,new Object[]{18});
	Method methodGet = clazz.getDeclaredMethod("getAge");
	methodGet.setAccessible(true);
	System.out.println(methodGet.invoke(stu));
}

获取和使用成员变量

//4.获取和使用成员变量
public static void test4() throws Exception{
	Class<Student> clazz = Student.class;
	Student stu = clazz.newInstance();
	Field[] fields = clazz.getDeclaredFields();
	for(Field f : fields){
		System.out.println(f.getName());
	}
}
public static void test4_1()throws Exception{
	Class<Student> clazz = Student.class;    
	Student stu = clazz.newInstance();
	Field field = clazz.getDeclaredField("name");
	field.set(stu, "王五");//stu.name = "wangwu"
	System.out.println(field.get(stu));  //stu.name
	
	//练习:age成员变量赋值(私有)
	Field f2=clazz.getDeclaredField("age");
	f2.setAccessible(true);
	f2.set(stu, 12);
	System.out.println(f2.get(stu));
}

练习:

public class GJC {
	public void zuo() {
		System.out.println("看风景");
	}

}
public class DDC {
	public void qi() {
		System.out.println("兜风hhhhh");
	}


}
test.properties

className=day_18.GJC
methodName=zuo

Properties p=new Properties();
		p.load(new FileInputStream("test.properties"));
		
		String className=p.getProperty("className");
		String methodName=p.getProperty("methodName");
		Class clazz=Class.forName(className);
		Object obj=clazz.newInstance();
		Method method=clazz.getDeclaredMethod(methodName);
		method.invoke(obj);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值