Java反射完全详解

三、反射的使用

3.1获取Class对象的三种方式。 
3.1测试类:

public class Example1 {
    public static void main(String[] args) {
        // 1.第一种方式获取Class对象
        // new产生一个对象,一个Class对象
        Example1 example1 = new Example1();
        // 获取Class对象
        Class class1 = example1.getClass();
        System.out.println(class1.getName());

        // 2.第二种方式获取Class对象
        Class class2 = Example1.class;
        // 判断是否为同一个class对象
        System.out.println(class1 == class2);

        try {
            // 3.第三种方式获取Class对象,参数为全限定名(最常用方法)
            Class class3 = Class.forName("top.itan.reflect.Example1");
            System.out.println(class2 == class3);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

//运行结果
top.itan.reflect.Example1
true
true

3.2通过反射获取构造方法并使用。 
3.2示例类:

public class Student {

    // 无参构造方法
    public Student() {
        System.out.println("调用了公有、无参构造方法");
    }

    // 有一个参数的构造方法
    public Student(String name) {
        System.out.println("调用了公有、一个参数的构造方法,姓名:" + name);
    }

    // 有多个参数的构造方法
    public Student(String name, int age) {
        System.out.println("调用了公有、两个参数的构造方法,姓名:" + name + ",年龄:" + age);
    }

    // 受保护的构造方法
    protected Student(boolean n) {
        System.out.println("调用了受保护的、一个参数的构造方法,n = " + n);
    }

    // 私有构造方法
    private Student(int age) {
        System.out.println("调用了私有的、一个参数构造方法,年龄:" + age);
    }
}

3.2测试类:

public class Contructors {
    public static void main(String[] args) throws Exception {
        // 加载Class对象
        Class clazz = Class.forName("top.itan.reflect.Student");

        // 1.获取所有公有构造方法
        System.out.println("=============================所有公有构造方法=============================");
        Constructor[] conArray = clazz.getConstructors();
        for (Constructor constructor : conArray) {
            System.out.println(constructor);
        }

        // 2.获取所有的构造方法(包括:私有、受保护、默认、公有)
        System.out.println("\n===================所有的构造方法(包括:私有、受保护、默认、公有)===================");
        conArray = clazz.getDeclaredConstructors();
        for (Constructor constructor : conArray) {
            System.out.println(constructor);
        }

        // 3.获取单个公有、无参的构造方法
        System.out.println("\n=========================获取单个公有、无参的构造方法=============================");
        // 1.无参的构造方法,所以类型是一个null,不写也可以,这里需要的是一个【参数的类型】
        // 2.返回的是描述这个无参构造函数的类对象。
        Constructor constructor = clazz.getConstructor(null);

        System.out.println("constructor --->>> " + constructor);
        // 调用构造方法
        Object object = constructor.newInstance();
        System.out.println("object --->>> " + object);
        Student student = (Student) object;
        System.out.println("student --->>> " + student);

        // 4.获取单个公有、有参构造方法,并调用
        System.out.println("\n=======================获取单个公有、有参构造方法,并调用==========================");
        // 这里需要的是一个【参数的类型】
        Constructor constructor2 = clazz.getDeclaredConstructor(String.class);
        System.out.println(constructor2);
        // 调用构造方法
        object = constructor2.newInstance("男");

        // 5.获取单个私有、有参构造方法,并调用
        System.out.println("\n=======================获取单个私有、有参构造方法,并调用==========================");
        // 这里需要的是一个【参数的类型】
        Constructor constructor3 = clazz.getDeclaredConstructor(int.class);
        System.out.println(constructor3);
        // 暴力访问(忽略掉访问修饰符)
        constructor3.setAccessible(true);
        // 调用构造方法
        object = constructor3.newInstance(18);
    }
}
// 运行结果
=============================所有公有构造方法=============================
public top.itan.reflect.Student(java.lang.String,int)
public top.itan.reflect.Student(java.lang.String)
public top.itan.reflect.Student()

=================所有的构造方法(包括:私有、受保护、默认、公有)=================
private top.itan.reflect.Student(int)
protected top.itan.reflect.Student(boolean)
public top.itan.reflect.Student(java.lang.String,int)
public top.itan.reflect.Student(java.lang.String)
public top.itan.reflect.Student()

=======================获取单个公有、无参的构造方法===========================
constructor --->>> public top.itan.reflect.Student()
调用了公有、无参构造方法
object --->>> top.itan.reflect.Student@7852e922
student --->>> top.itan.reflect.Student@7852e922

=====================获取单个公有、有参构造方法,并调用========================
public top.itan.reflect.Student(java.lang.String)
调用了公有、一个参数的构造方法,姓名:男

=====================获取单个私有、有参构造方法,并调用========================
private top.itan.reflect.Student(int)
调用了私有的、一个参数构造方法,年龄:18

3.3获取成员变量并调用 
3.3示例类:

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 + "]";
    }

}

3.3测试类:

public class Fields {

    public static void main(String[] args) throws Exception {
        // 1.获取Class对象
        Class clazz = Class.forName("top.itan.fields.Student");

        // 2.获取字段
        System.out.println("=============================获取所有公有的字段=============================");
        Field[] fieldArray = clazz.getFields();
        for (Field field : fieldArray) {
            System.out.println(field);
        }

        // 3.获取所有的字段(包括私有、受保护、默认的、公有的)
        System.out.println("\n==================获取所有的字段(包括私有、受保护、默认的、公有的)==================");
        fieldArray = clazz.getDeclaredFields();
        for (Field field : fieldArray) {
            System.out.println(field);
        }

        // 4.获取公有字段并调用
        System.out.println("\n==============================获取公有字段并调用==============================");
        Field field = clazz.getField("name");
        System.out.println(field);
        // 产生Student对象 --->>> Student student = new Student();无参构造方法
        Object obj = clazz.getConstructor().newInstance();
        // 为Student对象中的name属性赋值--->>> student.name = "刘德华"
        field.set(obj, "刘德华");
        // 验证
        Student student = (Student) obj;
        System.out.println("验证姓名:" + student.name);

        // 5.获取私有字段并调用
        System.out.println("\n==============================获取私有字段并调用=============================");
        Field field2 = clazz.getDeclaredField("phoneNum");
        System.out.println(field2);
        // 暴力反射,解除私有限定
        field2.setAccessible(true);
        field2.set(obj, "18888889999");
        System.out.println("验证电话:" + student);

    }

}
// 运行结果
=============================获取所有公有的字段=============================
public java.lang.String top.itan.fields.Student.name

=====================获取所有的字段(包括私有、受保护、默认的、公有的)==================
public java.lang.String top.itan.fields.Student.name
protected int top.itan.fields.Student.age
char top.itan.fields.Student.sex
private java.lang.String top.itan.fields.Student.phoneNum

==============================获取公有字段并调用==============================
public java.lang.String top.itan.fields.Student.name
验证姓名:刘德华

==============================获取私有字段并调用=============================
private java.lang.String top.itan.fields.Student.phoneNum
验证电话:Student [name=刘德华, age=0, sex= , phoneNum=18888889999]

3.4获取成员方法并调用 
3.4示例类:

public class Student {

    public void show1(String s) {
        System.out.println("调用了:公有的,String参数的show1(),参数值为:s --->>> " + s);
    }

    protected void show2() {
        System.out.println("调用了:受保护的,无参的show2()");
    }

    void show3() {
        System.out.println("调用了:默认的,无参的show3()");
    }

    private String show4(int age) {
        System.out.println("调用了:私有的,并且有返回值的,int参数的show4(),参数值为:age --->>> " + age);
        return String.valueOf(age);
    }

    public static void main(String[] args) {

    }
}

3.4测试类:

public class Methods {

    public static void main(String[] args) throws Exception {
        // 1.获取Class对象
        Class clazz = Class.forName("top.itan.methods.Student");

        // 2.获取所有公有方法
        System.out.println("=========================获取所有的公有方法=======================");
        clazz.getMethods();
        Method[] methodArray = clazz.getMethods();
        for (Method method : methodArray) {
            System.out.println(method);
        }

        System.out.println("\n==============获取所有的方法,包括公有的、默认的、受保护的、私有的================");
        Method[] methodArray1 = clazz.getDeclaredMethods();
        for (Method method : methodArray1) {
            System.out.println(method);
        }

        System.out.println("\n=====================获取公有的show1()方法=======================");
        // 传入方法名和参数类型
        Method method = clazz.getMethod("show1", String.class);
        System.out.println(method);
        // 实例化一个Student对象
        Object obj = clazz.getConstructor().newInstance();
        // 调用,需要两个参数,一个是要调用的对象(获取有反射),一个是实参
        method.invoke(obj, "刘德华");

        System.out.println("\n======================获取私有的show4()方法=======================");
        // 传入方法名和参数类型
        Method method2 = clazz.getDeclaredMethod("show4", int.class);
        System.out.println(method2);
        // 解除私有限定
        method2.setAccessible(true);
        // 实例化一个Student对象
        Object student = clazz.getConstructor().newInstance();
        // 调用,需要两个参数,一个是要调用的对象(获取有反射),一个是实参
        Object result = method2.invoke(student, 20);
        System.out.println("返回值:" + result);

    }
}
// 运行结果
=========================获取所有的公有方法=======================
public void top.itan.methods.Student.show1(java.lang.String)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
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 void top.itan.methods.Student.show1(java.lang.String)
private java.lang.String top.itan.methods.Student.show4(int)
protected void top.itan.methods.Student.show2()
void top.itan.methods.Student.show3()

=====================获取公有的show1()方法=======================
public void top.itan.methods.Student.show1(java.lang.String)
调用了:公有的,String参数的show1(),参数值为:s --->>> 刘德华

======================获取私有的show4()方法=======================
private java.lang.String top.itan.methods.Student.show4(int)
调用了:私有的,并且有返回值的,int参数的show4(),参数值为:age --->>> 20
返回值:20

3.5反射main方法 
3.5示例类:

public class Student {
    public static void main(String[] args) {
        System.out.println("main 方法执行了...");
        if (args != null) {
            for (String string : args) {
                System.out.println("值为: --->>> " + string);
            }
        }
}

3.5测试类:

public class ReflectMainMethod {

    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName("top.itan.main.Student");
            // 第一个参数:方法名称,第二个参数:方法形参的类型
            Method method = clazz.getMethod("main", String[].class);

            // 实例化Student对象
            Object object = clazz.newInstance();
            // 调用方法
            // 方式1,因为方法是static静态的,object也可以为null
            method.invoke(object, (Object) new String[] { "a", "b", "c" });

            // 方式2,因为方法是static静态的,object也可以为null
            method.invoke(object, new Object[] { new String[] { "d", "e", "f" } });
            // 这其实传了一个null值
            method.invoke(object, new String[1]);

            // 不转成Ojbect会报错
            method.invoke(object, new String[] { "a", "b", "c" });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
// 运行结果

main 方法执行了...
值为: --->>> a
值为: --->>> b
值为: --->>> c
main 方法执行了...
值为: --->>> d
值为: --->>> e
值为: --->>> f
main 方法执行了...
java.lang.IllegalArgumentException: wrong number of arguments
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at top.itan.main.ReflectMainMethod.main(ReflectMainMethod.java:22)

3.6反射之其他使用一:读取配置文件里的类名和方法再反射 
3.6示例类:

public class Student {

    public void read() {
        System.out.println("this is read() method");
    }

}

3.6文件file.properties内容

className = top.itan.readfile.Student
methodName = read

3.6测试类:

public class Read {

    /**
     * 我们利用反射和配置文件,可以:应用程序更新时,对源码无需进行任何修改,我们只需要将写新类,并修改配置文件即可
     */
    public static void main(String[] args) throws Exception {
        // 1.通过反射获取Class对象,top.itan.readfile.Student
        Class clazz = Class.forName(getValue("className"));
        // 2.获取read()方法
        Method method = clazz.getMethod(getValue("methodName"));
        // 3.实例化对象
        Object object = clazz.getConstructor().newInstance();
        // 4.调用read()方法
        method.invoke(object);
    }

    /**
     * 根据key读取配置文件中对应的value
     * 
     * @param key
     * @return
     * @throws IOException
     */
    public static String getValue(String key) throws IOException {
        // 获取配置文件的对象
        Properties properties = new Properties();
        // 获取输入流
        InputStream inputStream = new FileInputStream("D:/eclipseworkspacefor2017/reflect/src/main/resources/file.properties");
        // 将流加载到配置文件对象中
        properties.load(inputStream);
        inputStream.close();
        // 返回根据key获取的value值
        return properties.getProperty(key);
    }
}
// 运行结果
this is read() method

3.7反射之其他使用二:通过反射越过泛型检查 
3.7测试类:

public class SkipGenerics {

    /**
     * 通过反射越过泛型检查,例如:有一个String泛型的集合,怎样能向这个集合中添加一个int类型的值
     */
    public static void main(String[] args) throws Exception {
        ArrayList<String> strList = new ArrayList<String>();
        strList.add("aaa");
        strList.add("bbb");
        // 此处编译期就报错
        // strList.add(100);

        // 获取ArrayList的Class对象,反向的调用add()方法,添加数据
        Class clazz = strList.getClass();
        // 获取add()方法
        Method method = clazz.getMethod("add", Object.class);
        // 调用add()方法
        method.invoke(strList, 100);
        // 遍历集合
        for (Object obj : strList) {
            System.out.println(obj);
        }
    }
}
// 运行结果
aaa
bbb
100

3.8反射之其他使用三:通过反射修改String对象的值 
3.8测试类:

public class ChangeStringValue {
	public static void main(String[] args) {
		try {
			// 创建一个String类型的对象
			String str = "abcde";
			System.out.println("str --->>> " + str);

			// 1.获取String的Class对象
			Class<?> clazz = Class.forName("java.lang.String");
			// 2.获取String的value字段
			Field field = clazz.getDeclaredField("value");
			// 3.改变value属性的访问权限
			field.setAccessible(true);
			// 4.获取str对象上的value属性的值
			char[] chars = (char[]) field.get(str);
			System.out.println("chars --->>> " + String.valueOf(chars));
			// 5.改变value所引用的char数组中第一个字符串
			chars[0] = '_';
			System.out.println("str --->>> " + str);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

// 运行结果
str --->>> abcde
chars --->>> abcde
str --->>> _bcde

尊重原创,善于分享:https://blog.csdn.net/sinat_38259539/article/details/71799078,由于原创排版太差,本文对照原创整理修改完善而来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值