0
点赞
收藏
分享

微信扫一扫

反射创建对象

1. 反射创建对象  725

1.方式一: 调用类中的public修饰的无参构造器

2.方式二:调用类中的指定构造器

3. Class类相关方法

newInstance :调用类中的无参构造器,获取对应类的对象

getConstructor(as.clazz):根据参数列表,获取对应的public构造器对象

getDecalaredConstructor(Class..clazz):根据参数列表,获取对应的所有构造器对象

4. Constructor类相关方法

setAccessible:暴破

newInstance(Object..obj):调用构造器

1.1 案例演示  725

测试 1:通过反射创建某类的对象,要求该类中必须有 public 的无参构造 

测试 2:通过调用某个特定构造器的方式,实现创建某类的对象

代码在com.stulzl.reflection_create_instance包中

ReflectionCreateInstance

package com.stulzl.reflection_create_instance;

import jdk.nashorn.internal.ir.CallNode;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

//反射创建对象  725
//测试 1:通过反射创建某类的对象,要求该类中必须有 public 的无参构造
//测试 2:通过调用某个特定构造器的方式,实现创建某类的对象
public class ReflectionCreateInstance {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //1.先获取User的Class对象
        Class userClass = Class.forName("com.stulzl.reflection_create_instance.User");

        //2.通过public的无参构造器创建实例
        Object o = userClass.newInstance();
        System.out.println(o);//User [age=10, name=中国]

        //3.通过public的有参构造器创建实例
        /*
            constructor 对象就是
            public User(String name) {//public 的有参构造器
                this.name = name;
            }
        */
        //先得到对应的构造器
        Constructor constructor = userClass.getConstructor(String.class);
        //再创建实例,传入实参
        Object china = constructor.newInstance("China");
        System.out.println("China="+china);

        //4.通过非public的有参构造器创建实例
        //得到对应的private构造器
        Constructor constructor1 = userClass.getDeclaredConstructor(int.class, String.class);
        //创建实例,传入参数
        constructor1.setAccessible(true);//爆破,使用反射可以访问private构造器
        Object user2 = constructor1.newInstance(100, "世界");
        System.out.println("user2="+user2);

    }
}
class User { //User 类
    private int age = 10;
    private String name = "中国";

    public User() {//无参 public
    }

    public User(String name) {//public 的有参构造器
        this.name = name;
    }

    private User(int age, String name) {//private 有参构造器
        this.age = age;
        this.name = name;
    }

    public String toString() {
        return "User [age=" + age + ", name=" + name + "]";
    }
}

2. 通过反射访问类中的成员   726

2.1 访问属性

1.根据属性名获取Field对象

Field f = clazz对象.getDeclaredField(属性名);

2. 暴破: f.setAccessible(true); //f是Field

3.访问

f.set(o,值); // o 表示对象

syso(f.get(o))// o 表示对象

4. 注意:如果是静态属性,则set和get中的参数o,可以写成null

2.2 案例演示  726

代码在com.stulzl.reflection_access_property包中

ReflectionAccessProperty

package com.stulzl.reflection_access_property;

import java.lang.reflect.Field;

//通过反射访问类中的成员  访问属性   726
public class ReflectionAccessProperty {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        //得到Student类对应的Class对象
        Class stuClass = Class.forName("com.stulzl.reflection_access_property.Student");
        //2.创建对象
        Object o = stuClass.newInstance();
        System.out.println(o.getClass());//运行类型Student
        //3.使用反射得到age属性对象
        Field age = stuClass.getField("age");
        age.set(o,88);
        System.out.println(o);//Student [age=88, name=null]
        //也可以这样返回
        System.out.println(age.get(o));//88

        //4.使用反射操作name属性
        Field name = stuClass.getDeclaredField("name");
        //因为name是私有属性,访问时要爆破,爆破后可以操作private属性
        name.setAccessible(true);
        //第一种写法
        //name.set(o,"中国");
        //第二种写法
        name.set(null,"世界");;//因为 name 是 static 属性,因此 o 也可以写出 null
        System.out.println(o);
        System.out.println(name.get(o));
        System.out.println(name.get(null));//写null,获取属性值时, 要求 name 是 static

    }
}
class Student {//类
    public int age;
    private static String name;

    public Student() {//构造器
    }

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

2.3 访问方法  727

1.根据方法名和参数列表获取Method方法对象: 

Method m = clazz.getDeclaredMethod(方法名,xx.class); //得到本类的所有方法

2.获取对象: Object o= clazz.newlnstance;

3.暴破: m.setAccessible(true);

4.访问: Object returnValue = m.invoke(o,实参列表);//o就是对象

5.注意:如果是静态方法,则invoke的参数o,可以写成null!

2.4 案例演示  727

代码在com.stulzl.reflection_access_method包中

ReflectionAccessMethod

package com.stulzl.reflection_access_method;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

//通过反射访问类中的成员  访问方法  727
public class ReflectionAccessMethod {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //得到Boss对应的Class对象
        Class bossClass = Class.forName("com.stulzl.reflection_access_method.Boss");
        //创建对象
        Object o = bossClass.newInstance();
        //得到public的hi()方法
        Method hi = bossClass.getMethod("hi",String.class);
        //还可以这样写
        //Method hi = bossClass.getDeclaredMethod("hi", String.class);
        //调用
        hi.invoke(o, "中国");

        //得到private的say()方法
        Method say = bossClass.getDeclaredMethod("say",int.class,String.class, char.class);
        say.setAccessible(true);//因为say()方法时私有的所以要爆破
        System.out.println(say.invoke(o,100,"张三",'男'));
        // 因为 say 方法是 static 的,还可以这样调用 ,可以传入 null
        System.out.println(say.invoke(null,200,"李四",'男'));

        //在反射中,如果方法有返回值,统一返回 Object 但是他运行类型和方法定义的返回类型一致
        Object reVal = say.invoke(null, 300,"王五", '男');
        System.out.println("运行类型="+reVal.getClass());//String
        System.out.println(reVal);

    }
}

class Boss {//类
    public int age;
    private static String name;

    public Boss() {//构造器
    }

    private static String say(int n, String s, char c) {//静态方法
        return n + " " + s + " " + c;
    }

    public void hi(String s) {//普通 public 方法
        System.out.println("hi " + s);
    }
}

3. 练习1  728

通过反射修改私有成员变量

1. 定义PrivateTest类, 有私有name属性,并且属性值为hellokitty

2.提供getName的公有方法

3. 创建PrivateTest的类, 利用Class类得到私有的name属性,修改私有的name属性值,

并调用getName()的方法打印name属性值

反射创建对象_java

代码在com.stulzl.exercise01包中

Exercise01

package com.stulzl.exercise01;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

//本站练习01  728
//通过反射修改私有成员变量
//1. 定义PrivateTest类, 有私有name属性,并且属性值为hellokitty
//2.提供getName的公有方法
//3. 创建PrivateTest的类, 利用Class类得到私有的name属性,修改私有的name属性值,
//并调用getName()的方法打印name属性值
public class Exercise01 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        //1. 得到PrivateTest类的Class对象
        Class privateTestClass = PrivateTest.class;
        //创建对象实例
        PrivateTest privateTestObj = privateTestClass.newInstance();
        //因为name是私有的所以用getDeclaredField,并且需要爆破才能修改值
        Field name = privateTestClass.getDeclaredField("name");
        //爆破
        name.setAccessible(true);
        name.set(privateTestObj,"天龙八部");

        //得到getName()方法对象
        Method getName = privateTestClass.getMethod("getName");
        Object invoke = getName.invoke(privateTestObj);//接收返回值
        System.out.println("name属性的值="+invoke);//输出//name属性的值=天龙八部

    }
}
class PrivateTest {
    private String name = "hellokitty";

    public String getName() {
        return name;
    }
}

4. 练习2  728

利用反射和File完成以下功能Homework02.java

1.利用Class类的forName方法得到File类的class对象

2.在控制台打印File类的所有构造器

3.通过newInstance的方法创建File对象, 并创建E:\mynew.txt文件

提示:创建文件的正常写法如下:

File file = new File(" d:\\aa.txt")://内存

file.createNewFile();//方法,才能真正的创建文件

代码在com.stulzl.exercise02包中

Exercise02

package com.stulzl.exercise02;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

//本章练习02  728
//利用反射和File完成以下功能Homework02.java
//1.利用Class类的forName方法得到File类的class对象
//2.在控制台打印File类的所有构造器
//3.通过newInstance的方法创建File对象, 并创建E:\mynew.txt文件
//提示:创建文件的正常写法如下:
//File file = new File(" d:\\aa.txt")://内存
//file.createNewFile();//方法,才能真正的创建文件
public class Exercise02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //利用Class类的forName方法得到File类的class对象
        Class fileClass = Class.forName("java.io.File");
        //得到所有构造器
        Constructor[] declaredConstructors = fileClass.getDeclaredConstructors();
        //遍历输出
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println("File构造器="+declaredConstructor);
        }
        //指定得到  这个File构造器=public java.io.File(java.lang.String)
        Constructor declaredConstructor = fileClass.getDeclaredConstructor(String.class);
        String fileAllPath = "e:\\mynew.txt";
        Object file = declaredConstructor.newInstance(fileAllPath);//创建file对象
        //提示:创建文件的正常写法如下:
        //File file = new File(" d:\\aa.txt")://内存
        //file.createNewFile();//方法,才能真正的创建文件
        //得到createNewFile()方法对象
        Method createNewFile = fileClass.getMethod("createNewFile");
        createNewFile.invoke(file);//真正的创建文件了
        //file的运行类型就是File
        System.out.println(file.getClass());
        System.out.println("创建文件成功"+fileAllPath);
        
    }
}

举报

相关推荐

0 条评论