精华内容
下载资源
问答
  • 主要介绍了java通过反射创建对象调用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 通过反射创建对象的思路: 1.首次获取类的类对象,获取方式看前一篇博客。 2.调用类对象的newInstance()方法创建该类的实体对象。这是调用的类的默认构造器。 若想调用非默认的构造器创建实例对象,需要先通过...

    通过反射创建对象的思路:

    1.首次获取类的类对象,获取方式看前一篇博客。

    2.调用类对象的newInstance()方法创建该类的实体对象。这是调用的类的默认构造器。

    若想调用非默认的构造器创建实例对象,需要先通过class对象获取构造器,在用构造器调用newInstance()方法创建。

    例子:创建一个对象池,读取property文件,创建对象,spring依赖注入的基本原理也是这样实现

     

    调用方法为对象注入属性(注入):

    调用步骤:

    获取方法名和参数

    获取该方法的Method方法

    执行method.invoke(target,args);target为执行对象,即该类的实例对象,后面为参数

     

    读取的文件文件内容:

     

    补充:方法有访问权限,可以通过Method.setAccessible(boolean flag)设置调用该方法时是否检查访问权限,设为false则可以访问private方法。

     

    展开全文
  • Java试题-5:应用反射创建对象调用对象方法 反射为Java的高级技术应用
  • java基础-反射3(反射,反射创建对象,操作对象属性,调用对象方法)前面通过学习,我们了解的运行时类型信息的基本原理,以及通过Class对象和反射来获取运行时类型信息。下面来了解通过反射来创建对象,以及操作...

    java基础-反射3(反射,反射创建对象,操作对象属性,调用对象方法)

    前面通过学习,我们了解的运行时类型信息的基本原理,以及通过Class对象和反射来获取运行时类型信息。下面来了解通过反射来创建对象,以及操作对象的属性和方法

    首先还是创建一个person类

    
    @Service
    public class Person1 extends PersronParent implements PersonInterfance ,Cloneable{
        public  String name;
        public  double weight;
        protected  double height;
        private Integer age;
    
        public Person1(){}
    
        protected Person1(String name){
        }
        public void publicShow() throws Exception{
            System.out.println("publicShow()");
        }
        protected void disPlay(){
            System.out.println("disPlay()");
    
        }
    
        private String privateShow(String paramter1,String paramter2) throws NullPointerException{
            StringBuffer stringBuffer  = new StringBuffer(paramter1);
            return stringBuffer.append(paramter2).toString();
        }
        @Deprecated
        private int testParamter(String paramter1,String paramter2) throws NullPointerException{
            return 1;
        }
    
        @Deprecated
        public int testPublicParamter(String paramter1,String paramter2) throws NullPointerException{
            return 1;
        }
    
        @Override
        public void parentSay(){
            super.parentSay();
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public double getWeight() {
            return weight;
        }
    
        public void setWeight(double weight) {
            this.weight = weight;
        }
    
        public double getHeight() {
            return height;
        }
    
        public void setHeight(double height) {
            this.height = height;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", weight=" + weight +
                    ", height=" + height +
                    ", age=" + age +
                    '}';
        }

    通过反射来创建对象

    通常在java中我们有以下4中方式创建对象

    1. 通过new 关键字 创建对象
    2. 通过Object clone();方法
    3. 通过反序列化
    4. 通过反射创建

    这里我们来了解通过反射来创建对象和调用方法

    首先我们来看通过反射来创建对象
    我们通过newInstance()来创建对象,如果对于无参数的构造方法我们直接用Class的对象的newInstance()就可以创建对象
    如果对于有参数的构造方法,我们需要先获取带参数的构造器(注意权限修饰符),然后通过构造器的newInstance()方法创建对象。

    public class TestReflect {
    
        public static void main(String[] agrs){
    
                Class<Person> personClass = Person.class;
                try {
                    /**
                     * 通过无参数的构造方法创建对象
                     */
                    Person personOne =   personClass.newInstance();
                    /**
                     * 通过有参数的构造方法创建对象
                     */
                    Constructor constructor = personClass.getDeclaredConstructor(String.class);
                    Person personTwo =   (Person) constructor.newInstance("带参数");
    
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
    
        }
    
    }
    

    运行结果如下
    这里写图片描述

    这样我们就可以通过反射来创建对象。
    通过反射创建对象后可以通过反射来给操作对象的属性

    通过反射操作对象属性

    上一篇文章说过,类的属性在反射中使用java.lang.reflect.Field表示,当然也使用这个类来操作对象的属性,在java中属性的访问涉及到权限修饰的修饰,具体如下:
    这里写图片描述

    所以在操作对象的属性的需要注意对目标类属性访问的权限,如下
    如果当前类对目标对象有访问的权限(如目标类属性为public)

    1. 通过Class对象的getField()获取Field。
    2. 然后通过Field的set()方法对目标对象赋值。

    如果当前类对目标对象没有访问的权限(如目标类属性为private)

    1. 通过Class对象的getDeclaredField()获取Field。
    2. 调用Field 的setAccessible(true)方法,设置为可访问(如果不设置为true,则在当前类中不能访问目标类的属性,在为目标对象赋值时会报错)
    3. 然后通过Field的set()方法对目标对象赋值。
    4. 调用Field 的setAccessible(false)方法复原。

    具体操作如下

    public class TestFileId2 {
        public static void main(String agrs[]) throws NoSuchFieldException {
            try {
                //获取Class 对象
                Class<Person> personClass  = Person.class;
                //创建目标对象(注意,我们这里直接用的object,更体现了运行时类型信息)
                Object person = personClass.newInstance();
                //在没有通过反射赋值之前
                System.out.println("person对象在没有赋值之前");
                System.out.println(person.toString());
                System.out.println();
    
                System.out.println("当前类可以操作目标类的属性:比如public权限的属性");
                //获取有权限操作的属性(当前类可以操作目标对象的属性:比如public)
                Field name = personClass.getField("name");
                //为person 对象 的 name属性赋值为 TestName
                name.set(person,"TestName");
                System.out.println(person.toString());
                System.out.println();
    
                System.out.println("当前类不能够操作目标类的属性:比如private权限的属性");
                Field age = personClass.getDeclaredField("age");
                //为person 对象 的 age 属性设置为可访问
                age.setAccessible(true);
                //为person 对象 的 age属性赋值为 10
                age.set(person,10);
                age.setAccessible(false);
                System.out.println(person.toString());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    运行结果如下
    这里写图片描述

    通过反射调用对象方法

    反射能够操作对象的属性,当然也可以操作对象的方法,方法通过java.lang.reflect.Method表示,由于访问权限的限制,对于方法也有如下操作
    如果当前类对目标对象有访问的权限(如目标类方法为public)

    1. 通过Class对象的getMethod()获取Method。
    2. 然后通过Method的invoke()方法对目标对象赋值。

    如果当前类对目标对象没有访问的权限(如目标类方法为private)

    1. 通过Class对象的getDeclaredMethod()获取Method。
    2. 调用Method的setAccessible(true)方法,设置为可访问(如果不设置为true,则在当前类中不能访问目标类的方法,在调用目标类的方法时会报错)
    3. 然后通过Method的invoke()方法对目标对象赋值。
    4. 调用Method的setAccessible(false)方法复原。

    具体操作如下:

    public class TestMethod2 {
        public static void main(String agrs[]) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
            try {
                //获取Class 对象
                Class<Person> personClass = Person.class;
                //创建目标对象
                Object person = null;
                person = personClass.newInstance();
    
                System.out.println("当前类可以操作目标类的方法:比如public权限的方法");
                //获取有权限操作的方法(当前类可以操作目标对象的方法:比如public)
                Method publicShow = personClass.getMethod("publicShow");
                //通过Method 的invoke 调用person 的 publicShow方法
                publicShow.invoke(person);
    
    
                System.out.println("当前类不能够操作目标类的方法:比如private权限的方法");
                Method privateShow = personClass.getDeclaredMethod("privateShow", String.class, String.class);
                //为person 对象 的 privateShow 方法设置为可访问
                privateShow.setAccessible(true);
                //通过Method 的invoke 调用person 的 privateShow方法
                String result = (String) privateShow.invoke(person, "参数1", "参数2");
                System.out.println(result);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    
    }
    

    运行结果如下:
    这里写图片描述

    以上就是通过反射操作对象的基本方式。

    反射的基础知识就是以上几篇文章,反射相对于其他知识来说比较简单,但是反射应用很多,比如很多框架,以及java中的动态代理等都涉及到了,所以反射在java中还是很重要的。

    展开全文
  • java使用反射创建并操作对象方法

    千次阅读 2021-02-25 18:17:27
    Class 对象可以获得该类里的方法(由 Method 对象表示)、构造器(由 Constructor 对象表示)、成员变量...程序可以通过对象来执行对应的方法,通过 Constructor 对象调用对应的构造器创建实例,能通过 Field 对象直...

    Class 对象可以获得该类里的方法(由 Method 对象表示)、构造器(由 Constructor 对象表示)、成员变量(由 Field 对象表示),这三个类都位于 java.lang.reflect 包下,并实现了 java.lang.reflect.Member 接口。程序可以通过对象来执行对应的方法,通过 Constructor 对象来调用对应的构造器创建实例,能通过 Field 对象直接访问并修改对象的成员变量值。

    创建对象

    通过反射来生成对象需要先使用 Class 对象获取指定的 Constructor 对象,再调用 Constructor 对象的 newInstance() 方法来创建该 Class 对象对应类的实例。通过这种方式可以选择使用指定的构造器来创建实例。

    在很多 Java EE 框架中都需要根据配置文件信息来创建 Java 对象,从配置文件读取的只是某个类的字符串类名,程序需要根据该字符串来创建对应的实例,就必须使用反射。

    下面程序就实现了一个简单的对象池,该对象池会根据配置文件读取 key-value 对,然后创建这些对象,并将这些对象放入一个 HashMap 中。

    public class ObjectPoolFactory {

    // 定义一个对象池,前面是对象名,后面是实际对象

    private Map objectPool = new HashMap<>();

    // 定义一个创建对象的方法

    // 该方法只要传入一个字符串类名,程序可以根据该类名生成Java对象

    private Object createObject(String clazzName) throws Exception, IllegalAccessException, ClassNotFoundException {

    // 根据字符串来获取对应的Class对象

    Class> clazz = Class.forName(clazzName);

    // 使用clazz对应类的默认构造器创建实例

    return clazz.getConstructor().newInstance();

    }

    // 该方法根据指定文件来初始化对象池

    // 它会根据配置文件来创建对象

    public void initPool(String fileName)

    throws InstantiationException, IllegalAccessException, ClassNotFoundException {

    try (FileInputStream fis = new FileInputStream(fileName)) {

    Properties props = new Properties();

    props.load(fis);

    for (String name : props.stringPropertyNames()) {

    // 每取出一对key-value对,就根据value创建一个对象

    // 调用createObject()创建对象,并将对象添加到对象池中

    objectPool.put(name, createObject(props.getProperty(name)));

    }

    } catch (Exception ex) {

    System.out.println("读取" + fileName + "异常");

    }

    }

    public Object getObject(String name) {

    // 从objectPool中取出指定name对应的对象

    return objectPool.get(name);

    }

    public static void main(String[] args) throws Exception {

    ObjectPoolFactory pf = new ObjectPoolFactory();

    pf.initPool("obj.txt");

    System.out.println(pf.getObject("a")); // ①

    System.out.println(pf.getObject("b")); // ②

    }

    }

    上面程序中 createObject() 方法里的两行粗体字代码就是根据字符串来创建 Java 对象的关键代码,程序调用 Class 对象的 newInstance() 方法即可创建一个 Java 对象。程序中的 initPool() 方法会读取属性文件,对属性文件中每个 key-value 对创建一个 Java 对象,其中 value 是该 Java 对象的实现类,而 key 是该 Java 对象放入对象池中的名字。为该程序提供如下属性配置文件。

    a=java.util.Date

    b=javax.swing.JFrame

    编译、运行上面的 ObjectPoolFactory 程序,执行到 main 方法中的①号代码处,将看到输出系统当前时间——这表明对象池中已经有了一个名为a的对象,该对象是一个 java.util.Date 对象。执行到②号代码处,将看到输出一个 JFrame 对象。

    提示:这种使用配置文件来配置对象,然后由程序根据配置文件来创建对象的方式非常有用,大名鼎鼎的 Spring 框架就采用这种方式大大简化了 Java EE 应用的开发。当然,Spring 采用的是 XML 配置文件——毕竟属性文件能配置的信息太有限了,而 XML 配置文件能配置的信息就丰富多。

    如果不想利用默认构造器来创建 Java 对象,而想利用指定的构造器来创建 Java 对象,则需要利用 Constructor 对象,每个 Constructor 对应一个构造器。为了利用指定的构造器来创建 Java 对象,需要如下三个步骤。

    获取该类的 Class 对象。

    利用 Class 对象的 getConstructor() 方法来获取指定的构造器。

    调用 Constructor 的 newInstance() 方法来创建 Java 对象。

    下面程序利用反射来创建一个 JFrame 对象,而且使用指定的构造器。

    public class CreateJFrame {

    public static void main(String[] args) throws Exception {

    // 获取JFrame对应的Class对象

    Class> jframeClazz = Class.forName("javax.swing.JFrame");

    // 获取JFrame中带一个字符串参数的构造器

    Constructor ctor = jframeClazz.getConstructor(String.class);

    // 调用Constructor的newInstance方法创建对象

    Object obj = ctor.newInstance("测试窗口");

    // 输出JFrame对象

    System.out.println(obj);

    }

    }

    上面程序中第一行粗休字代码用于获取 JFrame 类的指定构造器,前面已经提到:如果要唯一地确定某类中的构造器,只要指定构造器的形参列表即可。第一行粗体字代码获取构造器时传入了一个 String 类型,即表明想获取只有一个字符串参数的构造器。

    程序中第二行粗体字代码使用指定构造器的 newInstance() 方法来创建一个 Java 对象,当调用 Constructor 对象的 newInstance() 方法时通常需要传入参数,因为调用 Constructor 的 newInstance() 方法实际上等于调用它对应的构造器,传给 newInstance() 方法的参数将作为对应构造器的参数。

    对于上面的 CreateFrame.java 中已知 java.swing.JFrame 类的情形,通常没有必要使用反射来创建该对象,毕竟通过反射创建对象时性能要稍低一些。实际上,只有当程序需要动态创建某个类的对象时才会考虑使用反射,通常在开发通用性比较广的框架、基础平台时可能会大量使用反射。

    调用方法

    当获得某个类对应的 Class 对象后,就可以通过该 Class 对象的 getMethods() 方法或者 getMethod()方法来获取全部方法或指定方法——这两个方法的返回值是 Method 数组,或者 Method 对象。

    每个 Method 对象对应一个方法,获得 Method 对象后,程序就可通过该 Method 来调用它对应的方法。在 Method 里包含一个 Invoke() 方法,该方法的签名如下。

    Object invoke(Object obj, Object...args):该方法中的 obj 是执行该方法的主调,后面的 args 是执行该方法时传入该方法的实参。

    下面程序对前面的对象池工厂进行加强,允许在配置文件中增加配置对象的成员变量的值,对象池工厂会读取为该对象配置的成员变量值,并利用该对象对应的 setter 方法设置成员变量的值。

    public class ExtendedObjectPoolFactory {

    // 定义一个对象池,前面是对象名,后面是实际对象

    private Map objectPool = new HashMap<>();

    private Properties config = new Properties();

    // 从指定属性文件中初始化Properties对象

    public void init(String fileName) {

    try (FileInputStream fis = new FileInputStream(fileName)) {

    config.load(fis);

    } catch (IOException ex) {

    System.out.println("读取" + fileName + "异常");

    }

    }

    // 定义一个创建对象的方法

    // 该方法只要传入一个字符串类名,程序可以根据该类名生成Java对象

    private Object createObject(String clazzName) throws Exception {

    // 根据字符串来获取对应的Class对象

    Class> clazz = Class.forName(clazzName);

    // 使用clazz对应类的默认构造器创建实例

    return clazz.getConstructor().newInstance();

    }

    // 该方法根据指定文件来初始化对象池

    // 它会根据配置文件来创建对象

    public void initPool() throws Exception {

    for (String name : config.stringPropertyNames()) {

    // 每取出一个key-value对,如果key中不包含百分号(%)

    // 这就表明是根据value来创建一个对象

    // 调用createObject创建对象,并将对象添加到对象池中

    if (!name.contains("%")) {

    objectPool.put(name, createObject(config.getProperty(name)));

    }

    }

    }

    // 该方法将会根据属性文件来调用指定对象的setter方法

    public void initProperty() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {

    for (String name : config.stringPropertyNames()) {

    // 每取出一对key-value对,如果key中包含百分号(%)

    // 即可认为该key用于控制调用对象的setter方法设置值

    // %前半为对象名字,后半控制setter方法名

    if (name.contains("%")) {

    // 将配置文件中的key按%分割

    String[] objAndProp = name.split("%");

    // 取出调用setter方法的参数值

    Object target = getObject(objAndProp[0]);

    // 获取setter方法名:set + "首字母大写" + 剩下部分

    String mtdName = "set" + objAndProp[1].substring(0, 1).toUpperCase() + objAndProp[1].substring(1);

    // 通过target的getClass()获取它的实现类所对应的Class对象

    Class> targetClass = target.getClass();

    // 获取希望调用的setter方法

    Method mtd = targetClass.getMethod(mtdName, String.class);

    // 通过Method的invoke方法执行setter方法

    // 将config.getProperty(name)的值作为调用setter方法的参数

    mtd.invoke(target, config.getProperty(name));

    }

    }

    }

    public Object getObject(String name) {

    // 从objectPool中取出指定name对应的对象

    return objectPool.get(name);

    }

    public static void main(String[] args) throws Exception {

    ExtendedObjectPoolFactory epf = new ExtendedObjectPoolFactory();

    epf.init("extObj.txt");

    epf.initPool();

    epf.initProperty();

    System.out.println(epf.getObject("a"));

    }

    }

    上面程序中 initProperty() 方法里的第一行粗体字代码获取目标类中包含一个 String 参数的 setter 方法,第二行粗体字代码通过调用 Method 的 invoke() 方法来执行该 setter 方法,该方法执行完成后,就相当于执行了目标对象的 setter 方法。为上面程序提供如下配置文件。

    a=javax.swing.JFrame

    b=javax.swing.JLabel

    #set the title of a

    a%title=Test Title

    上面配置文件中的 a%title 行表明希望调用a对象的 setTitle() 方法,调用该方法的参数值为 Test Title。编译、运行上面的 ExtendedObjectPoolFactory.java 程序,可以看到输出一个 JFrame 窗口,该窗口的标题为 Test Title。

    提示:Spring 框架就是通过这种方式将成员变量值以及依赖对象等都放在配置文件中进行管理的,从而实现了较好的解耦。这也是 Spring 框架的 IOC 的秘密。

    当通过 Method 的 invoke() 方法来调用对应的方法时,Java 会要求程序必须有调用该方法的权限。如果程序确实需要调用某个对象的 private 方法,则可以先调用 Method 对象的如下方法。

    setAccessible(boolean flag):将 Method 对象的 accessible 设置为指定的布尔值。值为true,指示该 Method 在使用时应该取消 Java 语言的访问权限检查:值为false,则指示该 Method 在使用时要实施 Java 语言的访问权限检查。

    注意:实际上,setAccessible() 方法并不属于 Method,而是属于它的父类 AccessibleObject。因此 Method、Constructor、Field 都可调用该方法,从而实现通过反射来调用 private 方法、private 构造器和成员变量,下一节将会让读者看到这种示例。也就是说,它们可以通过调用该方法来取消访问权限检查,通过反射即可访问 private 成员。

    访问成员变量值

    通过 Class 对象的 getFields() 或 getField() 方法可以获取该类所包括的全部成员变量或指定成员变量。Field 提供了如下两组方法来读取或设置成员变量值。

    getXxx(Object obj):获取 obj 对象的该成员变量的值。此处的 Xxx 对应8种基本类型,如果该成员变量的类型是引用类型,则取消 get 后面的Xxx。

    setXxx(Object obj, Xxx val):将 obj 对象的该成员变量设置成值。此处的 Xxx 对应8种基本类型,如果该成员变量的类型是引用类型,则取消 set 后面的Xxx。

    使用这两个方法可以随意地访问指定对象的所有成员变量,包括 private 修饰的成员变量。

    class Person {

    private String name;

    private int age;

    public String toString() {

    return "Person[name:" + name + " , age:" + age + " ]";

    }

    }

    public class FieldTest {

    public static void main(String[] args) throws Exception {

    // 创建一个Person对象

    Person p = new Person();

    // 获取Person类对应的Class对象

    Class personClazz = Person.class;

    // 获取Person的名为name的成员变量

    // 使用getDeclaredField()方法表明可获取各种访问控制符的成员变量

    Field nameField = personClazz.getDeclaredField("name");

    // 设置通过反射访问该成员变量时取消访问权限检查

    nameField.setAccessible(true);

    // 调用set()方法为p对象的name成员变量设置值

    nameField.set(p, "Yeeku.H.Lee");

    // 获取Person类名为age的成员变量

    Field ageField = personClazz.getDeclaredField("age");

    // 设置通过反射访问该成员变量时取消访问权限检查

    ageField.setAccessible(true);

    // 调用setInt()方法为p对象的age成员变量设置值

    ageField.setInt(p, 30);

    System.out.println(p);

    }

    }

    上面程序中先定义了一个 Person 类,该类里包含两个 private 成员变量:name 和 age,在通常情况下,这两个成员变量只能在 Person 类里访问。但本程序 FieldTest 的 main() 方法中6行粗体字代码通过反射修改了 Person 对象的 name、age 两个成员变量的值。

    第一行粗体字代码使用 getDeclaredField() 方法获取了名为 name 的成员变量,注意此处不是使用 getField()方法,因为 getField() 方法只能获取 public 访问控制的成员变量,而 getDeclaredField() 方法则可以获取所有的成员变量;第二行粗体字代码则通过反射访问该成员变量时不受访问权限的控制;第三行粗体字代码修改了 Person 对象的 name 成员变量的值。修改 Person 对象的 age 成员变量的值的方式与此完全相同。

    编译、运行上面程序,会看到如下输出:

    Person[name:Yeeku.H.Lee , age:30 ]

    操作数组

    在 java.lang.reflect 包下还提供了一个 Array 类,Array 对象可以代表所有的数组。程序可以通过使用 Array 来动态地创建数组,操作数组元素等。

    Array 提供了如下几类方法。

    static Object newInstance(Class> componentType,int...length):创建一个具有指定的元素类型、指定维度的新数组。

    static xxx getXxx(Object array, int index):返回 array 数组中第 index 个元素。其中是各种基本数据类型,如果数组元素是引用类型,则该方法变为 get(Object array, int index)。

    static void setXxx(Object array, int index, xxx val):将 array 数组中第 index 个元素的值设为 val。其中 xxx 是各种基本数据类型,如果数组元素是引用类型,则该方法变成 set(Object array, int index, Object val)。

    下面程序示范了如何使用 Array 来生成数组,为指定数组元素赋值,并获取指定数组元素的方式。

    public class ArrayTest1 {

    public static void main(String args[]) {

    try {

    // 创建一个元素类型为String ,长度为10的数组

    Object arr = Array.newInstance(String.class, 10);

    // 依次为arr数组中index为5、6的元素赋值

    Array.set(arr, 5, "疯狂Java讲义");

    Array.set(arr, 6, "轻量级Java EE企业应用实战");

    // 依次取出arr数组中index为5、6的元素的值

    Object book1 = Array.get(arr, 5);

    Object book2 = Array.get(arr, 6);

    // 输出arr数组中index为5、6的元素

    System.out.println(book1);

    System.out.println(book2);

    } catch (Throwable e) {

    System.err.println(e);

    }

    }

    }

    上面程序中三行粗体字代码分别是通过 Array 创建数组,为数组元素设置值,访问数组元素的值的示例代码,程序通过使用 Array 就可以动态地创建并操作数组。

    下面程序比上面程序稍微复杂一点,下面程序使用 Array 类创建了一个三维数组。

    public class ArrayTest2 {

    public static void main(String args[]) {

    /*

    * 创建一个三维数组。 根据前面介绍数组时讲的:三维数组也是一维数组, 是数组元素是二维数组的一维数组,

    * 因此可以认为arr是长度为3的一维数组

    */

    Object arr = Array.newInstance(String.class, 3, 4, 10);

    // 获取arr数组中index为2的元素,该元素应该是二维数组

    Object arrObj = Array.get(arr, 2);

    // 使用Array为二维数组的数组元素赋值。二维数组的数组元素是一维数组,

    // 所以传入Array的set()方法的第三个参数是一维数组。

    Array.set(arrObj, 2, new String[] { "疯狂Java讲义", "轻量级Java EE企业应用实战" });

    // 获取arrObj数组中index为3的元素,该元素应该是一维数组。

    Object anArr = Array.get(arrObj, 3);

    Array.set(anArr, 8, "疯狂Android讲义");

    // 将arr强制类型转换为三维数组

    String[][][] cast = (String[][][]) arr;

    // 获取cast三维数组中指定元素的值

    System.out.println(cast[2][3][8]);

    System.out.println(cast[2][2][0]);

    System.out.println(cast[2][2][1]);

    }

    }

    上面程序的第一行粗体字代码使用 Array 创建了一个三维数组,程序中较难理解的地方是第二段粗体字代码部分,使用 Array 为 arrObj 的指定元素赋值,相当于为二维数组的元素赋值。由于二维数组的元素是一维数组,所以程序传入的参数是一个一维数组对象。

    运行上面程序,将看到 cast[2][3][8]、cast[2][2][0]、cast[2][2][1] 元素都有值,这些值就是刚才程序通过反射传入的数组元素值。

    以上就是java使用反射创建并操作对象的方法的详细内容,更多关于JAVA 反射创建并操作对象的资料请关注脚本之家其它相关文章!

    展开全文
  • Java 反射创建get set方法及反射方法调用
  • 例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。 1.2 反射常用类 Class类—可获取类和类的成员信息 Field类—可访问类的属性 Method...

    一.反射的概念

    1.1什么是反射?

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

    1.2 反射常用类

    • Class类—可获取类和类的成员信息
    • Field类—可访问类的属性
    • Method类—可调用类的方法
    • Constructor类—可调用类的构造方法

    ** 1.3 使用反射的基本步骤**

    ​ 1.导入java.lang.reflect.*

    ​ 2.获得需要操作的类的Java.lang.Class对象

    ​ 3.调用Class的方法获取Field、Method等对象

    ​ 4.使用反射API进行操作(设置属性﹑调用方法)

    二.Class类

    2.1 Class类是反射机制的起源和入口

    • 每个类都有自己的Class对象
    • 提供了获取类信息的相关方法
    • Class类继承自Object类

    2.2 Class类存放类的结构信息

    • 类名
    • 父类﹑接口
    • 方法﹑构造方法﹑属性
    • 注释
      2.3 获取Class类的三种方式
      1.直接类型.class 例如:
     Class<?> clazz1 = Student.class;//括号泛型可以写Student
    

    2.先创建对象,然后用对象引用来创建

     Student student=new Student();
     Class<?> clazz = student.getClass();
    

    3.Class.forName()创建(推荐使用

     Class<?> clazz2 = Class.forName("night.Student");//注意这里需要写入对象全路径名
    

    2.4 获取类的其他结构

    Class clazz = Class.forName("java.lang.Object");
    Field fields[ ] = clazz.getDeclaredFields();//获取Field 对象 (即类的属性)
    Method methods[] = clazz.getDeclaredMethods();//获取Method 对象 (方法)
    Constructor constructors[] = clazz.getDeclaredConstructors();//获取Constructor对象 (构造方法)
    

    下面来一段代码 帮助我们更好的理解反射:

    public class Demo1 {
        public static void main(String[] args) throws Exception{
            //获取student的类对象(三种方式)
            //方法一
            Student student=new Student();
            Class<?> clazz = student.getClass();
            //方法二
            Class<?> clazz1 = Student.class;
            //方法三
            Class<?> clazz2 = Class.forName("night.Student");
    
         //获取clazz的带参构造方法
            Constructor<?> constructor = clazz.getConstructor(String.class, int.class, String.class);
            //使用带参构造创建对象
            Object zhangsan = constructor.newInstance("张三", 23, "男");
            //获取一个为无参的方法  Student中的show方法  
            Method show = clazz.getMethod("show");
            //调用  zhangsan对象的show方法   相当于zhangsan.show();的写法
            show.invoke(zhangsan);//姓名张三  年龄23   性别男
    
           //这个方法是获取clazz本类中所有的私有方法,返回的是一个数组
           //  Method[] declaredMethods = clazz.getDeclaredMethods();
    
           //获取clazz类中所有的公开方法,包括从父类中集成的方法  返回是一个数组
           //  Method[] declaredMethods = clazz.geMethods();
    
           //获取本类中私有属性name   参数写属性的名字
            Field name = clazz.getDeclaredField("name");
            //若修改该类属性 必须调用.setAccessible(true)  设置成true  表示将私有修饰符去掉
            name.setAccessible(true);
            
            //这里相当于zhangsan.name="张三";  
            name.set(zhangsan,"张三");
            
            Field age = clazz.getDeclaredField("age");
            age.setAccessible(true);
            age.set(zhangsan,23);
            
            Field sex = clazz.getDeclaredField("sex");
            sex.setAccessible(true);
            sex.set(zhangsan,"女");
            
          //获取zhangsan的age属性   由于前面没有设置泛型因此返回的是Object类型  需要强转
           // Integer age = (Integer) field.get(zhangsan);
    
         
            System.out.println(zhangsan);
            
            //下面两种输出是一样的
             System.out.println(sex);
            System.out.println(sex.get(zhangsan));
    
        }
    }
    

    这是Student类

    public class Student {
        private String name;
        private int age;
        private String sex;
    
        public Student(String name, int age, String sex) {
            this.name = name;
            this.age = age;
            this.sex = sex;
        }
    
        public Student() {
        }
        public void show(){
            System.out.println("姓名"+name+"  年龄"+age+"   性别"+sex);
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", sex='" + sex + '\'' +
                    '}';
        }
     public static void print(){
            System.out.println("这是一个静态方法");
        }
        public String printInfo(){
            return name+" "+age+" "+" "+sex;
        }
    }
    

    另外 当类中有静态方法和有带有返回值的方法时候 比如学生类中的 public static void print() 静态方法 在反射的时候 直接调用就行了 里面不用写对象引用 相当于Student.print(); 因为clazz就是Student的类对象嘛

      Method print = clazz.getMethod("print");
      print.invoke(null);
    

    调用有返回值的方法 返回值类型不指定的话为Object类型

    Method printInfo = clazz.getMethod("printInfo");
    Object value = printInfo.invoke(zhangsan);//相当于  zhangsan.printInfo();
      System.out.println(value);//打印的value值为方法返回的值
    
    
    展开全文
  • PHP利用反射实现对象调用方法

    千次阅读 2018-10-05 15:40:36
    写个例子: &lt;?php class Test { function phone() { return '13888888888'; } function user($name,$sex) { return '我是'.$name.',性别'.$sex;...//调用phone方法 $obj = new Test; $med =...
  • 反射创建对象 当我们反射创建对象,一般采用 Class clazz = Class.forName("java.lang.String"); Object instance = c.newInstance(); 这样创建对象,但这样默认是用无参的构造函数,当我们想通过反射调用...
  • 反射:使用反射调用构造器创建对象

    千次阅读 2017-07-03 13:01:17
    为什么使用反射创建对象,为什么不直接来new呢? 在框架中,提供给我们的都是字符串. ----------------------------------------------------------- 使用反射创建对象: 步骤:  1);找到构造器所在类的字节码对象....
  • java通过反射创建对象的两种方式与区别 1.使用Class对象的newInstance()方法来创建对象: 具体步骤是: 1、获取类的Class对象(有三种方式可以获取,可以自行百度一下) 2、通过调用所获取到的Class对象的newInstance...
  • 以上是反射对象中不存在注入的情况下可以使用的方法,一旦涉及到注入的时候,直接使用clazz.newInstance()会导致原本对象中注入的内容变为空值,这里需要通过spring去获取对象bean。 package test ; import ...
  • 一.Java反射拿到调用对象方法 1.通过Class.forName(“包名+方法的类名”)拿到方法对象; 如:Class&lt;?&gt; clazz = Class.forName("ReflectionTest");  也可以通过实例,获取方法对象...
  • java 中通过反射创建对象
  • 首先创建一个类public class ReflectDemo { private int m=0; //私有属性 private ReflectDemo(){ //私有无参构造函数 } public ReflectDemo(int aa){ //有参构造函数 } private int add(int a,int b){ //私有方法
  • java通过反射创建对象的两种方式

    千次阅读 2019-03-07 15:44:05
    在java中,通过反射创建对象有两种方式 使用Class对象的newInstance()方法来创建对象; 具体步骤是 1、获取类的Class对象(有三种方式可以获取,可以自行百度一下) 2、通过调用所获取到的Class对象的newInstance...
  • 通常情况下在父类中不能直接调用子类中的方法(重写的除外),但是在某些特殊的情况下,需要根据一个父类的对象调用子类的方法,原理就使用java的反射原理。例如:Person类,有一个name属性 public class Person { ...
  • C# 反射详解 定义 动态创建对象调用实例方法 1、反射的定义及功能介绍:审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个...
  • golang 通过反射创建对象

    千次阅读 2019-10-23 15:43:41
    废话少说,直接贴代码 type A struct { Name string } // 测试unit func TestReflect(t *testing.T) { ...//反射创建对象。 func reflectNew(target interface{}) { if target == nil { fmt.Printl...
  • 前言 使用反射,我们可以很容易地在运行时调用...另外我还可以直接创建对象,即使这个对象的类型在编译时还不知道。 反射的用途: (1)使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及从此程序
  • 初学反射,在个人理解中,他的主要目的是为了让系统实现可扩展 可配置。 反射+配置文件+工厂 为例 先来一个接口类 public interface IShowFun ...一个集成该接口的方法 public class ShowGirlFun:IShowFun {
  • 在 Java 中如果我们使用 new 关键字调用构造函数对类进行实例化,我们就可以根据在这个类中的修饰符来访问类中定义的非私有方法。但是如果需要在其他类调用私有的方法,就可以利用 Java 中提供的反射来实现。
  • 1、创建一个实体类 package adtec.reflect; public class Person { String name; public String getName() { return name; } public void setName(String name) { this.name = name; } ...
  • 在VS.Net中,有很多种方法动态调用对象的构造函数。一是通过Activator类的CreateInstance()方法。这个方法我们在Remoting中...(还有其他重载方法)注意它的返回值为object,MSDN对返回值的描述是:对新创建对象的引用
  • 利用反射创建对象的几种方式

    千次阅读 2019-05-23 15:50:42
    创建对象 1.使用Class对象的newInstance()方法来创建类的实例,这种方式要求该Class对象的对应类有默认构造器,执行newInstance()实际上是利用默认构造器来创建该类的实例。 2.先使用Class对象获取到Constructor对象...
  • /** * @author 万星明 * @version 创建时间:...public class 反射调用对象方法 { public static void main(String[] args) throws Exception { //创建反射对象 Class&lt;?&gt; clazz = Class.fo...
  • 利用反射创建对象的三种方式

    万次阅读 2019-05-23 15:13:36
    源头:获取Class对象,用三种方式 phone iPhone=new phone(); //1.1.对象.getClass();获取对象 Class<?> clazz1 = iPhone.getClass(); //1.2.类.class clazz1=phone.class; //1.3.C...
  • C#利用反射机制创建对象

    千次阅读 2019-09-25 14:47:11
    反射可以有很多方法,编写程序时请先导入 System.Reflection 命名空间。 1、假设你要反射一个 DLL 中的类,并且没有引用它(即未知的类型): Assembly assembly = Assembly.LoadFile("程序集路径,不能是相对路径...
  • 这里演示,通过反射创建默认构造方法的实例对象,和带参数的构造方法的实例对象。 案例实战 1. 反射访问默认构造方法,创建类实例对象 大概思路如下: 先在类中构建一个默认的构造方法 然后获取到Cl...
  • Java通过反射创建对象

    千次阅读 2016-11-13 23:28:35
    通过反射创建对象 创建对象之前,我们必须先知道要为哪个类创建对象。我们需要拿到这个类的全路径名。类似java.lang.String,除此之外我们还需要知道这个类的构造函数,是否有参数,参数的类型各是什么。下面分两种...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 238,164
精华内容 95,265
关键字:

反射创建对象调用方法