zoukankan      html  css  js  c++  java
  • 浅谈java放射机制

    java反射机制概念:

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

    2. JAVA反射(放射)机制 :程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。


    /**
    * 反射:就是通过.class文件对象,去使用该类的成员变量,构造方法,成员方法.
    *
    * Person p1=new Person();
    * p1.使用;
    * 这个就不是反射
    * @author Administrator
    *
    *要这样使用就必须获得class文件对象,也就是得到class类对象.
    *获取class类对象的方法
    * 1.getClass();
    * 2.数据类型的静态属性class
    * 3.class类中的静态方法,className要是全限定名
    * public static Class<?> forName(String className)

    *选择那种方法;
    * 自己随便,开发选择第三种,因为这种方式是一个字符串,而不是一个具体的类名,这样我们就可以把字串
    *配置到配置文件中
    */
    public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException {
    //方式一
    Person p1 = new Person();
    Class c1 = p1.getClass();

    Person p2=new Person();
    Class c2 = p2.getClass();

    System.out.println(p1==p2);//false
    System.out.println(c1==c2);//true

    //方式二
    Class c3=Person.class;
    //int.class;
    //String.class;
    System.out.println(c3==c2);//true;

    //方式三,
    Class c4=Class.forName("day13.Person");
    System.out.println(c4==c3);
    }
    }

    反射是框架设计的灵魂:

    [我还不懂,没去看过框架的源码,以后有机会回去看]  

    1.通过反射获取成员变量并使用:


    public class Reflect1 {
    public static void main(String[] args) throws Exception{
    //获取字节码对象
    Class c=Class.forName("day13.Person");

    /*//获取所有成员变量
    java.lang.reflect.Field[] fields=c.getDeclaredFields();
    for (java.lang.reflect.Field field : fields) {
    System.out.println(field);
    }*/

    //通过无参构造方法创建对象
    Constructor cons = c.getConstructor();
    Object obj=cons.newInstance();

    //获取单个成员变量
    //并对其赋值
    java.lang.reflect.Field addressFiled=c.getField("address");
    addressFiled.set(obj, "北京");//给obj对象的addressFiled设置值.
    System.out.println(obj);
    }
    }

    Person类:

    public class Person {
    private String name;
    private int age;
    public String address;

    //构造方法
    public Person(){

    }
    //成员方法
    Person(String name,Integer age){
    this.name=name;
    this.age=age;
    }
    public Person(String name,int age,String address){
    this.name=name;
    this.age=age;
    this.address=address;
    }
    public void show(){
    System.out.println("show");
    }
    public void method(String s){
    System.out.println("method"+s);
    }
    public String  method(String s,int i){
    return s+"---"+i;
    }
    private void function(){
    System.out.println("function");
    }

    @Override
    public String toString() {
    return "Person [name=" + name + ", age=" + age + ", address=" + address
    + "]";
    }

    }

    2.通过反射获取无参构造方法:


    public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
    //获取字节码对象
    Class c=Class.forName("day13.Person");

    //获取构造方法
    //public Constructor[] getConstructors(),获取的是public修饰的构造方法
    //public Constructor[] getDeclaredConstructors()返回所有

    /*Constructor[] cons=c.getDeclaredConstructors();
    for (Constructor constructor : cons) {
    System.out.println(constructor);
    }*/

    //获取单个构造方法
    Constructor cons=c.getConstructor();
    Object obj=cons.newInstance();
    System.out.println(obj);
    }
    }

    2.通过反射获取有参构造方法:

    public static void main(String[] args) throws Exception{
    //获取字节码对象
    Class c=Class.forName("day13.Person");
    //获取带参构造参数
    //public Constructor getConstructor(Class<?>... parameterTypes)
    Constructor con = c.getConstructor(String.class,int.class,String.class);

    //通过带参构造方法对象创建对象
    //public T newInstance(Object... initargs)
    Object obj=con.newInstance("海燕",23,"成都");
    System.out.println(obj);

    }
    }

    3.通过放射获取私有构造方法(加一个Declared):


    public class ReflectDemo3 {
    public static void main(String[] args) throws Exception{
    //获取字节码对象
    Class c=Class.forName("day13.Person");
    //获取带参构造函数
    Constructor cons = c.getDeclaredConstructor(String.class,Integer.class);

    cons.setAccessible(true);//值为 true则指示反射的对象在使用时应该取消 Java语言访问检查
    Object obj=cons.newInstance("海燕",23);
    System.out.println(obj);
    }
    }

    4.通过放射获取成员变量并调用

    package fanshe.field;
    import java.lang.reflect.Field;
    /*
    * 获取成员变量并调用:
    *
    * 1.批量的
    * 1).Field[] getFields():获取所有的"公有字段"
    * 2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
    * 2.获取单个的:
    * 1).public Field getField(String fieldName):获取某个"公有的"字段;
    * 2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
    *
    * 设置字段的值:
    * Field --> public void set(Object obj,Object value):
    * package fanshe.field;
    import java.lang.reflect.Field;
    /*
    * 获取成员变量并调用:
    *
    * 1.批量的
    * 1).Field[] getFields():获取所有的"公有字段"
    * 2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
    * 2.获取单个的:
    * 1).public Field getField(String fieldName):获取某个"公有的"字段;
    * 2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
    *
    * 设置字段的值:
    * Field --> public void set(Object obj,Object value):
    * 参数说明:
    * 1.obj:要设置的字段所在的对象;
    * 2.value:要为字段设置的值;
    *
    */
    public class Fields {

    public static void main(String[] args) throws Exception {
    //1.获取Class对象
    Class stuClass = Class.forName("fanshe.field.Student");
    //2.获取字段
    System.out.println("************获取所有公有的字段********************");
    Field[] fieldArray = stuClass.getFields();
    for(Field f : fieldArray){
    System.out.println(f);
    }
    System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");
    fieldArray = stuClass.getDeclaredFields(); for(Field f : fieldArray){ System.out.println(f); } System.out.println("*************获取公有字段**并调用***********************************"); Field f = stuClass.getField("name"); System.out.println(f); //获取一个对象 Object obj = stuClass.getConstructor().newInstance();//产生Student对象--》Student stu = new Student(); //为字段设置值 f.set(obj, "刘德华");//为Student对象中的name属性赋值--》stu.name = "刘德华" //验证 Student stu = (Student)obj; System.out.println("验证姓名:" + stu.name); System.out.println("**************获取私有字段****并调用********************************"); f = stuClass.getDeclaredField("phoneNum"); System.out.println(f); f.setAccessible(true);//暴力反射,解除私有限定 f.set(obj, "18888889999"); System.out.println("验证电话:" + stu); } }

    对应的student类


    package fanshe.field;

    public class Student {
    public Student(){

    }
    //**********字段*************//
    public String name;
    protected int age;
    char sex;
    private String phoneNum;

    @Override
    public String toString() {
    return "Student [name=" + name + ", age=" + age + ", sex=" + sex
    + ", phoneNum=" + phoneNum + "]";
    }


    }

    反射方法的其它使用之---通过反射越过泛型检查

    泛型用在编译期,编译过后泛型擦除(消失掉)。所以是可以通过反射越过泛型检查的 ,其实也就是在.class文件中没有泛型的概念的.


    public static void main(String[] args) throws Exception{
    ArrayList<String> 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);
    }
    }

    学习反射必须明白类加载:

    启动(Bootstrap)类加载器:java中jre中的类.

    扩展(Extension)类加载器:java扩展的api类ext好像是

    系统(System)类加载器:自己写的类

    https://www.2cto.com/uploadfile/Collfiles/20160126/2016012609242889.jpg

  • 相关阅读:
    第十二周学习进度条
    寻找水王
    第十一周进度条
    第十周进度条
    构建之法阅读笔记(二)
    第九周学习进度
    团队名字
    站立会议09
    站立会议08
    站立会议07
  • 原文地址:https://www.cnblogs.com/52haiyan/p/9490173.html
Copyright © 2011-2022 走看看