反射机制中的Class类

1.类的加载过程:

   程序经过java.exe命令以后,回生成一个或多个字节码文件(.class),接着我们使用java.exe命令堆某个字节码文件解释运行,相当于将某个字节码文件加载到内存中。此过程就叫做类的加载过程。加载到内存中的类,我们就称作运行时类,此运行时类,就作为class的一个实例。

获取Class类实例的方式:

public class PersonTest  {
    //获取class实例的方式
    @Test
       public void test1() throws ClassNotFoundException{
        //方式一:调用运行时类的属性:.class
           Class clazz1 = Person.class;
           System.out.println(clazz1);
           //方式二:通过运行时类的对象,调用getClass()
           Person p1 = new Person();
           Class clazz2 = p1.getClass();
           System.out.println(clazz2);
           //方式三:调用Class的静态方法:forName(String classPath)
           Class clazz3 = Class.forName("com.flect.Person");
           System.out.println(clazz3);
        System.out.println(clazz1 == clazz3);//加载到内存中的运行时类,会缓存一段时间,在此期间,我们可以通过不同的方式来获取此运行时类
        System.out.println(clazz2 == clazz3);
           //方式四:使用类的加载器:ClassLoader
        ClassLoader classLoader = PersonTest.class.getClassLoader();
       Class clazz4 =  classLoader.loadClass("com.flect.Person");
        System.out.println(clazz4);
        System.out.println(clazz1  == clazz4 );
       }
}

那些对象可以有Class对象?

     1>class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类

      2>interface:接口

      3>[]:数组

       4>enum:枚举

        5>annotation:注解@interface

        6>primitive type:基本数据类型

        7>void

2.ClassLoader

类加载器作用:是用来把类装进内存。

引导类加载器:用c++编写的,是JVM自带的类加载器,负责java平台核心库,用来装载核心类库。该类加载器无法直接获取

扩展类加载器:负责jre/lib/ext目录下jar包或-D java.ext.dirs指定目录下的jar包装入工作库

系统类加载器:负责java-classpath或-D java.class.path所指的目录下的类与jar包装入工作,是常用的加载器。

  public void test2(){
        //对于自定义,使用系统类加载器进行加载
       ClassLoader classLoader = PersonTest.class.getClassLoader();
       System.out.println(classLoader);
       //调用系统类加载器的getParent():获取扩展类加载器
        ClassLoader classLoader1 = classLoader.getParent();
        System.out.println(classLoader1);
        //调用扩展类加载器的getParent():无法获取引导类加载器
        //引导类加载器主要负责加载java的核心类库,无法加载自定义类的
        ClassLoader classLoader2 = classLoader1.getParent();
        System.out.println(classLoader2);
    }

properties与classloader加载配置文件:

  public void test3() throws Exception{
        Properties pros = new Properties();
        //方式一:读取配置文件
        FileInputStream fis = new FileInputStream("out//jdbc.properties");
        pros.load(fis);
        //方式二:使用ClassLoader,默认识别为当前module的src下
//        ClassLoader classLoader = PersonTest.class.getClassLoader();
//        InputStream is = classLoader.getResourceAsStream("out//jdbc.properties");
//        pros.load(is);

        String user = pros.getProperty("user");
        String password = pros.getProperty("password");
        System.out.println("user:"+user+"password:"+password);
    }
}

3.通过反射创建运行时类的对象

 public void test4() throws Exception{
        //通过发射创建运行时类的对象
    Class clazz = Person.class;
    //newInstance():调用此方法,创建对应的运行时类的对象,内部调用了类的空参构造器
//    要想此方法能创建对象,运行是类必须提供空参构造器
//            空参构造器的权限是public
    Person obj  = (Person) clazz.newInstance();
    System.out.println(obj);

}

 在javabean中提供一个空参构造器,原因:

                  1.便于通过反射创建运行时类对象

                   2.便于子类继承此运行时类时,磨粉调用super()时,保证父类有此构造器

4.反射的动态性

public void test5() throws Exception{
        int num = (int)Math.random()*3+1;
        String classPath = "";
        switch (num){
            case 0:
                classPath = "java.util.Date";
                break;
            case 1:
                classPath = "java.lang.Object";
                break;
            case 2:
                classPath = "java.lang.Math";
                break;
        }
        Object obj = getInstance(classPath);
        System.out.println(obj);
    }
//    创建一个指定类的对象,classPath:指定类的全类名
    public Object getInstance(String classPath) throws Exception{
        Class clazz = Class.forName(classPath);
         return clazz.newInstance();
    }

 5.获取运行时类的完整结构

获取运行时类的带泛型的父类的泛型   genericSuper()

获取运行时类的接口        getInterfaces()

获取运行时类的父类的接口         getSuperclass().getInterfaces()

获取运行时类所在的包         clazz.getPackage()

获取运行时类声明的注解       clazz.getAnnotations()

6.调用运行时类的指定结构,属性,方法

 public void test6() throws Exception{
       Class clazz = Person.class;
       //获取运行时类的对象
        Person p = (Person) clazz.newInstance();
        //常用,获取指定变量名的属性
        Field name = clazz.getDeclaredField("name");
        name.setAccessible(true);
        //设置当前属性的值set():参数1指明设置哪个对象的属性,参数2将此属性值设置为多少
        name.set(p,100);
        //获取当前属性值
        int pid = (int) name.get(p);

        //获取某个指定的方法,getDeclaredMethod():参数一指明获取方法的名称,参数2指明获取的方法的形参列表
        Method show = clazz.getDeclaredMethod("show",String.class);
        //保证当前方法时可访问的
        show.setAccessible(true);
        //调用invoke():参数1:方法的调用者,参数2:给方法的形参赋值的实参,它的返回值即为对应类调用方法的返回值
        Object returnValue = show.invoke(p,"CHN");
        System.out.println(returnValue);
        //调用静态方法
        Method showdesc = clazz.getDeclaredMethod("showDesc");
        showdesc.setAccessible(true);
        Object returnVal = show.invoke(Person.class,"CHN");

       //获取指定的构造器:getDeclaredCocstructor()参数指明构造器的参数列表
        Constructor c clazz.getDeclaredCocstructor(String.class);
          c.setAccessible(true);
         Peerson per = (Person) c.newInstanse("Tom");
         
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值