美文网首页
2019-04-16

2019-04-16

作者: 凨茗 | 来源:发表于2019-04-16 22:18 被阅读0次

    Java使用反射机制生成对象的3种方式

    一、在构造函数为空的情况下

    普通对象Book,构造函数为空的情况下

    Class Book{
        public Book(){
        System.out.println("初始化Book,无参构造函数!");
        }
      @Override
      public String toString(){
        System.out.println("这是一本书!“);
      }
    }
    

    1.使用对象的getClass方法

    public class TestBook{  //测试方法
      public static void main(String[] args) throws Exception{
        Book b = new Book();
        Class<?> cls = b.getClass();
        Object obj = cls.newInstance();         //进行实例化
        Book book = (Book)obj;
        System.out.println(book);
      }
    }
    

    2.使用"类.class"取得

    public class TestBook{  //测试方法
      public static void main(String[] args) throws Exception{
        Class<?> cls = Book.Class;
        Object obj = cls.newInstance();
        Book book = (Book)obj;
        System.out.println(book);
      }
    }
    

    3.调用Class对象提供的方法Class.forname

    public class TestBook{  //测试方法
      public static void main(String[] args) throws Exception{
        Class<?> cls = Class.forName("Book");
        Object obj = cls.newInstance();
        Book book = (Book)obj;
        System.out.println(book);
      }
    }
    

    此时可以不使用import导入一个明确的类,可以使用字符串的方式进行描述

    二、在构造函数不为空的情况下

    普通对象Book,构造函数不为空的情况下

    Class Book{
        private Stirng title ; 
        String double price;
        
        public Book(String title ,double price){
        this.title = title ; 
        this.price = price ;
        }
      @Override
      public String toString(){
        System.out.println("图书:“+this.title+ ",价格:"+this.price);
      }
    }
    

    此时不能直接调用getInstance 方法进行实例化,需要使用getConstructor方法,返回的是Constructor对象

    具体如下

    public class TestBook{
      public static void main(String[] args){
        Class<?> cls = Class.forName("Book");
        Construcotr<?> con = cls.getConstructor(String.class,double.class);//参数的类型定位
        Object obj = con.newInstance("Hadoop",49.9);  //里面是构造函数的参数
        System.out.println(obj); 
      }
    }
    

    所以最好在类中提供无参构造方法最好

    三、反射调用方法

    基本的对象Book

    Class Book{
        private String title;
        public void setTitle(String title)(){
        this.tile=title;
        }
        public String getTitle(){
        return title;
        }
    }
    

    在Class类中有以下几种取得类中方法的操作

    • 取得全部方法getMethods
    • 取得一个方法getMethod

    以上方法返回的java.reflect.Method类的对象,在这个类中重点关注一个方法

    • 调用方法public Object invoke(Object obj, Object…args)

    反射调用

    import java.lang.reflect.Method;
    public class TestBook{  //测试方法
      public static void main(String[] args) throws Exception{
        Class<?> cls = Class.forName("Book");
        Object obj = cls.newInstance(); //必须实例化对象才能调用方法
        Method  setMet= cls.getMethod("setTitle",String.class);
        Method  getMet= cls.getMethod("getTitle");
        setMet.invoke(obj,"java开发"); //等价于:Book类对象.setTitle(“java开发”)
        System.out.println(getMet.invoke(obj));
      }
    }
    

    四.反射调用成员

    类中的属性一定要在本类实例化对象产生之后才能分配内存空间。在class类里面提供有取得成员的方法:

    • 取得全部成员 public Field[] getDeclaredFields()
    • 取得指定成员 public Field getDeclaredField(String name)

    返回的类型java.lang.reflect.Field类,在这两个类中有两个重要的方法

    • 取得属性内容:public Object get(Object obj)
    • 设置属性内容:public Object set(Object obj, Object value)

    基本对象Book

    Class Book{
        public Book(){
            private String title;
      }
    }
    

    取得对象和设置对象

    import java.lang.reflect.Field;
    public class TestBook{  //测试方法
      public static void main(String[] args) throws Exception{
        Class<?> cls = Class.forName("Book");
        Object obj = cls.newInstance(); //必须实例化对象才能调用方法
        Field titleField = cls.getDeclaredField("title");
        titleField.set(obj,"java开发");//相当于:Book.title="java开发"
        System.out.println(titleField.get(obj))
      }
    }
    

    此时会提示错误,因为title是私有的属性

    在java.lang.reflect.AccessibleObject类下面(jdk1.8之后修改)

    • Executable:下面继续继承了Constructor、Method

    • Field:在这个类里面提供了:public void setAccessible(boolean flag)方法。用来设置是否封装,此时

      import java.lang.reflect.Field;
      public class TestBook{    //测试方法
        public static void main(String[] args) throws Exception{
          Class<?> cls = Class.forName("Book");
          Object obj = cls.newInstance(); //必须实例化对象才能调用方法
          Field titleField = cls.getDeclaredField("title");
          titleField.setAccessible(true);//封装取消了
          titleField.set(obj,"java开发");//相当于:Book.title="java开发"
          System.out.println(titleField.get(obj))
        }
      }
      

      此时就不会出错了,构造方法和普通的方法也可以取消封装,但是一般不这样做。所以属性设置最好还是使用setter和getter方法

    相关文章

      网友评论

          本文标题:2019-04-16

          本文链接:https://www.haomeiwen.com/subject/wmfwwqtx.html