反射原理

一、反射

1.原理:

每一个封装后的类进行编译,会生成一个字节码文件
当第一次自动使用该类的时候,JVM会把字节码文件加载到方法去区里面,并且生成该字节码文件对应的对象在堆里面。这个对象是Class类型的。
不管是哪一个字节码文件,都会省生成一个对应的对象,这些对象都有共同的特征和行为(类名,属性,构造,方法),根据共同的特征和行为向上抽取一个类,就是Cclass。
Class提供了一些很多的方法功能,对于字节码文件的对象可以调用Class类的功能,可以去获得它对应的字节码文件中的所有数据信息(类名,属性,构造,方法),这就是反射。
在这里插入图片描述

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;//所有的反射技术都来自这个包
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;

import javax.sound.midi.Soundbank;

class Student{
    private int no;
    public String name;
    public Student() {
        System.out.println("无参构造");
    }
    public Student(int no, String name) {
        this.no = no;
        this.name = name;
        System.out.println("带参构造:" + this.no + "," + this.name);
    }
    public void method() {
        System.out.println("无参方法");
    }
    public String function(String str,int num) {
        return "带参方法:" + str + ":" + num;
    }
}
public class TestStudent {

	public static void main(String[] args) throws Exception  {
		//对字节码文件进行操作(没有原码)
		//获得字节码对应的对象有三种方式
		//1.方式一(在代码中直接用上这个类了)
		//对象是Student类型
		Class<Student> c1 = Student.class;//直接通过类名.class获得
		//2.方式二(也在代码中直接用上这个类了,并且创建了一个对象)
		//对象是Student类型和Student子类型
		Class<? extends Student> c2 = new Student().getClass();//知道类名,创建一个对象,并且getClass获得
		//3.方式三 最常用(更灵活,用户可以随意传参)
		//对象类型是不确定的
		Class<?> c3 = Class.forName("cn.day0720.Student");//加载初始化一个类,必须完全限定名称(包名.类名),来获得对象
			/* 属性:Fieid
			 * 方法:Method
			 * 构造:Constructor
			 */
		//----------------属性---------
		//1.获得所有的公共的属性
		Field [] fs = c3.getFields();
		//2.获得所有类型的属性
		fs= c3.getDeclaredFields();
		for(Field f:fs){
			//4.f.getName():获得名称(属性的,构造的,方法的)
			System.out.println(f.getName());
			//5.f.getType():获得类型
			System.out.println(f.getType());
			//6.获得访问权限(f.getModifiers())
			System.out.println(Modifier.toString(f.getModifiers()));
			
			//获得单个属性
			Field f1 = c3.getDeclaredField("name");
			//创建一个实例对象
			Object obj = c1.newInstance();
			//给属性赋值
			f1.set(obj, "hello,tom");
			//访问属性值
			System.out.println(f1.get(obj));
			
			//访问private属性
			f1 = c3.getDeclaredField("no");
			f1.setAccessible(true);
			f1.set(obj, 11);
			System.out.println(f1.get(obj));
			
			//----------------方法---------
			Method [] ms = c3.getDeclaredMethods();
			for(Method m:ms){
				//获得方法名称
				System.out.println(m.getName());
				//获得返回值类型
				System.out.println(m.getReturnType());
				//获得参数类型
				System.out.println(Arrays.toString(m.getParameterTypes()));
			}
			//单个方法
			Method m = c3.getDeclaredMethod("method");
			m.invoke(obj);
			//带参数的
			m = c3.getDeclaredMethod("function", String.class,int.class);
			System.out.println(m.invoke(obj, "hello",999));
			//----------------构造---------
			Constructor [] crs = c3.getDeclaredConstructors();
			for(Constructor cr:crs){
				System.out.println(Arrays.toString(cr.getParameterTypes()));
			}
			//获得无参构造
			Constructor cr = c3.getEnclosingConstructor();
			cr.newInstance();
			//获得带参构造
			cr = c3.getConstructor(int.class,String.class);
			cr.newInstance(22,"guojing");
			
		}
		
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值