Java反射机制大吐血(超详细)

1、反射的定义及作用

1.1、通过Java语言中的反射机制可以操作字节码文件。(可以读和修改字节码文件)
         通过反射机制可以操作代码片段。

1.2、反射机制的作用:使程序更加的灵活。

1.3、反射机制的相关类在哪个包下?
         java.lang.reflect.*;

1.4、反射机制相关的重要的类有哪些?
        java.lang.Class;                         代表:整个字节码文件,代表一个类型,代表整个类。
        java.lang.reflect.Method;           代表:字节码中的方法字节码,代表类中的方法。
        java.lang.reflect.Constructor;     代表:字节码中的构造方法字节码,代表类中的构造方法。
        java.lang.reflect.Field;                代表:字节码中的属性字节码,代表类中的成员变量(静态变量和实例变量)

2、获取Class的三种方式

第一种方式:
Class c = Class.forName(“完整类名带包名”);
1、静态方法
2、方法的参数是一个字符串
3、字符串需要是一个完整的类名
4、完整类名前必须带有包名

第二种方式:Class c = 对象.getClass();

第三种方式:Class c = 任何类型.class;(java语言中任何一种类型,包括基本数据类型,它都有.class属性)

3、通过构造方法实例化对象

  1. 通过newInstance调用无参数构造方法实例化对象 。
    3.1.1、语法格式:
        // c代表的是日期对象
	    Class c = Class.forName("java.util.Date");

	    // 实例化一个日期类型的对象
	    Object obj = c.newInstance();

        3.1.2、注意事项:newInstance()底层调用的是无参数构造方法。如果没有无参数构造方法会出现实例化异常。

        3.1.3、如果你只想让一个类的“静态代码块”执行的话,你可以怎么做?
                Class.forName(“该类的类名”);
                原因:这样类就加载,类加载的时候,静态代码块执行。在这里对该方法的返回值不感兴趣,主要是为了使用“类加载”这个动作。

  1. 通过反射机制反编译Field;
    public static void main(String[] args) {
        // 创建字符串,用于追加字符串
        StringBuilder stringBuilder = new StringBuilder();
        // 获取class
        Class studentClass = null;
        try {
            studentClass = Class.forName("java.lang.Thread");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        // 获取类名
        String className = Modifier.toString(studentClass.getModifiers()) +" class "+studentClass.getSimpleName();
        stringBuilder.append(className+"{\n");

        // 获取属性
        Field[] fields = studentClass.getDeclaredFields();
        for (Field field : fields){
            // 制表符
            stringBuilder.append("\t");

            // 获取访问控制权限列表
            int modifiesInt = field.getModifiers();
            String modifiesString = Modifier.toString(modifiesInt);
            stringBuilder.append(modifiesString);

            // 空格
            stringBuilder.append(" ");

            // 获取属性类型
            Class fieldClass = field.getType();
            String fieldType = fieldClass.getSimpleName();
            stringBuilder.append(fieldType);

            // 空格
            stringBuilder.append(" ");

            // 获取属性名字
            String fieldName = field.getName();
            stringBuilder.append(fieldName+";");

            // 换行
            stringBuilder.append("\n");
        }
        stringBuilder.append("}");
        System.out.println(stringBuilder);
    }

运行结果:

public class Thread{
private volatile String name;
private int priority;
private Thread threadQ;
private long eetop;
private boolean single_step;
private boolean daemon;
private boolean stillborn;
private Runnable target;
private ThreadGroup group;
private ClassLoader contextClassLoader;
private AccessControlContext inheritedAccessControlContext;
private static int threadInitNumber;
ThreadLocalMap threadLocals;
ThreadLocalMap inheritableThreadLocals;
private long stackSize;
private long nativeParkEventPointer;
private long tid;
private static long threadSeqNumber;
private volatile int threadStatus;
volatile Object parkBlocker;
private volatile Interruptible blocker;
private final Object blockerLock;
public static final int MIN_PRIORITY;
public static final int NORM_PRIORITY;
public static final int MAX_PRIORITY;
private static final StackTraceElement[] EMPTY_STACK_TRACE;
private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION;
private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
long threadLocalRandomSeed;
int threadLocalRandomProbe;
int threadLocalRandomSecondarySeed;
}

  1. 通过反射机制调用Field;
       // 首先第一步:获取class,实例化对象
       Class studentClass = Class.forName("com.java.bean.Student");;

       Object obj = studentClass.newInstance();

       // 获取no属性(通过属性的名称来获取field)
       Field noField = studentClass.getDeclaredField("no");

       // 给obj对象(Student对象)的no属性赋值
       /*
       虽然使用了反射机制,但是三要素缺一不可
       三要素:
          要素1:obj对象
          要素2:no属性
          要素3:赋值

        注意:反射机制让代码复杂了,但是,使程序更加灵活了。
        */
       noField.set(obj,200);

       // 读属性值
       /*
       2要素:
         obj对象、no属性
        */
       System.out.println(noField.get(obj)); // 200

       // 尝试访问私有的属性name
       Field fieldName = studentClass.getDeclaredField("name");

       // 打破封装(反射机制的缺点,打破封装,不安全)
       fieldName.setAccessible(true);

       // 给name属性赋值
       fieldName.set(obj,"jack");

       // 获取name属性的值
       System.out.println(fieldName.get(obj)); // jack

4、通过反射机制反编译Method

// 获取类
        Class studentClass = Class.forName("java.lang.String");

        StringBuilder s = new StringBuilder();

        // 获取类名
        s.append(Modifier.toString(studentClass.getModifiers())+" class "+studentClass.getSimpleName());
        s.append("{\n");

        // 获取Method
        Method[] methods = studentClass.getDeclaredMethods();
        for (Method method : methods){

            s.append(" \t");

            // 获取方法的修饰符列表
            s.append(Modifier.toString(method.getModifiers()));
            s.append(" ");

            // 获取返回值类型
            Class classType = method.getReturnType();
            String stringType = classType.getSimpleName();
            s.append(stringType);
            s.append(" ");

            // 获取方法名
            s.append(method.getName());

            s.append("(");

            // 获取形参
            Class[] parameterTypes = method.getParameterTypes();
            // 如果Class[]的长度为0,则说明没有形参
            if (0 != parameterTypes.length){
                for (Class parameterType : parameterTypes){
                    String parameterTypeString = parameterType.getSimpleName();
                    s.append(parameterTypeString);
                    s.append(",");
                }
                s.deleteCharAt(s.length()-1);
            }

            s.append("){}\n");

        }

        s.append("}");
        System.out.println(s);
    }

运行结果:

public final class String{
public boolean equals(Object){}
public String toString(){}
public int hashCode(){}
public int compareTo(String){}
public volatile int compareTo(Object){}
public int indexOf(String,int){}
public int indexOf(String){}
public int indexOf(int,int){}
public int indexOf(int){}
static int indexOf(char[],int,int,char[],int,int,int){}
static int indexOf(char[],int,int,String,int){}
public static String valueOf(int){}
public static String valueOf(long){}
public static String valueOf(float){}
public static String valueOf(boolean){}
public static String valueOf(char[]){}
public static String valueOf(char[],int,int){}
public static String valueOf(Object){}
public static String valueOf(char){}
public static String valueOf(double){}
public char charAt(int){}
private static void checkBounds(byte[],int,int){}
public int codePointAt(int){}
public int codePointBefore(int){}
public int codePointCount(int,int){}
public int compareToIgnoreCase(String){}
public String concat(String){}
public boolean contains(CharSequence){}
public boolean contentEquals(CharSequence){}
public boolean contentEquals(StringBuffer){}
public static String copyValueOf(char[]){}
public static String copyValueOf(char[],int,int){}
public boolean endsWith(String){}
public boolean equalsIgnoreCase(String){}
public static transient String format(Locale,String,Object[]){}
public static transient String format(String,Object[]){}
public void getBytes(int,int,byte[],int){}
public byte[] getBytes(Charset){}
public byte[] getBytes(String){}
public byte[] getBytes(){}
public void getChars(int,int,char[],int){}
void getChars(char[],int){}
private int indexOfSupplementary(int,int){}
public native String intern(){}
public boolean isEmpty(){}
public static transient String join(CharSequence,CharSequence[]){}
public static String join(CharSequence,Iterable){}
public int lastIndexOf(int){}
public int lastIndexOf(String){}
static int lastIndexOf(char[],int,int,String,int){}
public int lastIndexOf(String,int){}
public int lastIndexOf(int,int){}
static int lastIndexOf(char[],int,int,char[],int,int,int){}
private int lastIndexOfSupplementary(int,int){}
public int length(){}
public boolean matches(String){}
private boolean nonSyncContentEquals(AbstractStringBuilder){}
public int offsetByCodePoints(int,int){}
public boolean regionMatches(int,String,int,int){}
public boolean regionMatches(boolean,int,String,int,int){}
public String replace(char,char){}
public String replace(CharSequence,CharSequence){}
public String replaceAll(String,String){}
public String replaceFirst(String,String){}
public String[] split(String){}
public String[] split(String,int){}
public boolean startsWith(String,int){}
public boolean startsWith(String){}
public CharSequence subSequence(int,int){}
public String substring(int){}
public String substring(int,int){}
public char[] toCharArray(){}
public String toLowerCase(Locale){}
public String toLowerCase(){}
public String toUpperCase(){}
public String toUpperCase(Locale){}
public String trim(){}
}

5、通过反射机制调用Method;

public static void main(String[] args) throws Exception{
        // 不使用反射机制调方法
        // 创建对象
        Student student = new Student();
        // 调方法
        /*
        要素分析:
           要素1:对象
           要素2:方法名
           要素3:实参列表
           要素4:返回值类型
         */
        boolean isStudent = student.isStudentName("aaa",100);
        System.out.println(isStudent ? "重复":"不重复");

        // 通过反射机制调方法
        // 获取类
        Class studentClass = Class.forName("com.java.bean.Student");
        // 创建对象
        Object obj = studentClass.newInstance();

        // 获取isStudentName方法
        Method studentMethod = studentClass.getDeclaredMethod("isStudentName",String.class,int.class);

        // 调用方法
        /*
        要素分析:
           要素1:对象       obj
           要素2:方法名     isStudentName
           要素3:实参列表    "aaa",100
           要素4:返回值类型  retValue
         */
        // 反射机制中最最最重要的方法之一
        Object retValue = studentMethod.invoke(obj,"aaa",100);
        System.out.println(retValue);
    }

6、通过反射机制反编译构造方法/Constructor

public static void main(String[] args) throws Exception{
        // 获取类
        Class studentClass = Class.forName("java.lang.String");

        StringBuilder s = new StringBuilder();

        s.append(Modifier.toString(studentClass.getModifiers())+" class ");
        s.append(studentClass.getSimpleName()+" {\n");

        // 拼接构造方法
        Constructor[] constructors = studentClass.getDeclaredConstructors();

        for (Constructor constructor : constructors){

            s.append(" "+Modifier.toString(constructor.getModifiers())+"\t");
            s.append(studentClass.getSimpleName()+" (");

            // 获取实参
            Class[] parameterTypes = constructor.getParameterTypes();
            if (parameterTypes.length != 0){
                for (Class parameterType : parameterTypes){
                    String parameter = parameterType.getSimpleName();
                    s.append(parameter);
                    s.append(",");
                }
                // 删除最后下标的字符
                s.deleteCharAt(s.length()-1);
            }
            s.append("){}\n");
        }

        s.append("}");
        System.out.println(s);
    }

运行结果:

public final class String {
public String (byte[],int,int){}
public String (byte[],Charset){}
public String (byte[],String){}
public String (byte[],int,int,Charset){}
public String (byte[],int,int,String){}
String (char[],boolean){}
public String (StringBuilder){}
public String (StringBuffer){}
public String (byte[]){}
public String (int[],int,int){}
public String (){}
public String (char[]){}
public String (String){}
public String (char[],int,int){}
public String (byte[],int){}
public String (byte[],int,int,int){}
}

7、通过反射机制调用构造方法

public static void main(String[] args) throws Exception{
        // 不使用反射机制调用方法
        // public Student(int no, String name, boolean sex, int age) {
        Student student1 = new Student();
        Student student2 = new Student(1,"a",true,20);
        System.out.println(student1);
        System.out.println(student2);

        System.out.println("============================");

        // 使用反射机制调用构造方法
        // 调用无参数构造方法
        Class studentClass = Class.forName("com.java.bean.Student");
        Object obj = studentClass.newInstance();
        System.out.println(obj);

        // 调用无参数构造方法
        Constructor con2 = studentClass.getDeclaredConstructor();
        Object o2 = con2.newInstance();
        System.out.println(o2);

        // 调用有参数构造方法
        // 第一步:先获取有参数构造方法
        Constructor con = studentClass.getDeclaredConstructor(int.class,String.class,boolean.class,int.class);
        // 第二步:调用构造方法new对象
        Object o = con.newInstance(123,"abc",false,21);
        System.out.println(o);
    }

8、通过反射机制获取该类的父类跟实现了哪些接口

public static void main(String[] args) throws Exception{
        // 拿String举例
        Class stringClass = Class.forName("java.lang.String");

        // 获取String的父类
        Class superClass = stringClass.getSuperclass();
        System.out.println(superClass.getName());

        // 获取String类实现的所有接口
        Class[] interfaces = stringClass.getInterfaces();
        for (Class in : interfaces){
            System.out.println(in.getName());
        }
    }

运行结果:

java.lang.Object
java.io.Serializable
java.lang.Comparable
java.lang.CharSequence

4、关于路径的问题

1、用以下的方法首先必须保证该文件在类的根路径下
2、获取路径的两种方式:

  1. 第一种方式:
/*
        解释:
            Thread.currentThread() 当前线程对象
            getContextClassLoader() 是线程对象的方法,可以获取当前线程的类加载器对象
            getResource("") 【获取资源】这是类加载器对象的方法,当前线程的类加载器默认从类的根路径下加载资源。
         */
String path = Thread.currentThread().getContextClassLoader().getResource("在src的根路径下的路径").getPath();       
  1. 第二种方式:直接以流的方式返回
// 直接以流的形式返回。
        InputStream reader = Thread.currentThread().getContextClassLoader().getResourceAsStream("在src的根路径下的路径");

3、IO + Properties ,怎么快速绑定属性配置文件?

         // 要求:第一这个文件必须在类路径下
	    // 第二:这个文件必须是.properties结尾。
	    // 第三:文件的扩展名不用写
	    ResourceBundle bundle = ResourceBundle.getBundle("在src的根路径下的路径");
	    String value = bundle.getString(key);

5、结语

您好!正在努力中的人陌生人,加油!!!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值