Java反射机制

目录

1.反射机制

2..反射带来的问题

3.关于java.lang.Class的理解

4.获取Class实例的方式

5.类的加载器

6.使用类的加载器获取配置文件信息的方法

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

8.获取属性结构

9.获取方法

10.获取构造器

11.获取运行时类的父类

12.调用运行类中指定的结构:属性、方法、构造器(重点)

一、调用指定的属性:(掌握)

二、调用指定的方法:(掌握)

三、如何调用运行时类的构造器

13.反射的应用


1.反射机制

定义:动态获取运行时类的属性或调用运行时类的方法叫做反射机制

1.体现了动态性,是动态语言的体现

2.动态语言:在运行时代码可以根据某些条件改变自身结构。

2..反射带来的问题

1.反射机制与面向对象中的封装性是否矛盾?

因为通过反射能够调用私有的属性、方法、构造器;但是不矛盾;封装性是建议你不要调用私有的,该有的功能都已经公开了;反射只是能够调用私有的,调不调看你自己。

2.开发中使用直接new的方式还是反射?

大部分还是new的方式;用反射时-动态性

3.关于java.lang.Class的理解

1.类的加载过程:程序经过javac.exe后,生成一个或多个字节码文件(.class)。接着使用java.exe对字节码文件进行解释运行,相当于把某个字节码文件加载到内存中。此过程称为类的加载。加载到内存中的类,就称为运行时类,此运行时类,就作为Class的一个实例。

2.Class的实例对应着一个运行时类。

3.加载到内存中的运行时类,会缓存一定的时间,在此时间内,可以获取此运行时类。

4.只要数组的元素类型和维度一样,就是同一个Class

5.Class类的对象可以是加载在内存中的各种对象

4.获取Class实例的方式

1.方式一:调用运行时类的属性:.class

2.通过运行时类的对象,getclass

3.调用Class静态方法:forName(classPath);一般用方式三

4.了解:使用类的加载器,ClassLoader

//获取Class实例的方式
@Test
public void test1() throws Exception {

    //1.调用.class
    Class clazz1 = Person.class;
    System.out.println(clazz1);

    //2.通过运行时类的对象
    Person p = new Person();
    Class clazz2 = p.getClass();
    System.out.println(clazz2);

    //3.调用Class静态方法:forName(classPath)
    Class clazz3 = Class.forName("com.gz.java.utility.Person");
    System.out.println(clazz3);

    //4.使用类的加载器
    ClassLoader classLoader = ClassTest.class.getClassLoader();
    Class clazz4 = classLoader.loadClass("com.gz.java.utility.Person");
    System.out.println(clazz4);

}

5.类的加载器

1.作用:将类加载到内存当中。

2.对于自定义类,使用系统类加载器

3.调用系统类加载器的getParent:获取扩展类加载器

4.而引导类加载器只用来加载Java的核心类库,无法加载自定义类

6.使用类的加载器获取配置文件信息的方法

  @Test
    public void test1() throws IOException {

        Properties p = new Properties();
//        //1.使用p.load(输入流)
//        FileInputStream fis = new FileInputStream("jdbc.properties");
//        p.load(fis);


        //2.使用ClassLoader
        ClassLoader c1 = PropetiesTest.class.getClassLoader();
        InputStream is = c1.getResourceAsStream("jdbc1.properties");
        p.load(is);

        String user = p.getProperty("user");
        String psw = p.getProperty("psw");
        System.out.println(user + "\t" + psw);

    }

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

1.newInstance():创建运行时类的对象;内部调用了运行时类的空参构造器;

2.只有构造器才能造对象

3.要想此方法能够正常创建运行时类的对象;则运行时类必须提供空参的构造器;且该空参构造器通常设置为public。

4.在Javabean中要求提供一个public的空参构造器:便于通过反射创建运行时类的对象;便于子类继承运行时类,默认调用super()时,不会报错。

//创建运行时类的对象:通过反射
@Test
public void test2() throws IllegalAccessException, InstantiationException {
    Class clazz1 = Person.class;
    Person p = clazz1.newInstance();
    System.out.println(p);
}

8.获取属性结构

1.getFields():获取当前运行时类及其父类中声明为public访问权限的属性

2.getDeclaredFields():获取当前运行时类中声明的所有属性(不包含父类中声明的属性)

3.获取每个属性的具体参数:了解

        权限修饰符:getModifiers

        数据类型:getType

        变量名:getName

9.获取方法

1.getMethods(): 获取当前运行时类及其父类中声明为public访问权限的方法

2.getDeclaredMethods(): 获取当前运行时类中声明的所有方法(不包含父类中声明的方法)

3.获取每个方法具体参数:了解

        方法注解:getAnnotations(生命周期为Runtime才能获取到)

        权限修饰符:getModifiers

        返回值类型:get ReturnType

        方法名:getName

        形参列表:getParameterTypes

        抛出的异常:getExceptionTypes

10.获取构造器

1.getConstructors:获取当前运行时类及其父类中声明为public访问权限的构造器

2.getDeclaredConstructors:获取当前运行时类中声明的所有构造器(不包含父类中声明的构造器)

11.获取运行时类的父类

1.getSuperClass()

2.getGenericSuperClass():带泛型父类

3.获取带泛型父类的泛型

4.获取运行时类的接口

5.获取运行时类的包:get Package()

6.获取运行时类的注解:getAnnotations

//使用反射获取运行时类的父类、带泛型的父类、父类的泛型的泛型、类的接口、父类的接口、类的包、注解
@Test
public void test4(){

    Class clazz = Person.class;

    //使用反射获取运行时类的父类
    System.out.println(clazz.getSuperclass());

    //使用反射获取运行时类带泛型父类
    System.out.println(clazz.getGenericSuperclass());

    //使用反射获取运行时类带泛型父类的泛型
    Type genericSuperclass = clazz.getGenericSuperclass();
    ParameterizedType param = (ParameterizedType) genericSuperclass;
    Type[] actualTypeArguments = param.getActualTypeArguments();
    System.out.println(((Class)actualTypeArguments[0]).getName());

    //使用反射获取运行时类的接口
    Class[] interfaces = clazz.getInterfaces();
    for (Class c : interfaces){
        System.out.println(c);
    }

    //使用反射获取运行时类的父类的接口
    Class[] interfaces1 = clazz.getSuperclass().getInterfaces();
    for (Class c : interfaces1){
        System.out.println(c);
    }

    //使用反射获取运行时类的包
    Package p = clazz.getPackage();
    System.out.println(p);

    //使用反射获取运行时类的方法的注解
    Method[] methods = clazz.getMethods();
    for (Method m : methods) {
        Annotation[] annotations = m.getAnnotations();
        for (Annotation a : annotations) {
            System.out.println(a);
        }
    }

}

12.调用运行类中指定的结构:属性、方法、构造器(重点)

一、调用指定的属性:(掌握)

1.创建运行时类实例,创建运行时类的对象

2.getDeclaredField(String Name):获取当前运行时类中指定变量的属性;

3.setAccessible(true):保证该属性可以被访问(即使封装为private也可以)

4.set(p,fieldName):设置指定对象的变量

5.get(p):获取指定对象的指定变量 

Java反射机制_第1张图片 

二、调用指定的方法:(掌握)

1.创建运行时类实例,创建运行时类的对象

2. getDeclaredMethod(): 参数一:指明获取方法的名称;参数二:指明获取方法的形参列表

3.setAccessible(true);设置为可以访问的

4.invoke(p,实参):参数一:方法的调用者;参数二:给方法形参赋值的形参

注意:invoke()方法的返回值即为对应类中调用方法的返回值。若为void没有返回值,则返回null

Java反射机制_第2张图片

 

5.如何调用静态方法

一样的步骤,invoke里面写上当前运行时类

Java反射机制_第3张图片

 

三、如何调用运行时类的构造器

1.找到指定构造器

2.setAccessible():保证次构造器可访问

3..newInstance():调用该构造器造对象

13.反射的应用

1.静态代理:代理类和被代理类在编译期间,就确定下来了

2.动态代理与AOP

具体见:

Java-代理模式_perseveregz的博客-CSDN博客

你可能感兴趣的:(java,jvm,开发语言)