Java反射机制

Java的反射,很多框架中使用的都有,比如mybatis、spring、springMVC等等都有使用,我们再看源码的时候很多有涉及到了反射,所以说要想看得懂源码,那反射必要掌握!

实现反射的几种方式

  1. Class.forName();这种方式使用的最多,最经典的就是jdbc的连接的地方通过反射来创建驱动
Class.forName("com.mysql.jdbc.Driver");
  1. .class;这种方式 需要导入类的包,依赖性太强。User是实体类后面会提供给大家
import edu.jokwe.User;

public class TestDotReflect {

    public static void main(String[] args) {
        Class cls = User.class;
        //获取全部名称
        System.out.println(cls.getName());
        //获取类名称
        System.out.println(cls.getSimpleName());
        //获取父类
        System.out.println(cls.getSuperclass());
        //获取包名
        System.out.println(cls.getPackage());
    }
}
/*
输出为:

D:\JDK1.8\bin\java.exe -javaagent:E:\Software\ideal\lib\idea_rt.jar=51319:E:\Software\ideal\bin -Dfile.encoding=UTF-8 -classpath "D:\JDK1.8\jre\lib\charsets.jar;D:\JDK1.8\jre\lib\deploy.jar;D:\JDK1.8\jre\lib\ext\access-bridge-64.jar;D:\JDK1.8\jre\lib\ext\cldrdata.jar;D:\JDK1.8\jre\lib\ext\dnsns.jar;D:\JDK1.8\jre\lib\ext\jaccess.jar;D:\JDK1.8\jre\lib\ext\jfxrt.jar;D:\JDK1.8\jre\lib\ext\localedata.jar;D:\JDK1.8\jre\lib\ext\nashorn.jar;D:\JDK1.8\jre\lib\ext\sunec.jar;D:\JDK1.8\jre\lib\ext\sunjce_provider.jar;D:\JDK1.8\jre\lib\ext\sunmscapi.jar;D:\JDK1.8\jre\lib\ext\sunpkcs11.jar;D:\JDK1.8\jre\lib\ext\zipfs.jar;D:\JDK1.8\jre\lib\javaws.jar;D:\JDK1.8\jre\lib\jce.jar;D:\JDK1.8\jre\lib\jfr.jar;D:\JDK1.8\jre\lib\jfxswt.jar;D:\JDK1.8\jre\lib\jsse.jar;D:\JDK1.8\jre\lib\management-agent.jar;D:\JDK1.8\jre\lib\plugin.jar;D:\JDK1.8\jre\lib\resources.jar;D:\JDK1.8\jre\lib\rt.jar;F:\ideal workstation\library-ten\java-reflect1\out\production\java-reflect1;D:\respository.respo\junit\junit\4.12\junit-4.12.jar;D:\respository.respo\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar" edu.jokwe.TestDotReflect
edu.jokwe.User
User
class java.lang.Object
package edu.jokwe

Process finished with exit code 0
*/

3.对象 .getClass()这种方式已经创建了对象,那么这个时候就不需要去进行反射了,显得就有点没有必要了。User是实体类后面会提供给大家

import edu.jokwe.User;

public class TestGetClass {
    public static void main(String[] args) {
        User user = new User();
        Class cls = user.getClass();
        //获取全部名称
        System.out.println(cls.getName());
        //获取类名称
        System.out.println(cls.getSimpleName());
        //获取父类
        System.out.println(cls.getSuperclass());
        //获取包名
        System.out.println(cls.getPackage());
    }

}
/*
输出为:

D:\JDK1.8\bin\java.exe -javaagent:E:\Software\ideal\lib\idea_rt.jar=51388:E:\Software\ideal\bin -Dfile.encoding=UTF-8 -classpath "D:\JDK1.8\jre\lib\charsets.jar;D:\JDK1.8\jre\lib\deploy.jar;D:\JDK1.8\jre\lib\ext\access-bridge-64.jar;D:\JDK1.8\jre\lib\ext\cldrdata.jar;D:\JDK1.8\jre\lib\ext\dnsns.jar;D:\JDK1.8\jre\lib\ext\jaccess.jar;D:\JDK1.8\jre\lib\ext\jfxrt.jar;D:\JDK1.8\jre\lib\ext\localedata.jar;D:\JDK1.8\jre\lib\ext\nashorn.jar;D:\JDK1.8\jre\lib\ext\sunec.jar;D:\JDK1.8\jre\lib\ext\sunjce_provider.jar;D:\JDK1.8\jre\lib\ext\sunmscapi.jar;D:\JDK1.8\jre\lib\ext\sunpkcs11.jar;D:\JDK1.8\jre\lib\ext\zipfs.jar;D:\JDK1.8\jre\lib\javaws.jar;D:\JDK1.8\jre\lib\jce.jar;D:\JDK1.8\jre\lib\jfr.jar;D:\JDK1.8\jre\lib\jfxswt.jar;D:\JDK1.8\jre\lib\jsse.jar;D:\JDK1.8\jre\lib\management-agent.jar;D:\JDK1.8\jre\lib\plugin.jar;D:\JDK1.8\jre\lib\resources.jar;D:\JDK1.8\jre\lib\rt.jar;F:\ideal workstation\library-ten\java-reflect1\out\production\java-reflect1;D:\respository.respo\junit\junit\4.12\junit-4.12.jar;D:\respository.respo\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar" edu.jokwe.TestGetClass
edu.jokwe.User
User
class java.lang.Object
package edu.jokwe

Process finished with exit code 0
*/

4.context.getClassLoader().loadClass(String ClassName);这种方式不建议使用!

反射的作用

某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。也就是有些类的属性或者是方法是private修饰的或者final修饰的不可更改的常量,或者只对系统应用开放,向这些就可以使用反射来获取所需要的内容。

获取类的构造方法

话不多说,上代码!

import java.lang.reflect.Constructor;

public class TestGetConstructor {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        Class cls = Class.forName("edu.jokwe.User");
        System.out.println("获取所有public的构造方法");
        //cls.getConstructors()返回的是一个Constructor数组
        Constructor[] constructors = cls.getConstructors();
        for (Constructor c : constructors) {
            System.out.println(c);
        }
        System.out.println("获取所有含有修饰符的构造方法");
        //cls.getDeclaredConstructors()返回的也是一个Constructor数组
        Constructor[] declaredConstructors = cls.getDeclaredConstructors();
        for (Constructor c : declaredConstructors) {
            System.out.println(c);
        }
        System.out.println("获取指定参数类型和数量的构造方法");
        Constructor constructor1 = cls.getConstructor(Integer.class);
        System.out.println(constructor1);
        Constructor constructor2 = cls.getDeclaredConstructor(String.class);
        System.out.println(constructor2);
    }
}
/*
	想要获取无参数的构造方法就传入一个null
	cls.getDeclaredConstructor(null);
	cls.getConstructors(null);
	
程序输出为:
D:\JDK1.8\bin\java.exe -javaagent:E:\Software\ideal\lib\idea_rt.jar=51447:E:\Software\ideal\bin -Dfile.encoding=UTF-8 -classpath "D:\JDK1.8\jre\lib\charsets.jar;D:\JDK1.8\jre\lib\deploy.jar;D:\JDK1.8\jre\lib\ext\access-bridge-64.jar;D:\JDK1.8\jre\lib\ext\cldrdata.jar;D:\JDK1.8\jre\lib\ext\dnsns.jar;D:\JDK1.8\jre\lib\ext\jaccess.jar;D:\JDK1.8\jre\lib\ext\jfxrt.jar;D:\JDK1.8\jre\lib\ext\localedata.jar;D:\JDK1.8\jre\lib\ext\nashorn.jar;D:\JDK1.8\jre\lib\ext\sunec.jar;D:\JDK1.8\jre\lib\ext\sunjce_provider.jar;D:\JDK1.8\jre\lib\ext\sunmscapi.jar;D:\JDK1.8\jre\lib\ext\sunpkcs11.jar;D:\JDK1.8\jre\lib\ext\zipfs.jar;D:\JDK1.8\jre\lib\javaws.jar;D:\JDK1.8\jre\lib\jce.jar;D:\JDK1.8\jre\lib\jfr.jar;D:\JDK1.8\jre\lib\jfxswt.jar;D:\JDK1.8\jre\lib\jsse.jar;D:\JDK1.8\jre\lib\management-agent.jar;D:\JDK1.8\jre\lib\plugin.jar;D:\JDK1.8\jre\lib\resources.jar;D:\JDK1.8\jre\lib\rt.jar;F:\ideal workstation\library-ten\java-reflect1\out\production\java-reflect1;D:\respository.respo\junit\junit\4.12\junit-4.12.jar;D:\respository.respo\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar" edu.jokwe.TestGetConstructor
获取所有public的构造方法
public edu.jokwe.User(java.lang.Integer)
public edu.jokwe.User(java.lang.String,int,java.lang.String)
public edu.jokwe.User()
获取所有含有修饰符的构造方法
public edu.jokwe.User(java.lang.Integer)
private edu.jokwe.User(java.lang.String)
public edu.jokwe.User(java.lang.String,int,java.lang.String)
private edu.jokwe.User(java.lang.String,int)
public edu.jokwe.User()
获取指定参数类型和数量的构造方法
public edu.jokwe.User(java.lang.Integer)
private edu.jokwe.User(java.lang.String)

Process finished with exit code 0
*/

获取类的属性以及赋值取值

话不多说,上代码!

import java.lang.reflect.Field;

public class TestField {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
        Class cls = Class.forName("edu.jokwe.User");

        System.out.println("获取所有public的字段");

        Field[] fields = cls.getFields();

        for (Field field : fields) {
            System.out.println(field);
        }

        System.out.println("获取所有含有修饰符的字段");

        Field[] declaredFields = cls.getDeclaredFields();

        for (Field field : declaredFields) {
            System.out.println(field);
        }
        System.out.println("给字段赋值(不能给私有字段赋值)");

        User user = (User) cls.newInstance();

        Field userNameField = cls.getField("username");

        userNameField.set(user, "张三");
        System.out.println(user.getUsername());
        System.out.println("给私有字段赋值");
        user = (User) cls.newInstance();
        Field iphoneField = cls.getDeclaredField("iphone");
        //暴力反射
        iphoneField.setAccessible(true);
        iphoneField.set(user, "132132132");
        System.out.println(user.getIphonePublic());
    }
}

/*
	 //需要进行暴力破解才能对数据进行赋值。
     iphoneField.setAccessible(true);

程序输出为:
D:\JDK1.8\bin\java.exe -javaagent:E:\Software\ideal\lib\idea_rt.jar=51899:E:\Software\ideal\bin -Dfile.encoding=UTF-8 -classpath "D:\JDK1.8\jre\lib\charsets.jar;D:\JDK1.8\jre\lib\deploy.jar;D:\JDK1.8\jre\lib\ext\access-bridge-64.jar;D:\JDK1.8\jre\lib\ext\cldrdata.jar;D:\JDK1.8\jre\lib\ext\dnsns.jar;D:\JDK1.8\jre\lib\ext\jaccess.jar;D:\JDK1.8\jre\lib\ext\jfxrt.jar;D:\JDK1.8\jre\lib\ext\localedata.jar;D:\JDK1.8\jre\lib\ext\nashorn.jar;D:\JDK1.8\jre\lib\ext\sunec.jar;D:\JDK1.8\jre\lib\ext\sunjce_provider.jar;D:\JDK1.8\jre\lib\ext\sunmscapi.jar;D:\JDK1.8\jre\lib\ext\sunpkcs11.jar;D:\JDK1.8\jre\lib\ext\zipfs.jar;D:\JDK1.8\jre\lib\javaws.jar;D:\JDK1.8\jre\lib\jce.jar;D:\JDK1.8\jre\lib\jfr.jar;D:\JDK1.8\jre\lib\jfxswt.jar;D:\JDK1.8\jre\lib\jsse.jar;D:\JDK1.8\jre\lib\management-agent.jar;D:\JDK1.8\jre\lib\plugin.jar;D:\JDK1.8\jre\lib\resources.jar;D:\JDK1.8\jre\lib\rt.jar;F:\ideal workstation\library-ten\java-reflect1\out\production\java-reflect1;D:\respository.respo\junit\junit\4.12\junit-4.12.jar;D:\respository.respo\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar" edu.jokwe.TestField
获取所有public的字段
public java.lang.String edu.jokwe.User.username
获取所有含有修饰符的字段
public java.lang.String edu.jokwe.User.username
protected java.lang.Integer edu.jokwe.User.age
private java.lang.String edu.jokwe.User.sex
private java.lang.String edu.jokwe.User.iphone
给字段赋值(不能给私有字段赋值)
张三
给私有字段赋值
132132132

Process finished with exit code 0
*/

通过反射修改常量值

话不多说,上代码


import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class TestFinal {
    private static final Integer EXT_NAME = 123;

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException, ClassNotFoundException {
        Class cls = Class.forName("edu.jokwe.TestFinal");
        Object obj = cls.newInstance();
        Field field = cls.getDeclaredField("EXT_NAME");
        //忽略final修饰符
        Field modifiers = Field.class.getDeclaredField("modifiers");
        System.out.println(modifiers);
        //暴力破解
        modifiers.setAccessible(true);
        modifiers.setInt(field,field.getModifiers() & ~Modifier.FINAL);
        field.set(null,345);
        System.out.println(EXT_NAME);
    }
}
/*
 	//因为是private修饰,还有final修饰,所以需要进行暴力破解
 	 modifiers.setAccessible(true);
 	 modifiers.setInt(field,field.getModifiers() & ~Modifier.FINAL);
 	 field.getModifiers() & ~Modifier.FINAL
 	 就是把final修饰符去掉的,后续会补充这个东西是如何成立的

程序输出为:
D:\JDK1.8\bin\java.exe -javaagent:E:\Software\ideal\lib\idea_rt.jar=52157:E:\Software\ideal\bin -Dfile.encoding=UTF-8 -classpath "D:\JDK1.8\jre\lib\charsets.jar;D:\JDK1.8\jre\lib\deploy.jar;D:\JDK1.8\jre\lib\ext\access-bridge-64.jar;D:\JDK1.8\jre\lib\ext\cldrdata.jar;D:\JDK1.8\jre\lib\ext\dnsns.jar;D:\JDK1.8\jre\lib\ext\jaccess.jar;D:\JDK1.8\jre\lib\ext\jfxrt.jar;D:\JDK1.8\jre\lib\ext\localedata.jar;D:\JDK1.8\jre\lib\ext\nashorn.jar;D:\JDK1.8\jre\lib\ext\sunec.jar;D:\JDK1.8\jre\lib\ext\sunjce_provider.jar;D:\JDK1.8\jre\lib\ext\sunmscapi.jar;D:\JDK1.8\jre\lib\ext\sunpkcs11.jar;D:\JDK1.8\jre\lib\ext\zipfs.jar;D:\JDK1.8\jre\lib\javaws.jar;D:\JDK1.8\jre\lib\jce.jar;D:\JDK1.8\jre\lib\jfr.jar;D:\JDK1.8\jre\lib\jfxswt.jar;D:\JDK1.8\jre\lib\jsse.jar;D:\JDK1.8\jre\lib\management-agent.jar;D:\JDK1.8\jre\lib\plugin.jar;D:\JDK1.8\jre\lib\resources.jar;D:\JDK1.8\jre\lib\rt.jar;F:\ideal workstation\library-ten\java-reflect1\out\production\java-reflect1;D:\respository.respo\junit\junit\4.12\junit-4.12.jar;D:\respository.respo\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar" edu.jokwe.TestFinal
private int java.lang.reflect.Field.modifiers
345

Process finished with exit code 0
*/

获取类中的方法并且执行方法

话不多说,上代码

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

public class TestGetMethod {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class cls =Class.forName("edu.jokwe.User");
        Constructor constructor = cls.getConstructor(null);
        Object obj = constructor.newInstance();
        System.out.println("连着这个父类的方法全部都获取到");
        Method[] methods = cls.getMethods();
        for (Method method:methods) {
            System.out.println(method);
        }
        System.out.println("获取所有的方法不包括父类,但包括私有的方法");
        Method[] declaredMethods = cls.getDeclaredMethods();
        for (Method method:declaredMethods) {
            System.out.println(method);
        }

        System.out.println("获取指定public 方法名和参数的方法");
        Method method2 = cls.getMethod("method2", String.class);
        System.out.println(method2);
        method2.invoke(obj,"zs");

        System.out.println("获取指定方法名和参数的方法");
        Method method3 = cls.getDeclaredMethod("method3", String.class,Integer.class);
        System.out.println(method3);
        method3.invoke(obj,"zs",123);
        Method method4 = cls.getDeclaredMethod("method4", String.class);

        System.out.println("调用默认修饰符的方法");
        System.out.println(method4);
        method4.invoke(obj,"zs");

        System.out.println("调用静态方法");
        Method method5 = cls.getDeclaredMethod("method5");
        System.out.println(method5);
        method5.invoke(null);

        System.out.println("调用private的方法");
        Method method6 = cls.getDeclaredMethod("method6");
        //暴力破解
        method6.setAccessible(true);
        System.out.println(method6);
        method6.invoke(obj);
    }
}

/*
	程序输出为:
	D:\JDK1.8\bin\java.exe -javaagent:E:\Software\ideal\lib\idea_rt.jar=52216:E:\Software\ideal\bin -Dfile.encoding=UTF-8 -classpath "D:\JDK1.8\jre\lib\charsets.jar;D:\JDK1.8\jre\lib\deploy.jar;D:\JDK1.8\jre\lib\ext\access-bridge-64.jar;D:\JDK1.8\jre\lib\ext\cldrdata.jar;D:\JDK1.8\jre\lib\ext\dnsns.jar;D:\JDK1.8\jre\lib\ext\jaccess.jar;D:\JDK1.8\jre\lib\ext\jfxrt.jar;D:\JDK1.8\jre\lib\ext\localedata.jar;D:\JDK1.8\jre\lib\ext\nashorn.jar;D:\JDK1.8\jre\lib\ext\sunec.jar;D:\JDK1.8\jre\lib\ext\sunjce_provider.jar;D:\JDK1.8\jre\lib\ext\sunmscapi.jar;D:\JDK1.8\jre\lib\ext\sunpkcs11.jar;D:\JDK1.8\jre\lib\ext\zipfs.jar;D:\JDK1.8\jre\lib\javaws.jar;D:\JDK1.8\jre\lib\jce.jar;D:\JDK1.8\jre\lib\jfr.jar;D:\JDK1.8\jre\lib\jfxswt.jar;D:\JDK1.8\jre\lib\jsse.jar;D:\JDK1.8\jre\lib\management-agent.jar;D:\JDK1.8\jre\lib\plugin.jar;D:\JDK1.8\jre\lib\resources.jar;D:\JDK1.8\jre\lib\rt.jar;F:\ideal workstation\library-ten\java-reflect1\out\production\java-reflect1;D:\respository.respo\junit\junit\4.12\junit-4.12.jar;D:\respository.respo\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar" edu.jokwe.TestGetMethod
连着这个父类的方法全部都获取到
public void edu.jokwe.User.setUsername(java.lang.String)
public void edu.jokwe.User.setAge(java.lang.Integer)
public static void edu.jokwe.User.method5()
public void edu.jokwe.User.method1()
public void edu.jokwe.User.method2(java.lang.String)
public java.lang.String edu.jokwe.User.getIphonePublic()
public java.lang.String edu.jokwe.User.getUsername()
public java.lang.String edu.jokwe.User.getSex()
public void edu.jokwe.User.setSex(java.lang.String)
public java.lang.Integer edu.jokwe.User.getAge()
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()
获取所有的方法不包括父类,但包括私有的方法
void edu.jokwe.User.method4(java.lang.String)
public void edu.jokwe.User.setUsername(java.lang.String)
public void edu.jokwe.User.setAge(java.lang.Integer)
public static void edu.jokwe.User.method5()
private void edu.jokwe.User.setIphone(java.lang.String)
private java.lang.String edu.jokwe.User.getIphone()
public void edu.jokwe.User.method1()
public void edu.jokwe.User.method2(java.lang.String)
private void edu.jokwe.User.method6()
public java.lang.String edu.jokwe.User.getIphonePublic()
public java.lang.String edu.jokwe.User.getUsername()
public java.lang.String edu.jokwe.User.getSex()
public void edu.jokwe.User.setSex(java.lang.String)
public java.lang.Integer edu.jokwe.User.getAge()
protected void edu.jokwe.User.method3(java.lang.String,java.lang.Integer)
获取指定public 方法名和参数的方法
public void edu.jokwe.User.method2(java.lang.String)
public 有参数 username method2
获取指定方法名和参数的方法
protected void edu.jokwe.User.method3(java.lang.String,java.lang.Integer)
protected 有参数 username age method3
调用默认修饰符的方法
void edu.jokwe.User.method4(java.lang.String)
默认修饰符 有参数 username method4
调用静态方法
public static void edu.jokwe.User.method5()
#21
调用private的方法
private void edu.jokwe.User.method6()
method6

Process finished with exit code 0
*/

答应给你们的User类

package edu.jokwe;


public class User {
    public String username;
    protected Integer age;
    private String sex;
    private String iphone;

    public User() {
    }

    private User(String username, int age) {
        this.username = username;
        this.age = age;
    }

    public User(String username, int age, String sex) {
        this.username = username;
        this.age = age;
        this.sex = sex;
    }

    private User(String username) {
        this.username = username;
    }

    public User(Integer age){
        this.age = age;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    private String getIphone() {
        return iphone;
    }
    public String getIphonePublic() {
        return iphone;
    }

    private void setIphone(String iphone) {
        this.iphone = iphone;
    }

    public void method1(){
        System.out.println("public 无参数 method1");
    }
    public void method2(String username){
        System.out.println("public 有参数 username method2");
    }
    protected void method3(String username,Integer age){
        System.out.println("protected 有参数 username age method3");
    }
    void method4(String username){
        System.out.println("默认修饰符 有参数 username method4");
    }

    public static void method5(){
        System.out.println("#21");
    }
    private void method6(){
        System.out.println("method6");
    }


}

有什么问题欢迎提出来!必定加以改正!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值