反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

反射就是把java类中的各种成分映射成一个个的Java对象。

例如:一个类有成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。

 

一个类的所有的对象共享同一个Class对象

举例: Student stu1=new Student()

Student stu2=new Student();

stu1与stu2共享同一个Student类的Class对象。

 

Class类被创建后的对象就是Class对象。注意,Class对象表示的是自己手动编写类的类型信息。比如创建一个Shapes类,那么,JVM就会创建一个Shapes对应Class类的Class对象,该Class对象保存了Shapes类相关的类型信息。

在Java中每个类都有一个Class对象,每当编写并且编译一个新创建的类时就会产生一个对应的Class对象,并且这个Class对象会被保存在同名.class文件里(编译后的字节码文件保存的就是Class对象)。

当我们new一个新对象或者引用静态成员变量时,JVM中的类加载器子系统会将对应的Class对象加载到JVM中,然后JVM再根据这个类型信息相关的Class对象创建我们需要的实例对象或者提供静态变量的引用值。

需要特别注意的是,手动编写的每个class类,无论创建多少个实例对象,在JVM中都只有一个Class对象,即在内存中每个类有且只有一个相对应的Class对象。

 

Class类的对象作用是运行时提供或获得某个对象的类型信息,这点对于反射技术很重要。

 

Class对象的加载

 

所有的类都是在对其第一次使用时动态加载到JVM中的,当程序创建第一个对类的静态成员引用时,就会加载这个被使用的类(实际上加载的就是这个类的字节码文件)。注意,使用new操作符创建类的实例对象也会被当作对类的静态成员的引用(构造函数也是类的静态方法)。

由此看来Java程序在它们开始运行之前并非被完全加载到内存,其各个部分是按需加载。所以在使用该类时,类加载器首先会检查这个类的Class对象是否已被加载,如果还没有加载,默认的类加载器就会先根据类名查找.class文件(编译后Class对象被保存在同名的.class文件中),在这个类的字节码文件被加载时,它们必须接受相关验证,以确保没有被破坏并且不包含不良Java代码(这是java的安全机制检测),完全没有问题后就会被动态加载到内存中,此时相当于Class对象也就被载入内存了,同时也就可以被用来创建这个类的所有实例对象。

 

获得Class对象的三种方式

public class FanShe02 {
    public static void main(String[] args) throws ClassNotFoundException {
        //使用字节码获取(类字面常量)
        Class c1=Student.class;
        System.out.println(c1);
        //通过Class的静态方法forName获取
        Class c2=Class.forName("cn.gakki.FanShe.Student");
        System.out.println(c2);
        //通过类的对象的成员方法getClass()获取,该方法为Object类的方法
        Student student=new Student("小兰",18);
        Class c3=student.getClass();
        System.out.println(c3);
        System.out.println(c1==c2);
        System.out.println(c1==c3);
        System.out.println(c2==c3);
    }
}

注意:在运行期间,一个类,只有一个Class对象产生。

类字面常量更加安全、高效。

 

获取Student类的属性对象(Field)

public class FanShen03 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        //获取Student类的Class对象
        Class c1= Class.forName("cn.gakki.FanShe.Student");
        //根据Class对象,获取Student类的属性对象
        //获取public属性
        Field[] fields=c1.getFields();
        for(Field field:fields){
            System.out.println(field);
        }
        System.out.println();
        //获取所有属性
        Field[] fields1=c1.getDeclaredFields();
        for(Field field:fields1){
            System.out.println(field);
            System.out.println("属性修饰符:"+field.getModifiers()+"--->"+ Modifier.toString(field.getModifiers()));
            System.out.println("属性类型:"+field.getType());
            System.out.println("属性名称:"+field.getName());
            System.out.println();
        }
        //根据名称获取属性对象
        Field field=c1.getDeclaredField("age");
        System.out.println(field);
    }
}

获取类的成员方法(Method)

public class FanShe05 {
    public static void main(String[] args) throws Exception {
        //获取Student类的Class对象
        Class c=Class.forName("cn.gakki.FanShe.Student");
        //获取Student类的成员方法
        Method[] methods=c.getDeclaredMethods();
        for(Method method:methods){
            System.out.println(method);
        }
        System.out.println();
        //获取所有方法(包括父类方法)
        Method[] methods1=c.getMethods();
        for(Method method:methods1){
            System.out.println(method);
        }
        System.out.println();
        //通过方法名称获取指定的方法对象
        Method method=c.getMethod("getAge");
        System.out.println(method);
        System.out.println("方法的权限:"+ Modifier.toString(method.getModifiers()));
        System.out.println("方法的返回值类型:"+method.getReturnType());
        System.out.println("方法的名称:"+method.getName());
        System.out.println();
        //获取setAge()方法
        Method method1=c.getMethod("setAge", int.class);
        System.out.print("方法的参数:");
        Class[] parm=method1.getParameterTypes();
        System.out.println(parm[0]);
        //获取show()方法
        Method method2=c.getMethod("show", String.class, int.class);
        Class[] parm1=method2.getParameterTypes();
        System.out.println("方法的参数:");
        for(Class p:parm1){
            System.out.println(p);
        }
        System.out.println();
        
        //方法的执行invoke
        //创建Student对象
        Student student=(Student) c.newInstance();
        //执行method1对象的方法(setAge()方法)
        method1.invoke(student,18);
        //执行method对象的方法(getAge()方法)
        method.invoke(student);
        //执行show()方法
        method2.invoke(student,"三三",7);
    }
}

获取Student的构造方法对象(Constructor)

public class FanShe04 {
    public static void main(String[] args) throws Exception {
        //获取Studeng类的Class对象
        Class c=Class.forName("cn.gakki.FanShe.Student");
        
        //获取Student类的构造方法对象
        Constructor[] constructor=c.getConstructors();
        for(Constructor constructor1:constructor){
            System.out.println(constructor1);
        }
        System.out.println();
        
        //获取指定的构造方法对象
        //获取无参构造
        Constructor constructor1=c.getConstructor();
        //创建Student对象
        Student student=(Student) constructor1.newInstance();
        System.out.println(student);//默认调用Student的toString方法
        System.out.println();
        
        //获取带参构造
        Constructor constructor2=c.getDeclaredConstructor(String.class,int.class);
        //创建对象
        Student student1=(Student) constructor2.newInstance("兰",20);
        System.out.println(student1);
        System.out.println();
        
        //创建Student对象,可以使用Class对象的newInstance()方法
        //默认调用无参构造方法
        Student student2=(Student) c.newInstance();
        System.out.println(student2);
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值