Java高级学习篇之反射

导读:本篇文章讲解 Java高级学习篇之反射,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

Java高级学习篇之反射

(一) 什么是反射?

            就是把Java类中的各个成分映射成一个个的Java对象。即在运行状态中,对于任意一个类,都能够获取这个类的所有属性和方法;对于任意一个对象,都能调用其任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫 Java的反射机制 

说明: 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个 类只有一个Class对象),这个对象就包含了完整的类的结构信息。可以通过这个对象查看到所对应类的所有信息。

Java高级学习篇之反射

(二) 反射能做什么?

Java高级学习篇之反射

(1)在运行时判断任意一个对象所属的类

(2)在运行时构造任意一个类的对象

(3)在运行时判断任意一个类所具有的成员变量和方法

(4)在运行时获取泛型信息

(5)在运行时调用任意一个对象的成员变量和方法

(6)在运行时处理注解

(7)生成动态代理

(三) Class类

Java高级学习篇之反射

通过对象可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接 口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含 了特定某个结构(class/interface/enum/annotation/primitive type/void/[])的有关信息。

(1) Class本身也是一个类

(2) Class 对象只能由系统建立

(3) 一个加载的类在 JVM 中只会有一个Class实例

(4)一个Class对象对应的是一个加载到JVM中的一个.class文件

(5) 每个类的实例都会记得自己是由哪个 Class 实例所生成

(6)通过Class可以完整地得到一个类中的所有被加载的结构

(7)Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得         相应的 Class对象

(四) 实际应用​

I.获取Class类的实例

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

方式二:通过运行时类的对象,调用getClass()

方式三:调用Class的静态方法:formatName(String classPath)

方式四:使用类的加载器:ClassLoader

@Test
    public void test3() throws ClassNotFoundException {//获取运行时类的方式(前三种为重点)
        //方式一:调用运行时类的属性
        Class clazz = Person.class;
        System.out.println(clazz);
        //方式二: 通过运行时类的对象,调用getClass()
        Person p1 = new Person();
        Class clazz2 = p1.getClass();
        System.out.println(clazz2);
        //方式三:调用Class的静态方法:formatName(String classPath)
        Class clazz3 = Class.forName("practice.Person");
        System.out.println(clazz3);
        //判断是否相等
        System.out.println(clazz == clazz2);
        System.out.println(clazz2 == clazz3);
        //说明:更好地体现了动态性,在编译时无法判断出错误一旦运行,如果错误就直接报错

        //方式四;使用类的加载器:ClassLoader
        ClassLoader classLoader = ReflectionTest.class.getClassLoader();
        Class clazz4 = classLoader.loadClass("practice.Person");
        System.out.println(clazz4);
        System.out.println(clazz3 == clazz4);
    }

补充:

(1) 哪些对象 可以有Class实例?

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

② interface:接口

③ []:数组

④ enum:枚举

⑤ annotation:注解@interface

⑥ primitive type:基本数据类型

⑦ void

(2)类的加载器( ClassLoader 

II.读取配置文件(properties)

基本介绍:

Java 中的 ​ ​ properties ​ ​ 文件是一种配置文件,主要用于表达配置信息,文件类型为*.properties,格式为文本文件,文件的内容是格式是”键=值”的格式.

@Test
    public void test1() throws Exception {
        Properties pros=new Properties();
        //此时的文件默认路径为当前的module下
        //也可以使用完整路径来寻找特定位置的properties文件
//        FileInputStream fis=new FileInputStream("src\\practice\\jdbc1.properties");
        FileInputStream fis=new FileInputStream("jdbc.properties");
        pros.load(fis);
        String user=pros.getProperty("user");
        String password=pros.getProperty("password");
        System.out.println("user = "+ user +"\npassword ="+ password);
    }
    /**
     * 读取配置文件(方式二)
     * */
    @Test
    public void test3() throws Exception {
        Properties pros3=new Properties();
        ClassLoader classLoader=ClassLoaderTest.class.getClassLoader();
        //使用绝对路径
        InputStream is=classLoader.getResourceAsStream("src\\practice\\jdbc1.properties");
        pros3.load(is);
        String name = pros3.getProperty("user");
        String password=pros3.getProperty("password");
        System.out.println("user= "+name+ ",password ="+password);

    }

III.创建运行时类的对象

  • newInstance():调用此方法,创建运行时类的对象,内部调用了运行时类的空参构造器​
  • 此方法使用前提:
  • (1)运行时类必须提供空参构造器
  • (2)空参构造器的访问权限必须要够,通常为public
  • 在javabean中要求提供一个public的空参构造器
  • 原因如下:
  • (1) 便于通过反射,创建运行时类的对象
  • (2) 便于子类继承此运行时类的对象,默认调用super()时,保证父类由此构造器
public class NewInstanceTest {
    @Test
    public void test2() throws InstantiationException, IllegalAccessException {
        //(1)获取运行时类
        Class<Person> clazz=Person.class;
        //(2)方法1--->newInstance() :调用此方法,创建对应的运行时类的对象(调用了运行时类的空参构造器)
        Object obj=clazz.newInstance();
        System.out.println(obj);
    }
}

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

①. 实现的全部接口  

      public Class<?>[] getInterfaces()                                                     

     说明:确定此对象所表示的类或接口实现的接口 

具体代码:

@Test
    public void test3(){
        Class clazz= Person1.class;
        Class[] interfaces=clazz.getInterfaces();
        for(Class f:interfaces){
            System.out.println(f);
        }
        System.out.println();
        //获取运行时类父类的接口
        Class[]interfaces1=clazz.getSuperclass().getInterfaces();
        for(Class m:interfaces1){
            System.out.println(m);
        }
    }

②. 所继承的父类      

  public Class<? Super T> getSuperclass()                                         

    说明:返回表示此 Class 所表示的实体(类、接口、基本类型)的父类的 Class。

/**
     * 获取运行时类的父类
     * */
    @Test
    public void test7(){
        Class clazz=Person1.class;
        Class superclass=clazz.getSuperclass();
        System.out.println(superclass);
    }
    /**
     * 通过反射获取带泛型的父类
     * */
    @Test
    public void test8(){
        Class clazz=Person1.class;
        Type generiSuperclass=clazz.getGenericSuperclass();

        ParameterizedType parameterizedType=(ParameterizedType) generiSuperclass;
        //获取泛型类型
        Type[] actualArguments=parameterizedType.getActualTypeArguments();
        System.out.println(actualArguments[0].getTypeName());
    }

③ . 全部的构造器     

   public Constructor<T>[] getConstructors()                                    

     说明:返回此 Class 对象所表示的类的所有public构造方法。

public Constructor<T>[] getDeclaredConstructors()                        

    说明:返回此 Class 对象表示的类声明的所有构造方法。

Constructor类中

  public int getModifiers(); —–>说明  : 取得修饰符                            

public String getName(); ——>说明:取得方法名称                       

public Class<?>[] getParameterTypes();—>说明: 取得参数的类型

代码实现:

@Test
    public void test1() throws NoSuchMethodException {
        Class clazz=Person1.class;
        //getConstructors():获取当前运行时类中声明为public 的方法
        Constructor[]constructors=clazz.getConstructors();
        for (Constructor e:constructors) {
            System.out.println(e);
        }
        System.out.println();
        //getDeclaredConstructor():获取当前类中所有声明的构造器
        Constructor[]declareConstructors=clazz.getDeclaredConstructors();
        for (Constructor e:declareConstructors) {
            System.out.println(e);
        }

    }

④. 全部的方法

public Method[] getDeclaredMethods()                                         

说明:返回此Class对象所表示的类或接口的全部方法

public Method[] getMethods()                                                        

说明:返回此Class对象所表示的类或接口的public的方法

 Method类中:

public Class<?>getReturnType()                                                      

说明:取得全部的返回值

public Class<?>[]getParameterTypes()                                            

说明:取得全部的参数

public int getModifiers() ;  —>取得修饰符                                     

public Class<?>[]getExceptionTypes()取得异常信息                          

具体代码:

/**
     * 权限修饰符 数据类型  变量名
     * */
    @Test
    public void test2(){
        Class clazz=Person1.class;
        Field[]declareFields=clazz.getDeclaredFields();
        for(Field f :declareFields){
            System.out.println();
            System.out.println(f);
           //权限修饰符
           int modifier=f.getModifiers();
           //输出对应属性的权限及权限修饰符的等级
            System.out.println(Modifier.toString(modifier));
            System.out.println(modifier);

            //数据类型
            Class type=f.getType();
            System.out.println(type+"\t");

            //变量名
            String name=f.getName();
            System.out.println(name);

        }

    }

⑤.全部的Field

public Field[] getFields() ;                                                                

说明:返回此Class对象所表示的类或接口的public的Field。

public Field[] getDeclaredFields() ;                                                  

说明:返回此Class对象所表示的类或接口的全部Field。

Field方法

public int getModifiers() ;                                                                  

说明:以整数形式返回此Field的修饰符。

 public Class<?> getType() ;                                                                                   

说明:得到Field的属性类型

public String getName()                                                                       

说明:返回Field的名称

具体代码

@Test
    public void test1(){
        Class clazz=Person1.class;
        //获取属性结构
        //getFields():获取当前运行时类及父类中声明为public访问权限的属性
        Field[]field=clazz.getFields();
        for(Field f:field){
            System.out.println(f);
        }
        System.out.println();
        //getDeclareFields():获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)
        Field[]declareFields=clazz.getDeclaredFields();
        for(Field f: declareFields){
            System.out.println(f);
        }
    }

⑥. Annotation相关

get Annotation(Class<T> annotationClass)                                       

getDeclaredAnnotations()                                                                  

代码实现:

@Test
    public void test9(){
        Class clazz=Person1.class;
        Annotation[]annotations=clazz.getAnnotations();
        for(Annotation s:annotations){
            System.out.println(s);
        }
    }

⑦.泛型相关

Type getGenericSuperclass()                                                               

说明:获取父类泛型类型

ParameterizedType                                                                             

说明:泛型类型

getActualTypeArguments()                                                                

说明:获取实际的泛型类型参数数组

⑧.类所在的包

Package getPackage()                                                                        

代码实现

@Test
    public void test5(){
        Class clazz=Person1.class;
        Package pack=clazz.getPackage();
        System.out.println(pack);
    }

​​

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/94713.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!