当前位置:首页 » 《关注互联网》 » 正文

Java之反射

13 人参与  2024年10月10日 15:20  分类 : 《关注互联网》  评论

点击全文阅读


目录

反射

定义

主要用途

反射相关的类

Class类中【获得类相关方法】

Class类中【获得类中属性相关的方法】 

Class类中【获得类中注解相关的方法】 

 

Class类中【获得类中构造器相关的方法】 

Class类中【获得类中方法相关的方法】 

获得Class对象

代码示例1

代码示例2

反射的优缺点


反射
定义

Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制。

主要用途

1.动态地创建类的实例:在运行时根据类的全限定名创建对象。
2.检查类的结构:获取类的成员变量、方法、构造器等信息。
3.调用方法:在运行时动态地调用对象的方法。
4.访问和修改私有字段:即使在类定义中字段是私有的,也可以通过反射来访问和修改。 

反射相关的类
类名用途
Class类代表类的实体,在运行的Java应用程序中表示类和接口
Filed类代表类的成员变量/类的属性
Method类代表类的方法
Constructor类代表类的构造方法

Class类

Class类代表类的实体,在运行的Java应用程序中表示类和接口 .

Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件 ,被编译后的Java文件.class也被JVM解析为一个对象,这个对象就是java.lang.Class,这样当程序在运行时,每个.class文件就最终变成了Class类对象的一个实例。我们通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类成为一个动态的类。

Class类中【获得类相关方法】
方法用途
getClassLoader()获得类的加载器
getDeclaredClasses()返回一个数组,数组中包含该类的所有类和和接口类的对象(包括私有的)
forName(String className)根据类名返回类的对象
newInstance()创建类的实例
getName()获得类的完整路径名字

Class类中【获得类中属性相关的方法】 
方法用途
getField(String name)获得某个公有的属性对象
getFields()获得所有公有的属性对象
getDeclaredField(String name)获得某个属性对象
getDeclaredFields()获得所有属性对象

Class类中【获得类中注解相关的方法】 
方法用途
getAnnotation(Class annotationClass)返回该类中与参数匹配的公有注解对象
getAnnotations()返回该类中所有的公有注解对象
getDeclaredAnnotaion(Class annotationClass)返回该类中与参数类型匹配的所有注解对象
getDeclaredAnnotations()返回该类所有的注解对象

Class类中【获得类中构造器相关的方法】 
方法用途
getConstructor(Class<?>... parameterTypes)获得该类中与参数类型匹配的公有构造方法
getConstructors()获得该类的所有公有构造方法
getDeclaredConstructor(Class<?>... parameterTypes)获得该类中与参数类型匹配的构造方法
getDeclaredConstructors()获得该类所有构造方法

Class类中【获得类中方法相关的方法】 
方法用途
getMethod(String name,Class<?>... parameterTypes)获得该类某个公有的方法
geMethods()获得该类所有公有的方法
getDeclaredMethod(String name,Class<?>... parameterTypes)获得该类某个方法
getDeclaredMethds()获得该类所有方法

获得Class对象

反射的第一步是获取代表某个类的Class对象。可以通过多种方式获取Class对象,最常见的是:

1.使用Class.forName(String className)静态方法,如果类名在类的路径中,则通过该类的全限定名(包括包名)来获取Class对象。注意,这种方式会抛出ClassNotFoundException。
2.使用.class语法,在编译时就已经确定。
3.调用对象的getClass()方法,在运行时确定对象的实际类型。

代码示例1
class Student{    //私有属性name    private String name = "bit";    //公有属性age    public int age = 18;    //不带参数的构造方法    public Student(){        System.out.println("Student()");    }    private Student(String name,int age) {        this.name = name;        this.age = age;        System.out.println("Student(String,name)");    }    private void eat(){        System.out.println("i am eat");    }    public void sleep(){        System.out.println("i am pig");    }    private void function(String str) {        System.out.println(str);    }    @Override    public String toString() {        return "Student{" +                "name='" + name + '\'' +                ", age=" + age +                '}';    }}public class Test {    //Class对象 只有一个    public static void main(String[] args) {        Class<?> c1;        try {            c1 = Class.forName("reflectdemo.Student");        } catch (ClassNotFoundException e) {            throw new RuntimeException(e);        }        Class<?> c2;        c2 = Student.class;        Student student = new Student();        Class<?> c3 = student.getClass();        System.out.println(c1.equals(c2));        System.out.println(c1.equals(c3));        System.out.println(c3.equals(c2));    }}
代码示例2
class Student{    //私有属性name    private String name = "bit";    //公有属性age    public int age = 18;    //不带参数的构造方法    public Student(){        System.out.println("Student()");    }    private Student(String name,int age) {        this.name = name;        this.age = age;        System.out.println("Student(String,name)");    }    private void eat(){        System.out.println("i am eat");    }    public void sleep(){        System.out.println("i am pig");    }    private void function(String str) {        System.out.println(str);    }    @Override    public String toString() {        return "Student{" +                "name='" + name + '\'' +                ", age=" + age +                '}';    }}public class ReflectDemo {    //如何通过反射 实例化对象    public static void reflectNewInstance() {        Class<?> c1;        try {            c1 = Class.forName("reflectdemo.Student");            Student student = (Student) c1.newInstance();            System.out.println(student);        } catch (ClassNotFoundException e) {            throw new RuntimeException(e);        } catch (InstantiationException e) {            throw new RuntimeException(e);        } catch (IllegalAccessException e) {            throw new RuntimeException(e);        }    }    // 反射私有的构造方法  屏蔽内容为获得公有的构造方法    public static void reflectPrivateConstructor() {        Class<?> c1;        try {            c1 = Class.forName("reflectdemo.Student");            Constructor<Student> con =                    (Constructor)c1.getDeclaredConstructor(String.class,int.class);            con.setAccessible(true);            Student student = con.newInstance("zhangsan",18);            System.out.println(student);        } catch (ClassNotFoundException e) {            throw new RuntimeException(e);        } catch (NoSuchMethodException e) {            throw new RuntimeException(e);        } catch (InvocationTargetException e) {            throw new RuntimeException(e);        } catch (InstantiationException e) {            throw new RuntimeException(e);        } catch (IllegalAccessException e) {            throw new RuntimeException(e);        }    }    // 反射私有属性    public static void reflectPrivateField() {        Class<?> c1;        try {            c1 = Class.forName("reflectdemo.Student");            Field field = c1.getDeclaredField("name");            field.setAccessible(true);            Student student = (Student) c1.newInstance();            field.set(student,"wangwu");            System.out.println(student);        } catch (ClassNotFoundException e) {            throw new RuntimeException(e);        } catch (NoSuchFieldException e) {            throw new RuntimeException(e);        } catch (InstantiationException e) {            throw new RuntimeException(e);        } catch (IllegalAccessException e) {            throw new RuntimeException(e);        }    }    // 反射私有方法    public static void reflectPrivateMethod() {        Class<?> c1;        try {            c1 = Class.forName("reflectdemo.Student");            Method method = c1.getDeclaredMethod("function",String.class);            method.setAccessible(true);            Student student = (Student) c1.newInstance();            method.invoke(student,"我是一个参数");            //System.out.println(student);        } catch (ClassNotFoundException e) {            throw new RuntimeException(e);        } catch (NoSuchMethodException e) {            throw new RuntimeException(e);        } catch (InstantiationException e) {            throw new RuntimeException(e);        } catch (IllegalAccessException e) {            throw new RuntimeException(e);        } catch (InvocationTargetException e) {            throw new RuntimeException(e);        }    }    public static void main(String[] args) {        //reflectNewInstance();        //reflectPrivateConstructor();        //reflectPrivateField();        reflectPrivateMethod();    }}
反射的优缺点

优点

1. 对于任意一个类,都能够知道这个类的所有属性和方法;

    对于任意一个对象,都能够调用它的任意一个方法。

2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力。
3. 反射已经运用在了很多流行框架如:Struts、Hibernate、Spring 等等。

缺点

1.反射会破坏封装性,使代码难以理解和维护。
2.反射通常比直接代码调用慢,因为它涉及到类型检查等动态解析。
3.滥用反射可能导致安全问题,如访问或修改不应该被访问的私有成员。


点击全文阅读


本文链接:http://zhangshiyu.com/post/170090.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1