Java - 反射及其使用

Java - 反射及其使用

Java 开发人员必须要知道的一个知识,就是反射,在看很多底层源码的时候或多或少都会涉及一些,下面来介绍一下

前言

Java 一种经典的面向对象开发语言,对象先声明后使用,而一个变量又分为 编译型类型 与 运行时类型

  • 编译时类型 是由声明该变量时使用的类型决定
  • 运行时类型 由实际赋给该变量的对象决定

若编译时类型和运行时类型不一致,也就是我们所谓的 多态。因为子类其实是一种特殊的父类,因此java允许把一个子类对象直接赋值给一个父类引用变量,无须任何类型转换,或者被称为向上转型,由系统自动完成。引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法

前期准备

为方便下面的方法示例,这里做一些准备工作,新建几个类

1、新建一个类 StudyParamParentPre

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class StudyParamParentPre {

    String namePrePre;

    List<String> listPrePre;

    List<List<String>> dListPrePre;
    
    public void publicGetParentPre() {
    }

    protected void protectedGetParentPre() {
    }

    private void privateGetParentPre() {
    }
}

2、新建一个类 StudyParamParent,其是StudyParamParentPre 的子类

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class StudyParamParent extends StudyParamParentPre{


    String namePre;

    List<String> listPre;

    List<List<String>> dListPre;
    
    
    
    public void publicGetParent() {
    }

    protected void protectedGetParent() {
    }

    private void privateGetParent() {
    }
}

3、新建一个接口 StudyInfer

public interface StudyInfer {
   
   public void publicGetInfer();

}

4、新建一个类 StudyParam,其是 StudyParamParent 的子类,实现了 StudyInfer

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class StudyParam extends StudyParamParent implements StudyInfer {

    String name;


    List<String> list;

    String[] strings;

    List<List<String>> dList;

    public StudyParam(String namePre, List<String> listPre, List<List<String>> dListPre, String name) {
        super(namePre, listPre, dListPre);
        this.name = name;
    }

    private StudyParam(String namePre, List<String> listPre, List<List<String>> dListPre, String name, List<String> list) {
        super(namePre, listPre, dListPre);
        this.name = name;
        this.list = list;
    }

    public void publicGet() {
    }

    protected void protectedGet() {
    }

    private void privateGet() {
    }

    @Override
    public void publicGetInfer() {

    }

    public void getPublicHa() {
    }

    public void getPublicHa(String name) {
    }

    private void getPrivateHa() {
    }

    private void getPrivateHa(String name) {
    }
}

反射

什么是反射?

反射 就是在运行状态中,能够知道任意类所有属性和方法,可调用其任意一个方法和属性,即动态获取信息及动态调用对象方法的功能叫 Java 反射

反射可以做什么?

在运行状态中,反射可以做以下事情:

  • 判断任意一个对象所属的类,实例化该对象
  • 获得任意一个对象的属性,可修改该属性的值
  • 获得任意一个对象的方法,可反射执行该方法

反射如何使用?

因为Java是面向对象编程,最基础的就是类,即 Class

Class

面向对象编程,故基础为类,属性与方法都基于类,该类中有的方法常用的如下:

方法名称 用途 返回值
toString
toGenericString
对象转换为String String
isInstance
isAssignableFrom
isInterface
isArray
isPrimitive
isAnnotation
isSynthetic
isAnnotationPresent
isAnonymousClass
isLocalClass
isMemberClass
isEnum
是否是某实例
是否从xx 继承/实现来的
是否是接口
是否是数组
是否是原始类型
是否是注解
是否是Synthetic
是否是注解
是否是匿名类
是否是局部变量
是否是Member
是否是枚举
boolean
newInstance 实例化对象 T
getName
getSimpleName
getTypeName
getCanonicalName
获取类的全类名 String
getSuperclass
getGenericSuperclass
获取父类 Class
Type
getPackage 获取类所在的包 Package
getComponentType 返回表示数组组件类型的 Class Class
getClassLoader 获取类加载器 ClassLoader

说明:

  • toString 与 toGenericString 的返回值去吧在于一个是全类名的名称字符串,一个是包含了访问符、类类型的字符串
  • getName 与 getSimpleName,getName包含包名和类名、getSimpleName为类名

方法使用举例:

package com.study;

import com.study.pojo.StudyInfer;
import com.study.pojo.StudyParam;
import com.study.pojo.StudyParamParent;

import java.lang.reflect.Constructor;
import java.lang.reflect.Type;

public class Study {


    public static void main(String[] args) throws IllegalAccessException, InstantiationException {

        Class<StudyParam> studyParamClass = StudyParam.class;
        Class<StudyParamParent> studyParamParent = StudyParamParent.class;

        System.out.println("-------- class  toString  -------- ");
        System.out.println(studyParamClass.toString());
        //class com.study.pojo.StudyParam

        System.out.println("-------- class  toGenericString -------- ");
        System.out.println(studyParamClass.toGenericString());
        //public class com.study.pojo.StudyParam


        System.out.println("-------- class  isInstance -------- ");
        System.out.println(studyParamClass.isInstance(new StudyParam()));
        System.out.println(studyParamClass.isInstance(new StudyParamParent()));
        //true
        //false

        System.out.println("-------- class  isAssignableFrom -------- ");
        System.out.println(studyParamClass.isAssignableFrom(StudyParamParent.class));
        System.out.println(studyParamClass.isAssignableFrom(StudyInfer.class));
        System.out.println(studyParamParent.isAssignableFrom(StudyParam.class));
        //false
        //false
        //true

        System.out.println("-------- class  isInterface -------- ");
        System.out.println(studyParamClass.isInterface());
        // false

        System.out.println("-------- class  isArray -------- ");
        System.out.println(studyParamClass.isArray());
        // false

        System.out.println("-------- class  isPrimitive -------- ");
        System.out.println(studyParamClass.isPrimitive());
        // false

        System.out.println("-------- class  isAnnotation -------- ");
        System.out.println(studyParamClass.isAnnotation());
        // false


        System.out.println("-------- class  getName -------- ");
        System.out.println(studyParamClass.getName());
        // com.study.pojo.StudyParam

        System.out.println("-------- class  getSimpleName -------- ");
        System.out.println(studyParamClass.getSimpleName());
        // StudyParam

        System.out.println("-------- class  getCanonicalName -------- ");
        System.out.println(studyParamClass.getCanonicalName());
        // com.study.pojo.StudyParam
        
        
        System.out.println("-------- class  getTypeName -------- ");
        System.out.println(studyParamClass.getTypeName());
        //com.study.pojo.StudyParam


        System.out.println("-------- class  getInterfaces -------- ");
        Class<?>[] interfaces = studyParamClass.getInterfaces();
        for (Class<?> interfacess : interfaces) {
            System.out.println(interfacess);
        }
        //interface com.study.pojo.StudyInfer

        System.out.println("-------- class  getSuperclass -------- ");
        Class<? super StudyParam> superclass = studyParamClass.getSuperclass();
        System.out.println(superclass);
        // class com.study.pojo.StudyParamParent

        System.out.println("-------- class  getGenericSuperclass -------- ");
        Type genericSuperclass = studyParamClass.getGenericSuperclass();
        System.out.println(genericSuperclass.getTypeName());
        // com.study.pojo.StudyParamParent


        System.out.println("-------- class  getPackage -------- ");
        Package aPackage = studyParamClass.getPackage();
        System.out.println(aPackage.getName());
        // com.study.pojo


        System.out.println("-------- class  getComponentType -------- ");
        StudyParam studyParam = studyParamClass.newInstance();
        studyParam.setStrings(new String[]{"1"});
        Class<?> componentType = studyParamClass.getComponentType();
        Class<?> componentType1 = studyParam.getStrings().getClass().getComponentType();
        System.out.println(componentType);
        System.out.println(componentType1);
        //null
        //class java.lang.String

        System.out.println("-------- class  getClassLoader -------- ");
        ClassLoader classLoader = studyParamClass.getClassLoader();
        System.out.println(classLoader);
        // sun.misc.Launcher$AppClassLoader@18b4aac2
    }
}

1、获取Class

涉及的方法如下:

方法名称 用途 返回值
forname 根据类全类名称获取类 Class

获取 Class 有四种方式:

  • Class.forname:根据类的全类名来获取
  • xxx.class:根据类来获取
  • new xxx().getClass():根据实例对象来获取
  • classloader.loadClass:根据类加载器加载

example:

Class clazz1 = Class.forName("com.study.pojo.StudyParam");

Class clazz2 = GenericTest.class;

Class clazz3 = new GenericTest().getClass();

ClassLoader loader = null;
loader.loadClass("com.study.pojo.StudyParam");

2、获取Class 中的方法(Method、Constructor)

类中有很多方法,包括:

  • 构造器
  • 私有(private)方法
  • 公共(public)方法
  • 保护(protected)方法
  • 默认(default)方法
  • 父类继承 / 接口实现的方法

常用获取类中方法的方式如下:

方法名称 用途 返回值
getMethods 或者本类以及父类或者父接口中所有的公共方法 Method[]
getMethod 获取本类以及父类或者父接口中所有的公共方法指定的Method Method
getDeclaredMethod 获取本类所有的方法中指定的Method,不包括继承的方法 Method
getDeclaredMethods() 获取本类所有的方法,不包括继承的方法 Method[]
getConstructors
getDeclaredConstructors
获取所有的构造方法
getConstructors包含所有的公共构造方法
getDeclaredConstructors 包含所有的构造方法
Constructor[]
getConstructor 获取指定构造方法 Constructor

方法使用举例:

package com.study;
import com.study.pojo.StudyInfer;
import com.study.pojo.StudyParam;
import com.study.pojo.StudyParamParent;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;

public class Study {

    public static void main(String[] args) throws NoSuchMethodException  {
Class<StudyParam> studyParamClass = StudyParam.class;
        System.out.println("-------- class  getConstructors -------- ");
        Constructor<?>[] constructors = studyParamClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
        //public com.study.pojo.StudyParam()
        //public com.study.pojo.StudyParam(java.lang.String,java.util.List,java.lang.String[],java.util.List)
        //public com.study.pojo.StudyParam(java.lang.String,java.util.List,java.util.List,java.lang.String)
        

        System.out.println("-------- class  getConstructor -------- ");
        Constructor<StudyParam> constructor = studyParamClass.getConstructor(String.class, List.class, List.class, String.class);
        System.out.println(constructor);
        //public com.study.pojo.StudyParam(java.lang.String,java.util.List,java.util.List,java.lang.String)
        

        System.out.println("-------- class  getDeclaredConstructors -------- ");
        Constructor<?>[] declaredConstructors = studyParamClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        //public com.study.pojo.StudyParam()
        //public com.study.pojo.StudyParam(java.lang.String,java.util.List,java.lang.String[],java.util.List)
        //private com.study.pojo.StudyParam(java.lang.String,java.util.List,java.util.List,java.lang.String,java.util.List)
        //public com.study.pojo.StudyParam(java.lang.String,java.util.List,java.util.List,java.lang.String)
        
        
        
        System.out.println("-------- class  getDeclaredConstructor -------- ");
        Constructor<StudyParam> declaredConstructor = studyParamClass.getDeclaredConstructor(String.class, List.class, List.class, String.class, List.class);
        System.out.println(declaredConstructor);
        //private com.study.pojo.StudyParam(java.lang.String,java.util.List,java.util.List,java.lang.String,java.util.List)


        System.out.println("-------- class  getMethods -------- ");
        Method[] methods = studyParamClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        
        //public java.lang.String com.study.pojo.StudyParam.toString()
        //public java.lang.String com.study.pojo.StudyParam.getName()
        //public void com.study.pojo.StudyParam.setName(java.lang.String)
        //public void com.study.pojo.StudyParam.setDList(java.util.List)
        //public void com.study.pojo.StudyParam.publicGetInfer()
        //public java.util.List com.study.pojo.StudyParam.getList()
        //public java.util.List com.study.pojo.StudyParam.getDList()
        //public void com.study.pojo.StudyParam.setList(java.util.List)
        //public void com.study.pojo.StudyParam.getPublicHa()
        //public void com.study.pojo.StudyParam.getPublicHa(java.lang.String)
        //public java.lang.String[] com.study.pojo.StudyParam.getStrings()
        //public void com.study.pojo.StudyParam.setStrings(java.lang.String[])
        //public void com.study.pojo.StudyParam.publicGet()
        //public void com.study.pojo.StudyParamParent.setDListPre(java.util.List)
        //public void com.study.pojo.StudyParamParent.publicGetParent()
        //public java.util.List com.study.pojo.StudyParamParent.getListPre()
        //public void com.study.pojo.StudyParamParent.setNamePre(java.lang.String)
        //public void com.study.pojo.StudyParamParent.setListPre(java.util.List)
        //public java.util.List com.study.pojo.StudyParamParent.getDListPre()
        //public java.lang.String com.study.pojo.StudyParamParent.getNamePre()
        //public void com.study.pojo.StudyParamParentPre.publicGetParentPre()
        //public java.util.List com.study.pojo.StudyParamParentPre.getDListPrePre()
        //public java.lang.String com.study.pojo.StudyParamParentPre.getNamePrePre()
        // public void com.study.pojo.StudyParamParentPre.setDListPrePre(java.util.List)
        //public void com.study.pojo.StudyParamParentPre.setListPrePre(java.util.List)
        //public void com.study.pojo.StudyParamParentPre.setNamePrePre(java.lang.String)
        //public java.util.List com.study.pojo.StudyParamParentPre.getListPrePre()
        //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 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()

        System.out.println("-------- class  getMethod -------- ");
        Method getPublicHa = studyParamClass.getMethod("getPublicHa", String.class);
        System.out.println(getPublicHa);
        //public void com.study.pojo.StudyParam.getPublicHa(java.lang.String)

        System.out.println("-------- class  getDeclaredMethods -------- ");
        Method[] declaredMethods = studyParamClass.getDeclaredMethods();
        for (Method method : declaredMethods) {
            System.out.println(method);
        }
        //public java.lang.String com.study.pojo.StudyParam.toString()
        //public java.lang.String com.study.pojo.StudyParam.getName()
        //public void com.study.pojo.StudyParam.setName(java.lang.String)
        //public void com.study.pojo.StudyParam.setDList(java.util.List)
        //public void com.study.pojo.StudyParam.publicGetInfer()
        //private void com.study.pojo.StudyParam.privateGet()
        //public java.util.List com.study.pojo.StudyParam.getList()
        //public java.util.List com.study.pojo.StudyParam.getDList()
        //public void com.study.pojo.StudyParam.setList(java.util.List)
        //public void com.study.pojo.StudyParam.getPublicHa()
        //public void com.study.pojo.StudyParam.getPublicHa(java.lang.String)
        //public java.lang.String[] com.study.pojo.StudyParam.getStrings()
        //public void com.study.pojo.StudyParam.setStrings(java.lang.String[])
        //private void com.study.pojo.StudyParam.getPrivateHa(java.lang.String)
        //private void com.study.pojo.StudyParam.getPrivateHa()
        //public void com.study.pojo.StudyParam.publicGet()
        //protected void com.study.pojo.StudyParam.protectedGet()

        System.out.println("-------- class  getDeclaredMethod -------- ");
        Method getPrivateHa = studyParamClass.getDeclaredMethod("getPrivateHa", String.class);
        System.out.println(getPrivateHa);
        //private void com.study.pojo.StudyParam.getPrivateHa(java.lang.String)
    }
}

3、获取Class 中的Filed

类中有很多属性,包括:

  • 私有(private)属性
  • 公共(public)属性
  • 保护(protected)属性
  • 默认(default)属性
  • 父类继承的属性

常用获取类中属性的方式如下:

方法名称 用途 返回值
getFields
getDeclaredFields
获取当前类和父类中 public 类型的 所有属性
获取当前类中的所有属性(public、protected、default、private)
Field[]
getField
getDeclaredField
获取当前类和父类中 public 类型的 指定属性
获取当前类中的指定属性(public、protected、default、private)
Field

方法使用举例:

package com.study;
import com.study.pojo.StudyInfer;
import com.study.pojo.StudyParam;
import com.study.pojo.StudyParamParent;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.List;

public class Study {

    public static void getFiledInfo() throws NoSuchFieldException {

        Class<StudyParam> studyParamClass = StudyParam.class;
        System.out.println("-------- class  getFields -------- ");
        Field[] fields = studyParamClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        // 无

        System.out.println("-------- class  getField -------- ");
        Field name = studyParamClass.getField("name");
        System.out.println(name);
        // 无

        System.out.println("-------- class  getDeclaredFields -------- ");
        Field[] declaredFields = studyParamClass.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field);
        }
        //java.lang.String com.study.pojo.StudyParam.name
        //java.util.List com.study.pojo.StudyParam.list
        //java.lang.String[] com.study.pojo.StudyParam.strings
        //java.util.List com.study.pojo.StudyParam.dList

        System.out.println("-------- class  getDeclaredField -------- ");
        Field declaredField = studyParamClass.getDeclaredField("name");
        System.out.println(declaredField);
        //java.lang.String com.study.pojo.StudyParam.name

    }

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, NoSuchFieldException {
        getFiledInfo();
    }
}

Method

为了下面的示例,在上述的 StudyParam 类中新增一个方法

package com.study.pojo;

import lombok.*;

import java.util.ArrayList;
import java.util.List;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class StudyParam extends StudyParamParent implements StudyInfer {


    public <T extends Throwable> List<String> getPublicHa(String name, String hhh, List<String> l, List<List<String>> ll) throws T, NullPointerException {
        System.out.println("getPublicHa  invoke  process");
        return new ArrayList<>();
    }

}

类中的方法为Method,Method常用的方法如下:

方法名称 用途 返回值
toString()
toGenericString
方法的名称字符串 String
isBridge
isVarArgs
isSynthetic
isDefault
是否是xxx,与上面的雷同 boolean
getReturnType
getGenericReturnType
返回方法返回值类型 Class
Type
getParameterTypes
getGenericParameterTypes
返回方法参数值类型 Class[]
Type[]
getExceptionTypes
getGenericExceptionTypes
返回方法异常抛出类型 Class[]
Type[]
getName 获取方法名称 String
invoke 方法执行
getParameterCount 获取方法的参数数量 int
getTypeParameters 获取方法一共都用了哪些泛型参数 TypeVariable[]
setAccessible 设置方法可访问

说明:(getGenericxxxx 这种相比较 getxxxx ,若涉及泛型会输出泛型里面参数的具体类型)

  • getReturnType、getGenericReturnType :返回方法返回值类型
  • getParameterTypes、getGenericParameterTypes :返回方法参数值类型
  • getExceptionTypes、getGenericExceptionTypes :返回方法异常抛出类型
  • invoke:方法反射执行

方法使用举例:

package com.study;
import com.study.pojo.StudyInfer;
import com.study.pojo.StudyParam;
import com.study.pojo.StudyParamParent;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.List;

public class Study {


    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, NoSuchFieldException {
        method();
    }

    public static void method() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class<StudyParam> studyParamClass = StudyParam.class;
        StudyParam  studyParam = new StudyParam();
        Method getPublicHa = studyParamClass.getMethod("getPublicHa", String.class ,String.class ,List.class,List.class);

        System.out.println("-------- method  toString -------- ");
        String toString = getPublicHa.toString();
        System.out.println(toString);
        // public java.util.List com.study.pojo.StudyParam.getPublicHa(java.lang.String,java.lang.String,java.util.List,java.util.List) throws java.lang.Throwable,java.lang.NullPointerException

        
        System.out.println("-------- method  toGenericString -------- ");
        String toGenericString = getPublicHa.toGenericString();
        System.out.println(toGenericString);
        // public  java.util.List com.study.pojo.StudyParam.getPublicHa(java.lang.String,java.lang.String,java.util.List,java.util.List>) throws T,java.lang.NullPointerException



        System.out.println("-------- method  isDefault -------- ");
        boolean defaults = getPublicHa.isDefault();
        System.out.println(defaults);
	   //false


        System.out.println("-------- method  getName -------- ");
        String name = getPublicHa.getName();
        System.out.println(name);
        // getPublicHa
        


        System.out.println("-------- method  getParameterCount -------- ");
        int parameterCount = getPublicHa.getParameterCount();
        System.out.println(parameterCount);
        // 4
        

        System.out.println("-------- method  getReturnType -------- ");
        Class<?> returnType = getPublicHa.getReturnType();
        System.out.println(returnType);
        // interface java.util.List


        System.out.println("-------- method  getGenericReturnType -------- ");
        Type genericReturnType = getPublicHa.getGenericReturnType();
        System.out.println(genericReturnType);
        // java.util.List
        

        System.out.println("-------- method  getParameterTypes -------- ");
        Class<?>[] parameterTypes = getPublicHa.getParameterTypes();
        for(Class<?> c : parameterTypes){
            System.out.println(c);
        }
        //class java.lang.String
        //class java.lang.String
        //interface java.util.List
        //interface java.util.List

        
        System.out.println("-------- method  getGenericParameterTypes -------- ");
        Type[] genericParameterTypes = getPublicHa.getGenericParameterTypes();
        for(Type t: genericParameterTypes){
            System.out.println(t);
        }
        //class java.lang.String
        //class java.lang.String
        //java.util.List
        //java.util.List>


        System.out.println("-------- method  getExceptionTypes -------- ");
        Class<?>[] exceptionTypes = getPublicHa.getExceptionTypes();
        for(Class<?> c : exceptionTypes){
            System.out.println(c);
        }
        //class java.lang.Throwable
        //class java.lang.NullPointerException

        
        System.out.println("-------- method  getGenericExceptionTypes -------- ");
        Type[] genericExceptionTypes = getPublicHa.getGenericExceptionTypes();
        for(Type t: genericExceptionTypes){
            System.out.println(t);
        }
        // T

        System.out.println("-------- method  getGenericExceptionTypes -------- ");
        Type[] genericExceptionTypes = getPublicHa.getGenericExceptionTypes();
        for(Type t: genericExceptionTypes){
            System.out.println(t);
        }
        // T

        System.out.println("-------- method  getTypeParameters -------- ");
        TypeVariable<Method>[] typeParameters = getPublicHa.getTypeParameters();
        for(TypeVariable<Method> typeVariable : typeParameters){
            System.out.println(typeVariable);
        }
        // T
        
        
        String invokeName = "name";
        String invokeHhh = "hh";
        List<String> invokeL = new ArrayList<>();
        List<List<String>> invokeLl = new ArrayList<>();
        getPublicHa.invoke(studyParam, invokeName , invokeHhh , invokeL , invokeLl);
        // getPublicHa  invoke  process
    }
}

Constructor

本次示例使用以下构造方法:

package com.study.pojo;

import lombok.*;

import java.util.ArrayList;
import java.util.List;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class StudyParam extends StudyParamParent implements StudyInfer {

    String name;

    List<String> list;

    String[] strings;

    List<List<String>> dList;

    public StudyParam(String namePre, List<String> listPre, List<List<String>> dListPre, String name) {
        super(namePre, listPre, dListPre);
        this.name = name;
        this.list = listPre;
        this.dList = dListPre;
    }
}

Constructor(构造方法) 与 Method 类似,Constructor 常用的方法如下:

方法名称 用途 返回值
toString()
toGenericString
方法的名称字符串 String
isVarArgs
isSynthetic
是否是xxx,与上面的雷同 boolean
getReturnType
getGenericReturnType
返回方法返回值类型 Class
Type
getParameterTypes
getGenericParameterTypes
返回方法参数值类型 Class[]
Type[]
getExceptionTypes
getGenericExceptionTypes
返回方法异常抛出类型 Class[]
Type[]
getName 获取方法名称 String
getParameterCount 获取方法的参数数量 int
getTypeParameters 获取方法一共都用了哪些泛型参数 TypeVariable

说明:(getGenericxxxx 这种相比较 getxxxx ,若涉及泛型会输出泛型里面参数的具体类型)

  • getReturnType、getGenericReturnType :返回方法返回值类型
  • getParameterTypes、getGenericParameterTypes :返回方法参数值类型
  • getExceptionTypes、getGenericExceptionTypes :返回方法异常抛出类型
  • newInstance:通过构造方法实例化对象

方法使用大多与Method相同,这里主要试 newInstance 方法来实例化类:

package com.study;
import com.study.pojo.StudyInfer;
import com.study.pojo.StudyParam;
import com.study.pojo.StudyParamParent;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.List;

public class Study {


    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, NoSuchFieldException {
        constructor();
    }
    
    public static void constructor() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        Class<StudyParam> studyParamClass = StudyParam.class;
        Constructor<StudyParam> declaredConstructor = studyParamClass.getDeclaredConstructor(String.class, List.class, List.class, String.class);

        String constructorPreName = "preName";
        String constructorName = "name";
        List<String> constructorPreL = new ArrayList<>();
        List<List<String>> constructorLl = new ArrayList<>();
        StudyParam studyParam = declaredConstructor.newInstance(constructorPreName, constructorPreL, constructorLl, constructorName);
        System.out.println(studyParam);
        // StudyParam(name=name, list=[], strings=null, dList=[])
    }

}

Filed

类中的属性为 Fileld,Fileld 常用的方法如下:

方法名称 用途 返回值
toString()
toGenericString
属性的名称字符串 String
isEnumConstant
isSynthetic
isAccessible
是否是xxx,与上面的雷同 boolean
getType
getGenericType
返回属性类型 Class
Type
getName 获取属性名称 String
setAccessible 设置属性可访问

说明:(getGenericxxxx 这种相比较 getxxxx ,若涉及泛型会输出泛型里面参数的具体类型)

  • getType、getGenericType:返回属性类型

方法使用举例:

package com.study;

import com.study.pojo.StudyInfer;
import com.study.pojo.StudyParam;
import com.study.pojo.StudyParamParent;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;

public class Study {

    public static void filed() throws NoSuchFieldException {
        Class<StudyParam> studyParamClass = StudyParam.class;

        Field declaredField = studyParamClass.getDeclaredField("dList");


        System.out.println("-------- filed  toString -------- ");
        String toString = declaredField.toString();
        System.out.println(toString);
        // java.util.List com.study.pojo.StudyParam.dList

        System.out.println("-------- filed  toGenericString -------- ");
        String toGenericString = declaredField.toGenericString();
        System.out.println(toGenericString);
        // java.util.List> com.study.pojo.StudyParam.dList


        System.out.println("-------- filed  isAccessible -------- ");
        boolean defaults = declaredField.isAccessible();
        System.out.println(defaults);
        declaredField.setAccessible(true);
        defaults = declaredField.isAccessible();
        System.out.println(defaults);
        // false
        // true


        System.out.println("-------- filed  getName -------- ");
        String name = declaredField.getName();
        System.out.println(name);
        // dList

        
		System.out.println("-------- filed  getType -------- ");
        Class<?> type = declaredField.getType();
        System.out.println(type);
        // interface java.util.List
        
        
        System.out.println("-------- filed  getGenericType -------- ");
        Type genericType = declaredField.getGenericType();
        System.out.println(genericType);
        // java.util.List>
    }

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {
        filed();
    }
}

实例化类

上述介绍了 反射、Class与Constructor,也介绍了其中的一些方法,此处之外,实例化类还有其他的几种方式,下面介绍一下:

  • 正常 new 对象
  • 调用 Class对象 的 newInstance 方法
  • 调用 Constructor 对象的 newInstance 方法
  • clone 对象拷贝方法
  • 通过ObjectInputStream的readObject()方法反序列化类

注意:这里五种方法,只有 clone 对象拷贝方法 不会执行构造方法

准备:

package com.study.pojo;
import lombok.*;
@Setter
@Getter
@ToString
public class Person {

    String name;
    String sex;

    public Person() {
        System.out.println("调用了无参构造方法");
    }

    public Person(String name, String sex) {
        this.name = name;
        this.sex = sex;
        System.out.println("调用了有参构造方法");
    }
}

1、正常 new 对象**(会调用构造方法)**

Person person = new Person();
//调用了无参构造方法
//Person(name=null, sex=null)

2、调用 Class对象 的 newInstance 方法 (会调用构造方法)

Person person = Person.class.newInstance();
System.out.println(person);
//调用了无参构造方法
//Person(name=null, sex=null)

3、调用 Constructor 对象的 newInstance 方法 (会调用构造方法)

Constructor<Person> declaredConstructor = Person.class.getDeclaredConstructor(String.class, String.class);
Person person = declaredConstructor.newInstance("myName", "mySex");
System.out.println(person);
//调用了有参构造方法
//Person(name=myName, sex=mySex)

4、clone 对象拷贝方法 (不会调用构造方法)

使用这种方式,必须实现 Cloneable 接口,可自定义重写 clone 方法

package com.study.pojo;
import lombok.*;
@Setter
@Getter
@ToString
public class Person implements Cloneable{

    String name;
    String sex;

    public Person() {
        System.out.println("调用了无参构造方法");
    }

    public Person(String name, String sex) {
        this.name = name;
        this.sex = sex;
        System.out.println("调用了有参构造方法");
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        System.out.println("调用了clone 方法");
        return super.clone();
    }
}

调用:

Person person = new Person();
try {
    Person clone =(Person) person.clone();
    System.out.println(clone);
    System.out.println(clone.equals(person));
} catch (CloneNotSupportedException e) {
    e.printStackTrace();
}
// 调用了clone 方法
// Person(name=null, sex=null)
// false

5、通过 ObjectInputStream的readObject() 方法反序列化类 (会调用构造方法)

使用这种方式,必须实现 Serializable 接口

package com.study.pojo;
import lombok.*;
import java.io.Serializable;

@Setter
@Getter
@ToString
public class Person implements Serializable {

    private final long serializableId = -1;

    String name;
    String sex;

    public Person() {
        System.out.println("调用了无参构造方法");
    }

    public Person(String name, String sex) {
        this.name = name;
        this.sex = sex;
        System.out.println("调用了有参构造方法");
    }

}

调用:

Person person = new Person();
FileOutputStream fos = new FileOutputStream("ci.tmp");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(person);
oos.close();
fos.close();

FileInputStream fis = new FileInputStream("ci.tmp");
ObjectInputStream ois = new ObjectInputStream(fis);
Person ci04 = (Person) ois.readObject();
System.out.println(ci04);
System.out.println(ci04.equals(person));
ois.close();
fis.close();

// 调用了无参构造方法
// Person(name=null, sex=null)
// false

你可能感兴趣的:(JAVA,面试,java,开发语言)