资讯专栏INFORMATION COLUMN

Java反射机制及API使用

vibiu / 1984人阅读

摘要:有一个参数的构造方法姓名有多个参数的构造方法姓名年龄这的执行效率有问题,以后解决。私有构造方法私有的构造方法年龄反射获取对象的三种方式通过对象名方法获取通过类名方式获得通过方法获得在运行期间,一个类,只有一个对象产生。

原文地址

反射简单来说,就是动态加载对象,并对对象进行剖析。在Java中的反射机制是指在运行状态中,对于任意一个类,都能够知道并获取这个类的所有属性和方法。

Java反射机制的作用:

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

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

在运行时任意调用一个对象的方法

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

反射机制的优缺点是什么?

反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性。

它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它
满足我们的要求。这类操作总是慢于只直接执行相同的操作。

获取Class对象的三种方式
package com.gyl;

public class Student {
    public int no;
    public String sex;

    private String name;
    private int age;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    /*
     * 构造方法
     */
    
   Student(String str){  
       System.out.println("(默认)的构造方法 s = " + str);  
   }  
     
   //无参构造方法  
   public Student(){  
       System.out.println("调用了公有、无参构造方法执行了。。。");  
   }  
     
   //有一个参数的构造方法  
   protected Student(char name){  
       System.out.println("姓名:" + name);  
   }  
     
   //有多个参数的构造方法  
   public Student(String name ,int age){  
       System.out.println("姓名:"+name+"年龄:"+ age);//这的执行效率有问题,以后解决。  
   }  
     
   //私有构造方法  
   private Student(int age){  
       System.out.println("私有的构造方法   年龄:"+ age);  
   }
    
}
package com.gyl;

import java.lang.reflect.Constructor;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        Student student = new Student();
        
        /*
         * JAVA反射--获取Class对象的三种方式
         */
        
        // 通过对象名.getClass()方法获取
        Class stuClass = student.getClass();
        System.out.println("stuClass is "+stuClass.getName());        
        
        // 通过类名.class方式获得
        Class stuClass1 = Student.class;
        System.out.println("stuClass1 is "+stuClass1.getName());
        System.out.println(stuClass == stuClass1);
        
        // 通过Class.forName()方法获得
        Class stuClass2 = Class.forName("com.gyl.Student");
        System.out.println("stuClass2 is "+stuClass2);
        System.out.println(stuClass1 == stuClass2);
    }
}

Output:
stuClass is com.gyl.Student
stuClass1 is com.gyl.Student
true
stuClass2 is class com.gyl.Student
true
在运行期间,一个类,只有一个Class对象产生。三种方式常用第三种,第一种对象都有了还要反射干什么。第二种需要导入类的包,依赖太强,不导包就抛编译错误。一般都选第三种,一个字符串可以传入也可写在配置文件中等多种方法。
反射API 获取构造方法
// 返回指定参数类型 public的构造器。 
Constructor getConstructor(类... parameterTypes) 

// 返回指定参数类型的构造器(public, protected, private)。
Constructor getDeclaredConstructor(类... parameterTypes) 

// 返回所有的public类型的构造器
Constructor[] getConstructors() 

// 返回所有的构造器
Constructor[] getDeclaredConstructors() 
package com.gyl;

import java.lang.reflect.Constructor;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException {

        // 通过Class.forName()方法获得Class对象
        Class stuClass = Class.forName("com.gyl.Student");
        
        
        System.out.println("************返回所有public构造方法************");
        Constructor[] constructors = stuClass.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        /*
         * Output:
         * ************返回所有public构造方法************
         *    public com.gyl.Student()
         *    public com.gyl.Student(java.lang.String,int)
         */
    
        System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");  
        Constructor[] constructors2 = stuClass.getDeclaredConstructors();
        for (Constructor constructor : constructors2) {
            System.out.println(constructor);
        }
        /*
         * Output:
         * ************所有的构造方法(包括:私有、受保护、默认、公有)***************
         *    private com.gyl.Student(int)
         *    public com.gyl.Student()
         *    protected com.gyl.Student(char)
         *    public com.gyl.Student(java.lang.String,int)
         *    com.gyl.Student(java.lang.String)
         */
        
        
        Constructor constructor;

        System.out.println("************返回指定类型的 public构造器************");
        try {
            constructor = stuClass.getConstructor(String.class, int.class);
            System.out.println(constructor);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        /*
         * Output:
         * ************返回指定类型的 public构造器************
         * public com.gyl.Student(java.lang.String,int)
         * 
         * 如果指定参数的构造器是非public类型的 则抛出java.lang.NoSuchMethodException异常
         */
          
        System.out.println("************返回指定类型的构造器************");
        try { 
            constructor = stuClass.getDeclaredConstructor(int.class);
            System.out.println(constructor);            // char.class
        } catch (NoSuchMethodException e) {             // String.class, int.class
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        /*
         * Output:
         * ************返回指定类型的构造器************
         * public com.gyl.Student(java.lang.String,int)
         * protected com.gyl.Student(char)
         * private com.gyl.Student(int)
         */
    }
}
获取变量
// 根据变量名获得对应的变量,访问权限不限;
Field getDeclaredField(String name) 

// 获得类中所有属性变量 
Field[] getDeclaredFields()

// 根据变量名获取对应public类型的属性变量
Field getField(String name) 

// 获取类中所有public类型的属性变量
Field[] getFields() 
package com.gyl;

import java.lang.reflect.Field;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException {

        // 通过Class.forName()方法获得Class对象
        Class stuClass = Class.forName("com.gyl.Student");
        
        try {
            Field field1 = stuClass.getField("sex");
            System.out.println(field1);
            
            Field field = stuClass.getDeclaredField("name");
            System.out.println(field);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        /*
         * Output:
         * public java.lang.String com.gyl.Student.sex
         * private java.lang.String com.gyl.Student.name
         * 如果使用getField方法指定了一个非public类型的属性,则抛出java.lang.NoSuchFieldException异常
         */
        
        Field[] fields1 = stuClass.getFields();
        Field[] fields = stuClass.getDeclaredFields();
        System.out.println("************返回所有public属性************");
        for (Field field : fields1) {
            System.out.println(field);
        }
        /*
         * Output:
         * ************返回所有public属性************
         *    public int com.gyl.Student.no
         *    public java.lang.String com.gyl.Student.sex
         */

        System.out.println("************返回所有属性************");
        for (Field field : fields) {
            System.out.println(field);
        }
        /*
         * Output:
         * ************返回所有属性************
         *    public int com.gyl.Student.no
         *    public java.lang.String com.gyl.Student.sex
         *    private java.lang.String com.gyl.Student.name
         *    private int com.gyl.Student.age
         */
    }
}
获取方法
// 获取“名称是name,参数是parameterTypes”的public的函数(包括从基类继承的、从接口实现的所有public函数)
public Method  getMethod(String name, Class[] parameterTypes)

// 获取全部的public的函数(包括从基类继承的、从接口实现的所有public函数)
public Method[]  getMethods()

// 获取“名称是name,参数是parameterTypes”,并且是类自身声明的函数,包含public、protected和private方法。
public Method  getDeclaredMethod(String name, Class[] parameterTypes)

// 获取全部的类自身声明的函数,包含public、protected和private方法。
public Method[]  getDeclaredMethods()

// 如果这个类是“其它类中某个方法的内部类”,调用getEnclosingMethod()就是这个类所在的方法;若不存在,返回null。
public Method  getEnclosingMethod()
package com.gyl;

import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException {

        // 通过Class.forName()方法获得Class对象
        Class stuClass = Class.forName("com.gyl.Student");
        
        Method method;
        try {
//            method = stuClass.getMethod("getName");
            method = stuClass.getDeclaredMethod("getAge");
            System.out.println(method);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        
        
        System.out.println("*********输出所有方法********");
        Method[] methods = stuClass.getDeclaredMethods();
        for (Method method2 : methods) {
            System.out.println(method2);
        }
        /*
         * Output:
         * public int com.gyl.Student.getAge()
         *    *********输出所有方法********
         *    public java.lang.String com.gyl.Student.getName()
         *    public void com.gyl.Student.setName(java.lang.String)
         *    void com.gyl.Student.print(java.lang.String)
         *    public int com.gyl.Student.getAge()
         *    public void com.gyl.Student.setAge(int)
         */
    }
}
通过反射越过泛型检查

泛型用在编译期,编译过后泛型擦除(消失掉)。所以是可以通过反射越过泛型检查的

import java.lang.reflect.Method;  
import java.util.ArrayList;  
 
/* 
* 通过反射越过泛型检查 
*  
* 例如:有一个String泛型的集合,怎样能向这个集合中添加一个Integer类型的值? 
*/  
public class Demo {  
   public static void main(String[] args) throws Exception{  
       ArrayList strList = new ArrayList<>();  
       strList.add("aaa");  
       strList.add("bbb");  
         
   //  strList.add(100);  
       //获取ArrayList的Class对象,反向的调用add()方法,添加数据  
       Class listClass = strList.getClass(); //得到 strList 对象的字节码 对象  
       //获取add()方法  
       Method m = listClass.getMethod("add", Object.class);  
       //调用add()方法  
       m.invoke(strList, 100);  
         
       //遍历集合  
       for(Object obj : strList){  
           System.out.println(obj);
           System.out.println(obj.getClass());
       }  
        /*
         *Output:
         * aaa
         * class java.lang.String
         * bbb
         * class java.lang.String
         * 100
         * class java.lang.Integer
         */
   }  
}

其他方法请参考Java jdk,本文参考自Java jdk1.8

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69414.html

相关文章

  • Java知识点汇总

    摘要:由于类型擦除机制的存在,泛型类中的类型参数等信息,在运行时刻是不存在的。对此,对类文件的格式做了修订,添加了属性,用来包含不在类型系统中的类型信息。在运行时刻,会读取属性的内容并提供给反射来使用。 OOP 对象的创建和拷贝 对象的初始化 多态的实现 内部类、匿名类、静态类 对象内存模型 上面内容均请参考以下文章: 谈谈Java的面向对象 运行时 异常 聊聊Java的异常机制及实现 ...

    Chao 评论0 收藏0
  • 乐字节Java反射之一:反射概念与获取反射源头class

    摘要:一反射机制概念程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言,如,是动态语言显然,,不是动态语言,但是有着一个非常突出的动态相关机制。相关的为二获取源头重点打开权限所有类的对象其实都是的实例。 一、Java反射机制概念 程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言,如Python, Ruby是动态语言;显然C++,Java,C#不是动态语言,但是JAVA有...

    caikeal 评论0 收藏0
  • Java笔记-反射机制(一)

    摘要:反射机制一结合官方通过编写的反射教程,复习一下反射的知识。反射的概念反射是一种在运行时获取以及修改应用行为的一种工具。因为反射需要动态的解析类的信息,相比于非反射使用的方式要慢。反射需要获取一定的运行时权限,在特定的安全环境下不一定存在。 Java反射机制(一) 结合Oracle官方通过JDK8编写的反射教程,复习一下反射的知识。结尾篇补一个小例子。 主要内容 这次博客的主要内容就是简...

    AWang 评论0 收藏0
  • 一文带你了解Java反射机制

    摘要:在的反射包中提供了三个类以及来分别描述属性方法和构造器。获取构造器获取方法可以看到我们可以通过一个类的对象很轻松的获取他的属性构造器以及方法信息。返冋一个用于描述构造器名的字符串。 想要获取更多文章可以访问我的博客 - 代码无止境。 上周上班的时候解决一个需求,需要将一批数据导出到Excel。本来公司的中间件组已经封装好了使用POI生成Excel的工具方法,但是无奈产品的需求里面有个合...

    darcrand 评论0 收藏0
  • java反射机制的基本语法练习

    摘要:在思否上面开了一个专栏,主要是想对零散的知识点做一个梳理,在与大家交流的同时,也加强自己的理解。今天主要谈一下中的反射机制,虽然实际编程中我们很少直接使用,但是反射机制却始终围绕着我们程序员。 在思否上面开了一个专栏,主要是想对零散的知识点做一个梳理,在与大家交流的同时,也加强自己的理解。   今天主要谈一下Java中的反射机制,虽然实际编程中我们很少直接使用,但是反射机制却始终...

    gaomysion 评论0 收藏0

发表评论

0条评论

vibiu

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<