对于java反射的一些学习理解和认知

1. 反射(Reflection)的概念

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

功能:

反射是java中一种强大的机制. Java反射机制主要提供了以下功能:

1.运行时判断任意一个对象所属的类;

2.运行时构造任意一个类的对象;

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

4.在运行时调用任意一个对象的方法,生成动态代理。

反射简单的解释就是,把类中的成分,映射到相应的类,达到用这些类操作框架.

2. Class 类

Java 程序在运行时,系统会对所有的对象进行所谓的运行时类型标识,用来保存这些信息的类就是 Class 类。Class 类封装一个对象和接口运行时的状态。

从Java源程序到java程序运行要经历一个曲折的过程:
源程序javac编译源程序,得到.class文件.jvm从硬盘读取.class文件,并且把.class文件转化成字节码存入内存读取这些字节码,得到程序运行效果

在第三个步骤的, jvm从硬盘读取.class文件,并且把.class文件转化成字节码存入内存,其中每一份字节码就是一个Class对象,Class相当于字节码的类(类似于Person是人的类).要得到Class类,通常有3种方式:

  1. 类名.class

  2. 对象名.getClass()

  3. Class. forName(完整的类名)—在反射中比较常用

反射的作用是把类中的成分,映射到相应的类,也就是说类中的方法,字段,构造函数,数组等都有映射的类,它们对应的就是Method , Field, Constructor, Array

Class类中的getFields , getConstructors,和getMethods方法返回public修饰的字段,构造函数和方法的数组,其中包括父类的公有成员.

Class类中的getDeclareFields , getDeclareMethods和getDeclareConstructors方法返回类中声明的全部字段,方法和构造函数,包含私有的和受保护的,但是不包括父类的成员。

3、通过案例来一步一步熟悉JAVA反射机制

//实例1、通过一个对象获取完整的包名和类名
package cn.cast.reflect;
class Demo{

}
public class test01 {
    public static void main(String[] args) {
        Demo demo=new Demo();
        System.out.println(demo.getClass().getName());
    }
}

运行结果:
cn.cast.reflect.Demo(所有类的对象都是Class的实例)
package cn.cast.reflect;
/*
 * 实例2、Class类的实例化
 * 由于Class类没有构造方法,所以实例化Class类的方式有点特殊,有三种方式:
 *  对象.getClass( )
 *  类.Class
 *  forName( )
 *  
 *  重点掌握forName()方法,因为它可以在类不确定的情况下实例化Class,更具灵活性
 *
 */
public class test02 {
    public static void main(String[] args) {
        //方式一:对象.getClass( )
        Demo demo=new Demo();
        Class<?> c1=demo.getClass();
        System.out.println(c1);

        //方式2:类.Class
        //Class<?> c2=Demo.class;
        Class c2=Demo.class;
        System.out.println(c2);

        //方式三:forName( )
        Class<?> c3=null;
        //forName()方法会抛出异常
        try {
            c3=Class.forName("cn.cast.reflect.Demo");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(c3);
    }
}

运行结果:
class cn.cast.reflect.Demo
class cn.cast.reflect.Demo
class cn.cast.reflect.Demo
package cn.cast.reflect;

/*
 *Class类的应用
 *  Class类中有一个方法叫做newInstance( ),它可以用来创建一个Class类对象的新实例
 *  怎么说呢?Class对象包含的内容就是反射好的那个类,我们要构造那个类的新实例(新对象)
 * 实例3:Class类的无参构造对象
 */
public class test03 {
    public static void main(String[] args) {
        //实例化Class对象,forname()方法抛出异常
        Class<?> c=null;
        try {
            //填写完整的包名和类名
            c=Class.forName("java.lang.String");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //生成一个String的引用
        String s=null;
        try {
            //将构造好的对象向下转型为Demo类
            //newInstance()方法会抛出异常
            s=(String)c.newInstance();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(s.length());

    }
}

运行结果:
0
package cn.cast.reflect;

import java.lang.reflect.Constructor;

/*
 * 实例4、Class类的有参构造对象
 * 因为String类用的比较多,便于理解
 * 这里需要注意的是,构造方法需要使用getConstructor( )方法获得
 * 至于参数类型则是:原有类型.class
 */
public class test04 {
    public static void main(String[] args) throws Exception {
        Class<?> c = null;
        try {
            c = Class.forName("java.lang.String");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        char[] ch = { 'H', 'e', 'l', 'l', 'o' };

        String s = null;
        // 需要获得Class类对象的有参构造方法,参数的写法:类型.class
        Constructor<?> con = c.getConstructor(char[].class);
        // 用这个构造方法构造一个新的字符串对象,参数为一个char数组
        s = (String) con.newInstance(ch);
        System.out.println("构造的字符串为:" + s);
    }
}

运行结果:
Hello
package cn.cast.reflect;

import java.lang.reflect.Constructor;
import java.util.Arrays;

/*
 * 获取类的结构
 * 实例5、获取类的构造方法
 */
public class test05 {
    public static void main(String[] args) throws Exception{
        Class<?> c=null;
        try {
            c=Class.forName("java.lang.Boolean");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //这里getConstrutors()方法返回的是一个Constructor数组
        Constructor<?> [] cons=c.getConstructors();
        //打印
        System.out.println(Arrays.toString(cons));

    }
}

运行结果:
[public java.lang.Boolean(boolean), 
public java.lang.Boolean(java.lang.String)]
package cn.cast.reflect;

import java.util.Arrays;

/*
 * 实例6:取得类所实现的接口
 */
public class test06 {
    public static void main(String[] args) {
        Class<?> c=null;
        try {
            c=Class.forName("java.lang.Boolean");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Class<?> []in=c.getInterfaces();
        System.out.println(Arrays.toString(in));
    }
}

运行结果:
[interface java.io.Serializable, interface java.lang.Comparable]

package cn.cast.reflect;
/*
 * 实例7:取得父类
 */

public class test07 {
    public static void main(String[] args) throws Exception {
        Class<?> c=null;
        try {
            c=Class.forName("java.lang.Boolean");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //这里不能用数组接收了
        Class<?> su=c.getSuperclass();
        System.out.println(su);
    }
}

运行结果:
class java.lang.Object
package cn.cast.reflect;

import java.lang.reflect.Method;

/*
 * 实例8:取得类的全部方法
 */
public class test08 {
    public static void main(String[] args) {
        Class<?> c=null;
        try {
            c=c.forName("java.lang.Boolean");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Method[] m=c.getMethods();
        for(int i=0;i<m.length;i++){
            System.out.println(m[i]);
        }

    }
}

运行结果:
public int java.lang.Boolean.hashCode()
public boolean java.lang.Boolean.equals(java.lang.Object)
public static java.lang.String java.lang.Boolean.toString(boolean)
public java.lang.String java.lang.Boolean.toString()
public static int java.lang.Boolean.compare(boolean,boolean)
public int java.lang.Boolean.compareTo(java.lang.Object)
public int java.lang.Boolean.compareTo(java.lang.Boolean)
public static java.lang.Boolean java.lang.Boolean.valueOf(boolean)
public static java.lang.Boolean java.lang.Boolean.valueOf(java.lang.String)
public boolean java.lang.Boolean.booleanValue()
public static boolean java.lang.Boolean.getBoolean(java.lang.String)
public static boolean java.lang.Boolean.parseBoolean(java.lang.String)
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException

package cn.cast.reflect;

import java.lang.reflect.Field;

/*
 * 实例9:取得本类的全部属性
 */
class Person{
    private String name;
    private int age;
}
public class test09 {
    public static void main(String[] args) {
        Class <?> c=null;
        try {
            c=Class.forName("cn.cast.reflect.Person");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Field[] f=c.getDeclaredFields();
        for(int i=0;i<f.length;i++){
            System.out.println(f[i]);
        }
    }
}

运行结果:
private java.lang.String cn.cast.reflect.Person.name
private int cn.cast.reflect.Person.age

getDeclaredFielsd()方法可以获取全部属性,getFields()只能获取公共属性
package cn.cast.reflect;

import java.lang.reflect.Field;

/*
 * 实例10:获取本类中属性的值
 */
class Person1{
    public String name;
    private int age;
    public Person1(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

}
public class test10 {
    public static void main(String[] args) throws Exception {
        Person1 p= new Person1("wangchen",18);
        Class<?> c=p.getClass();
        //获取公共属性的值
        Field f1=c.getField("name");
        //get(p)表明要获取的哪个对象的值
        String str=(String) f1.get(p);

        System.out.println("姓名:"+str);

        //获取私有属性的值
        Field f2=c.getDeclaredField("age");
        //age是私有属性,所以要设置安全检查为true
        f2.setAccessible(true);
        int age=(int)f2.get(p);
        System.out.println("年龄是:"+age);


    }
}

运行结果:
姓名:wangchen
年龄是:18
package cn.cast.reflect;

import java.lang.reflect.Field;

/*
 * 实例11:通过反射修改属性
 */
class Person2{
    private String name;

    public Person2(String name) {
        super();
        this.name = name;
    }

    @Override
    public String toString() {
        return "姓名是" + this.name;
    }

}
public class test11 {
    public static void main(String[] args) throws Exception {
        Person2 p=new Person2("wangchen");
        System.out.println(p);

        Class<?> c=p.getClass();

        //定义要修改的属性
        Field f=c.getDeclaredField("name");
        f.setAccessible(true);
        //修改属性,传入要设置的对象和值
        f.set(p, "xiaohua");
        System.out.println(p);

    }
}

运行结果:
姓名是wangchen
姓名是xiaohua

package cn.cast.reflect;

import java.lang.reflect.Method;

/*
 * 实例12:通过反射调用方法
 */
class Person3{
    public void print(int i){
        System.out.println("数字:"+i);

    }
    public static void say(String str){
        System.out.println("说:"+str);
    }
}
public class test12 {
    public static void main(String[] args) throws Exception {
        Person3 p=new Person3();
        Class<?> c=p.getClass();

        //GetMethod()方法需要传方法名和类型(数据类型.class)
        Method m1=c.getMethod("print", int.class);
        //invoke()表示调用的意思,需要传对象和参数
        m1.invoke(p, 10);

        Method m2=c.getMethod("say", String.class);
        //这里的null不由对象调用,也就是静态方法
        m2.invoke(null, "hehe");
    }
}

运行结果:
姓名是wangchen
姓名是xiaohua
package cn.cast.reflect;

import java.lang.reflect.Array;

/*
 * 实例13:通过反射操作数组
 */
public class test13 {
    public static void main(String[] args) {
        int [] arr={1,2,3,4,5};
        Class<?> c=arr.getClass().getComponentType();//返回的是数组元素的class
        System.out.println("数组类型:"+c.getName());
        int len=Array.getLength(arr);
        System.out.println("数组长度:"+len);
        System.out.println("遍历数组:");
        for(int i=0;i<len;i++){
            System.out.println(Array.get(arr, i));
        }
        System.out.println();
        //修改数组 
        System.out.println("修改前的第一个元素: " + Array.get(arr, 0));
        Array.set(arr, 0, 3);
        System.out.println("修改后的第一个元素: " + Array.get(arr, 0));
        for(int i=0;i<len;i++){
            System.out.println(Array.get(arr, i));
        }
    }
}

运行结果:
数组类型:int
数组长度:5
遍历数组:
1
2
3
4
5

修改前的第一个元素: 1
修改后的第一个元素: 3
3
2
3
4
5
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值