反射, 获取Class, 创建对象, 调用方法

反射的概述


  1. Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
    框架 = 反射 + 注解 + 设计模式。
  2. 反射机制能提供的功能:
    在这里插入图片描述

Class类理解与获取Class类实例


Class类理解

  1. 类的加载过程:程序经过javac.exe命令以后,会生成一个或多个字节码文件(.class结尾)。接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。此过程就称为类的加载。加载到内存中的类,我们就称为运行时类,此运行时类,就作为Class的一个实例。
  2. 换句话说,Class的实例就对应着一个运行时类。
  3. 加载到内存中的运行时类,会缓存一定的时间。在此时间之内,我们可以通过不同的方式
    来获取此运行时类。

获取Class类实例的四种方法

public class GetClass {
	public static void main(String[] args) throws ClassNotFoundException {
		//方法一:调用运行时类的属性:.class  (缺点:写死)
		Class c1 = Person.class;
		System.out.println(c1);  //class com.xd.Person  即class加全限定类名
		
		//方法二:调用运行时类对象,调用getClass()
		Person p = new Person();
		Class c2 = p.getClass();
		System.out.println(c2);
		
		//方法三:调用Class的静态方法:froName(String classPath)  (用的多)
		Class c3 = Class.forName("Test.Person");
		System.out.println(c3);
		
		//方法四:使用类加载器:ClassLoader
		ClassLoader classLoader = GetClass.class.getClassLoader();
		Class c4 = classLoader.loadClass("Test.Person");
		System.out.println(c4);
		
		System.out.println(c1==c2); //true
		System.out.println(c1==c3);  //true
	}
}

ClassLoader类


类加载器作用

  1. 将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。
  2. 类缓存:标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象。

使用Classloader加载配置文件

public class ClassLoaderProperty {	
	public static void main(String[] args) throws IOException {		
	
		Properties pros = new Properties();
		
		InputStream in = ClassLoaderProperty.class.getClassLoader().getResourceAsStream("jdbc.properties");
		pros.load(in);	
		System.out.println(pros.getProperty("name"));  //熊大
	}
}

配置文件 jdbc.properties

name = 熊大

创建运行时类对象

Class clazz = Person.class;
//newInstance():调用此方法,创建对应的运行时类的对象。内部调用了运行时类的空参的构造器。
Person p= (Person)clazz.newInstance();

调用指定的构造器:

@Test
public void testConstructor() throws Exception {
    Class clazz = Person.class;
    //private Person(String name)
   // 1.获取指定的构造器  getDeclaredConstructor():参数:指明构造器的参数列表
   
    Constructor constructor = clazz.getDeclaredConstructor(String.class);

    //2.保证此构造器是可访问的  构造器是public权限跳过此步骤
    constructor.setAccessible(true);

    //3.调用此构造器创建运行时类的对象
    Person per = (Person) constructor.newInstance("Tom");
}

调用指定的属性

    //1. getDeclaredField(String fieldName):获取运行时类中指定变量名的属性
    Field name = clazz.getDeclaredField("name");

    //2.保证当前属性是可访问的
    name.setAccessible(true);
    //3.获取、设置指定对象的此属性值
    name.set(p,"Tom");

    System.out.println(name.get(p));
}

调用指定的方法

         //1.获取指定的某个方法
         //getDeclaredMethod():参数1 :指明获取的方法的名称  参数2:指明获取的方法的形参列表,空参不写
        Method show = clazz.getDeclaredMethod("show", String.class);
        
        //2.保证当前方法是可访问的,若public权限跳过
        show.setAccessible(true);

         //3. 调用方法的invoke():参数1:方法的调用者  参数2:给方法形参赋值的实参
         //invoke()的返回值即为对应类中调用的方法的返回值。
        Object returnValue = show.invoke(p,"CHN"); 
        System.out.println(returnValue);

        System.out.println("*************如何调用静态方法*****************");

        // private static void showDesc()

        Method showDesc = clazz.getDeclaredMethod("showDesc");
        showDesc.setAccessible(true);
        //如果调用的运行时类中的方法没返回值,则此invoke()返回null
//        Object returnVal = showDesc.invoke(null);
        Object returnVal = showDesc.invoke(Person.class);
        System.out.println(returnVal);//null
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值