JavaSE 反射

18 反射机制

18.1 概述

  1. 概述

有什么用?通过反射机制可以操作字节码文件,可以读和修改字节码文件

在哪个包下?在java.lang.reflect包下

相关的类有哪些?

①java.lang.Class:代码字节码文件

②java.lang.reflect.Method:代表字节码的方法字节码

③java.lang.reflect.Constructor:代表字节码中的构造方法字节码

④java.lang.reflect.Field:代表字节码中的属性字节码

java.lang.Class类详述:

public class User{

//Field属性

int no;

//Constructor构造方法

public User(){

}

public User(int no){

}

//Method方法

public void setNo(int no){

this.no = no;

}

public int getNo(){

return no;

}

}

18.2 获取class的三种方式

  1. 代码实现
java 复制代码
package com.bjpowernode._14Reflect;

import java.util.Date;

/**
 要操作一个类的字节码,首先要获取这个类的字节码,怎么获取java.lang.Class实例
 第一种:Class c = Class.forName("完整类名带包名")
 第二种:Class c = 对象.getClass();
 */
public class Reflect01 {
    public static void main(String[] args) {
        //第一种方法:Class类中的静态方法
        //static Class forName(String className)返回带有给定字符串的名的类(参数传的String的包名,且必须带有包名)
        // 或接口相关联的Class对象
        Class c1= null;
        Class c2= null;
        try {
             c1 = Class.forName("java.lang.String");//c1代表String.class文件,或者说c1代表String类型
             c2 = Class.forName("java.util.Date");
            Class c3 = Class.forName("java.lang.Integer");
            Class c4 = Class.forName("java.lang.System");

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        //第二种方法:java中任何一个对象都有一个方法:getClass()
        String s = "abc";
        Class x = s.getClass();//x代表String.class字节码文件,x代表String类型
        System.out.println(c1==x);//看下内存地址一样吗,结果是true

        Date time = new Date();
        Class y = time.getClass();
        System.out.println(c2==y);//看下内存地址一样吗,结果是true
        //c2和y两个变量种保存到内存地址都是一样的,都指向方法区中的字节码文件,只有一份文件

        //第三种方式,java语言中任何一种类型,他都有.class属性
        Class z = String.class;//z代表String类型
        Class k = Date.class;
        Class f = int.class;
        Class e = double.class;

        System.out.println(z==x);//true
    }
}
  1. forName()类加载用法
java 复制代码
package com.bjpowernode._14Reflect;

/**
 研究下:Class.forName()发生了什么?
 如果想让一个静态代码块执行可以用forName()的方法
 后续JDBC技术的时候我们需要使用
 */
public class Reflect04 {
    public static void main(String[] args) {
        try {
            //forName()发生了类加载,静态代码块必然执行
            Class.forName("com.bjpowernode._14Reflect.MyClass");//MyClass类的静态代码块执行了
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }

    }
}


class MyClass{
    //静态代码块在类加载时执行,并且只执行一次
    static {
        System.out.println("MyClass类的静态代码块执行了");
    }
}

18.3 通过反射实例化对象

18.3.1 instance()实例化对象

User类

java 复制代码
package com.bjpowernode._14Reflect.Reflect02.bean;

public class User {
    public User(){
        System.out.println("无参构造方法!");
    }
//    //有参构造方法,无参构造器就等于没了
//    public User(String s){
//
//    }
}

程序入口类

java 复制代码
package com.bjpowernode._14Reflect.Reflect02.reflect;

import com.bjpowernode._14Reflect.Reflect02.bean.User;

/**
 获取到class,能干什么?
    通过Class的newInstance()方法来实例化对象
    注意:instance()底层会调用User类的无参构造器方法创建对象,必须保证无参构造是存在的!
 */
public class ReflectTest02 {
    public static void main(String[] args) {

        //这个是不使用反射机制,创建对象
        User user = new User();//无参构造方法!
        System.out.println(user);//com.bjpowernode._14Reflect.Reflect02.bean.User@1b6d3586


        //通过反射机制,获取Class,通过class实例化对象,
        try {
            Class c1 = Class.forName("com.bjpowernode._14Reflect.Reflect02.bean.User");
            //public T instance()方法:调用的是无参构造,必须保证无参构造是存在的!
            Object obj = c1.newInstance();//无参构造方法!instance()底层会调用User类的无参构造器方法创建对象
                                         //即使没有设置无参构造方法,也会自动构造
                                        //如果设置了有参构造器方法,无参相当于没有,instance()会报异常,
                                        //java.lang.InstantiationException:就会报异常,实例化异常
                                        // Caused by: java.lang.NoSuchMethodException: com.bjpowernode._14Reflect.Reflect02.bean.User.<init>()
            //或者加泛型
            Class<User> c2 = (Class<User>)Class.forName("com.bjpowernode._14Reflect.Reflect02.bean.User");
            User user1 = c2.newInstance();

            System.out.println(obj);//com.bjpowernode._14Reflect.Reflect02.bean.User@1b6d3586
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

18.3.2 通过读属性文件实例化对象

属性文件

properties 复制代码
className =com.bjpowernode._14Reflect.Reflect02.bean.User

程序入口类

java 复制代码
package com.bjpowernode._14Reflect;

import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

/**
 验证反射机制的灵活性
   java代码写一遍,在不改变java源代码的基础之上,通过配置文件,可以做到不同对象的实例化,非常之灵活,
   符合OCT开闭原则:对扩展开放,对修改关闭
   原来的new类只能创建一种类型的对象

 未来学的Spring,SpringMVC,MyBatis,Structs,Hibernate都是使用了反射机制
 */
public class Reflect03 {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        //通过IO流读取classinfo/properties文件
        FileReader reader = new FileReader("D:\\学习\\专业学习\\4-编程语言类\\java\\java代码\\13_Java_advanced\\Java_basic\\src\\main\\java\\com\\bjpowernode\\_14Reflect\\classinfo.properties");
        //创建属性类对象Map
        Properties pro = new Properties();
        //加载
        pro.load(reader);
        //关闭流
        reader.close();
        //通过key获取value
        String className = pro.getProperty("className");
        System.out.println(className);//com.bjpowernode._14Reflect.Reflect02.bean.User

        //通过反射机制实例化对象
        Class c = Class.forName(className);
        Object obj = c.newInstance();//无参构造方法!
        System.out.println(obj);//com.bjpowernode._14Reflect.Reflect02.bean.User@1b6d3586
    }
}

18.3.3 优化文件路径

  1. 获取文件路径getContextClassLoader()
java 复制代码
package com.bjpowernode._14Reflect;

import java.io.FileNotFoundException;
import java.io.FileReader;

/**
 研究一下文件路径的问题
 */
public class AboutPath05 {
    public static void main(String[] args) throws FileNotFoundException {
        //这种方式的路径缺点是:移植性差,在IDEA中默认的当前路径是project的根
        //离开IDEA,当前路径就不对了,路径无效
        //FileReader reader = new FileReader("main/java/com/bjpowernode/_14Reflect/classinfo.properties");

        //1.通用路径写法,但是前提是:文件必须在类路径下(在scr下的都是类路径下,scr的是类的根路径)
        /**
         解释:
         当前线程对象,getContextClassLoader()是线程对象的方法,目的是可以获取到当前线程的类加载器对象
         getResource()是类加载器对象的方法,默认当前线程的类加载器从类的根目录下加载资源
         可以拿到当前文件的绝对路径!!!

         */
        String path = Thread.currentThread().getContextClassLoader().getResource("classinfo2.properties").getPath();
        System.out.println(path);

        //2.获取classinfo.properties的绝对路径(从根路径下作为起点)
        String path2 = Thread.currentThread().getContextClassLoader()
                .getResource("main/java/com/bjpowernode/_14Reflect/classinfo.properties").getPath();
        System.out.println(path2);



    }
}

其实真正的类路径是out里面开始的路径,out表示输出的class类

  1. 具体运用在以往IO流案例上getResourceAsStream()
java 复制代码
package com.bjpowernode._14Reflect;

import sun.plugin2.ipc.InProcEvent;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class IoPropertiesTest06 {
    public static void main(String[] args) throws IOException {
        //1.可以获取绝对路径传进去,classinfo2.properties在src根目录下
        String path = Thread.currentThread().getContextClassLoader().
                getResource("classinfo2.properties").getPath();
        FileReader reader = new FileReader(path);
        Properties pro = new Properties();
        pro.load(reader);
        reader.close();
        //通过key获取value
        String className = pro.getProperty("className");
        System.out.println(className);

        //2.或者直接以流的形式返回
        InputStream reader2 = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("classinfo2.properties");
        System.out.println(reader2);


    }
}
  1. 资源绑定器ResourceBundle

不用使用File和Properties了,全部用资源绑定器,但是只能是properties文件

java 复制代码
package com.bjpowernode._14Reflect;

import java.util.ResourceBundle;

/**
 java.util包下提供了一个资源绑定器,便于获取属性配置文件中的内容(只能是properties结尾的文件)
 前提是属性配置文件xxx.properties必须放在类路径下(src下面)
 */
public class ResourceBundleTest07 {
    public static void main(String[] args) {
        //资源绑定器,记得去掉properties结尾
        ResourceBundle bundle = ResourceBundle.getBundle("classinfo2");
        //也不用pro对象去获取value了
        String className = bundle.getString("className");
        System.out.println(className);

    }
}

18.4 类加载器(额外)

复制代码
1. 概述

什么是类加载器?专门负责加载器的命令/工具

有什么加载器?

①启动类加载器

②扩展类加载器

③应用类加载器

  1. 场景:

假设有这样一段代码:

代码在开始执行之前,会将所需要类全部加载道JVM当中,通过类加载器加载,看到以上代码类加载器后类加载器会去找Spring.class文件去加载

  1. 具体:

通过"启动类加载器"加载。注意:专门加载rt.gar,是最重要的类库

如果"启动类加载器"加载不到,会通过"拓展类加载器"加载*.jar

如果"扩展类加载器"没有找到,会通过"应用类加载器"加载classpath中的类,就像以前配置的环境变量

  1. 双亲委派机制

java中为了保证类加载的安全,使用了双亲委派机制

"父"无法加载到,再从扩展类加载器加载,成为"母",叫做双亲委派,最后才会从应用类加载类加载,知道加载位置

是为了避免例如自己写一个String一摸一样的类,先加载启动类和扩展类中的String

18.4 获取和反射Field【属性】(了解)

  1. 获取Field属性getDeclaredFields()
java 复制代码
package com.bjpowernode._14Reflect.Relect08.reflect;

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

public class Reflect08 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取整个类
        Class studentClass = Class.forName("com.bjpowernode._14Reflect.Relect08.bean.Student");

        //获取类名
        System.out.println(studentClass.getName());//com.bjpowernode._14Reflect.Relect08.bean.Student
        System.out.println(studentClass.getSimpleName());//Student
        //获取类中所有的public修饰的Field
        Field[] fields = studentClass.getFields();
        System.out.println(fields.length);//1
        //取出元素
        Field f = fields[0];
        //取数Field的名字
        System.out.println(f.getName());//no
        System.out.println(f);//public int com.bjpowernode._14Reflect.Relect08.bean.Student.no

        //获取所有的Field
        Field[] fs = studentClass.getDeclaredFields();
        System.out.println(fs.length);//4

        //取出数组
        for (Field field : fs) {
            //
            //获取属性的名字
            System.out.println(field.getName());/**no name age sex*/


            //获取属性的类型
            System.out.println(field.getType());//int,java.lang.String,int,boolean

            //获取属性的类型简单名
            System.out.println(field.getType().getSimpleName());//int sex boolean boolean

            //获取属性的修饰符列表:getModifiers修饰符可能有多个
            //返回的修饰符是一个数字,每个数字是修饰符的代号,可以将代号转换成字符串吗?可以的
            System.out.println(field.getModifiers());//25
            int i = field.getModifiers();
            String modifierString = Modifier.toString(i);
        }

    }
        }
  1. 反编译Field
java 复制代码
package com.bjpowernode._14Reflect.Relect08.reflect;

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

//通过反射机制拿到了源码
public class ReReflect {
    public static void main(String[] args) throws ClassNotFoundException {

        //创建这个是为了拼接字符串
        StringBuilder s = new StringBuilder();

        Class studentClass = Class.forName("java.lang.String");

//        Class studentClass = Class.forName("com.bjpowernode._14Reflect.Relect08.bean.Student");
        //public class Student{}
        s.append(Modifier.toString(studentClass.getModifiers())+" class "+studentClass.getSimpleName()+"{\n");

        Field[] fields = studentClass.getDeclaredFields();

        for (Field field : fields) {
            s.append("\t"+Modifier.toString(field.getModifiers())+" "+field.getType().getSimpleName()+" "+field.getName()+";\n");
            
        }
        s.append("}");

        System.out.println(s);
        /**
         * public final class String{
         * 	private final char[] value;
         * 	private int hash;
         * 	private static final long serialVersionUID;
         * 	private static final ObjectStreamField[] serialPersistentFields;
         * 	public static final Comparator CASE_INSENSITIVE_ORDER;
         * }
         *
         * Process finished with exit code 0
         */
    }
}

18.5 通过反射机制访问对象属性

set(obj,"") get(obj)

java 复制代码
package com.bjpowernode._14Reflect.Relect08.reflect;

import com.bjpowernode._14Reflect.Relect08.bean.Student;

import java.lang.reflect.Field;

/**
 如何通过反射机制访问一个java对象的属性?
 即给属性赋值set/获取属性的get
 */
public class Reflect09 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //1.
        //我们不适用反射机制,怎么去访问一个对象的属性?
        Student s = new Student();
        //给属性赋值:三要素:对象,no属性,值
        s.no = 1111;
        //读属性值:两要素:1对象 2 值
        System.out.println(s.no);//1111

        //使用反射机制如何访问一个对象的属性
        Class studentClass = Class.forName("com.bjpowernode._14Reflect.Relect08.bean.Student");
        Object obj = studentClass.newInstance();//obj就是Student对象(底层调用无参构造器方法)

        //获取no属性(根据属性名称来获取Field),使用反射机制我可以把属性名称写到配置文件中
        Field noField = studentClass.getDeclaredField("no");

        //给object对象(Student)的no属性赋值
        //虽然使用了反射对象,但是三要素缺一不可:1对象2no属性32222
        //虽然反射机制让代码复杂了,但是为了一个"灵活",也是值得的
        noField.set(obj,2222);//给obj的对象赋值2222

        //获取no属性的值:两要素:1对象 2 值
        System.out.println(noField.get(obj));//2222


        //2.可以访问私有的属性吗?
        Field namefield = studentClass.getDeclaredField("name");
        //namefield.set(obj,"jackson");//报错:私有的范围不了

        //打破封装(反射机制缺点:打破封装,会给不法分子留下机会!!!)
        namefield.setAccessible(true);

        namefield.set(obj,"jackson");//报错:私有的范围不了

        System.out.println(namefield.get(obj));//jackson
    }
}

18.6 反射Method【方法】(了解)

1.可变长度参数

m(int ...args)

java 复制代码
package com.bjpowernode._14Reflect.Relect08.reflect;

/**
 1.可变长度参数要求的参数个数是:0~N个
 2.可变长度参数在参数列表中必须在最后一个位置上,而且可变长度参数只能有1个
 3.可变参数可以当作一个数组来看待
 */
public class ArgsTest {
    public static void main(String[] args) {
        m();
        m(10);
        m(10,20);
        //m("abc");编译报错


        m2(100);
        m2(200,"abc");
        m2(200,"abc","def");

        m3("ab","de","gh");
        String[] strs = {"a","b","c"};
        m3(strs);
        m3(new String[]{"我","是","中","国","人"});

    }

    public static void m(int ...args){
        System.out.println("m方法执行了!");
    }

//    public static void m2(String...args1,int...args2){//编译报错
//
//    }

        //必须只能有一个,并且在最后
        public static void m2(int a,String...args2){

    }

    public static void m3(String...args2){
        //args有length属性,说明是一个数组!
        //将可变长度参数可以当作数组
        for (int i = 0; i < args2.length; i++) {
            System.out.println(args2[i]);
        }
    }
}
  1. 反射Method方法
java 复制代码
package com.bjpowernode._14Reflect.Relect08.reflect;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;

/**
 作为了解内容"反射Method
 */
public class Reflect11 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取类
        Class userServiceClass = Class.forName("com.bjpowernode._14Reflect.Relect08.service.UserService");
        //获取所有的Method
        Method[] methods = userServiceClass.getDeclaredMethods();
        System.out.println(methods.length);
        //遍历方法
        for (Method method : methods) {
            System.out.println(method.getName());//login logout
            //获取方法返回类型
            System.out.println(method.getReturnType().getSimpleName());//boolean void
            //获取修饰符
            System.out.println(Modifier.toString(method.getModifiers()));//public public
            //获取参数
            Class[] parameterTypes= method.getParameterTypes();
            for (Class parameterType : parameterTypes) {
                System.out.println(parameterType.getSimpleName());//String String 
            }
        }
    }
}
  1. 反编译Method
java 复制代码
package com.bjpowernode._14Reflect.Relect08.reflect;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * 了解内容:反编译Method()
 */
public class Reflect12 {
    public static void main(String[] args) throws ClassNotFoundException {
        StringBuilder s = new StringBuilder();
        //获取类,可以灵活获取类的方法
//        Class userServiceClass = Class.forName("com.bjpowernode._14Reflect.Relect08.service.UserService");
        Class userServiceClass = Class.forName("java.lang.String");

        //
        s.append(Modifier.toString(userServiceClass.getModifiers())+" class "+userServiceClass.getSimpleName()+"{\n");
       //    public boolean login(String name,String password){
        for (Method methods : userServiceClass.getDeclaredMethods()) {
            s.append("\t");
            s.append(Modifier.toString(methods.getModifiers())+" ");
            s.append(methods.getReturnType().getSimpleName()+" ");
            s.append(methods.getName());
            s.append("(");
            Class[] parameterTypes = methods.getParameterTypes();
            for (Class parameterType : parameterTypes) {
                s.append(parameterType.getSimpleName());
                s.append(",");
            }
            //删除指定下边位置上面的字符
            s.deleteCharAt(s.length()-1);

            s.append("){}\n");
            
        }
        s.append("}");
        System.out.println(s);
    }
}

18.7 反射机制调用方法(最重要)

invoke()

java 复制代码
package com.bjpowernode._14Reflect.Relect08.reflect;

import com.bjpowernode._14Reflect.Relect08.service.UserService;

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

/**
 * 重点:必须掌握
 反射机制,让代码更灵活且具有通用性,可变化的内容都是写到配置文件中
 将来创建对象不一样,调用方法也不同了,修改配置文件即可
 */
public class ReflectTest13 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //不使用反射机制,如何调用方法
        UserService userService = new UserService();
        //调用方法:要素分析:1对象2方法3实际参数列表4返回值
        boolean logicSuccess = userService.login("admin", "12312312");
//        System.out.println(logicSuccess);
        System.out.println(logicSuccess?"登录成功":"登陆失败");


        //使用反射机制调用一个对象的方法
        Class userClass = Class.forName("com.bjpowernode._14Reflect.Relect08.service.UserService");
        Object obj = userClass.newInstance();
        //获取方法单纯靠方法名是不行的,有的方法名是重载的,可能同名
        //java中如何去定一个方法,通过方法名和参数列表
        // public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
        //传String.class是因为:java语言中任何一种类型,他都有.class属性 Class z = String.class;
        Method loginMethod = userClass.getDeclaredMethod("login", String.class, String.class);

        //调用方法 要素分析:1对象2方法3实际参数列表4返回值
        // 反射机制中最重要东西!!
        Object retValue = loginMethod.invoke(obj, "admin", "12312312");
        System.out.println(retValue);//false
    }
}

18.8 反射Constructor【构造器】

  1. 反编译Constructor
java 复制代码
package com.bjpowernode._14Reflect.Relect08.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.lang.reflect.TypeVariable;

public class Reflect14 {
    public static void main(String[] args) throws ClassNotFoundException {
        StringBuilder s = new StringBuilder();
        //类名public class Vip{}
//        Class vipClass = Class.forName("com.bjpowernode._14Reflect.Relect08.bean.Vip");
                Class vipClass = Class.forName("java.lang.String");
        s.append(Modifier.toString(vipClass.getModifiers()));
        s.append(" class ");
        s.append(vipClass.getSimpleName());
        s.append("{\n");


        //拼接构造方法
        Constructor[] constructors = vipClass.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            s.append("\t");
            s.append(Modifier.toString(constructor.getModifiers()));
            s.append(" ");
            s.append(vipClass.getSimpleName());
            s.append("(");
            //拼接参数
            Class[] parametersTypes = constructor.getParameterTypes();
            for (Class parametersType : parametersTypes) {
                s.append(parametersType.getSimpleName());
                s.append(",");

            }

            //如果数组长度大于0,再删除最后下标位置上的字符
            if(parametersTypes.length>0){
            s.deleteCharAt(s.length()-1);}

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

        s.append("}");
        System.out.println(s);
    }
}
  1. 通过反射机制如何创造对象
java 复制代码
package com.bjpowernode._14Reflect.Relect08.reflect;

import com.bjpowernode._14Reflect.Relect08.bean.Vip;

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

/**
 通过反射机制调用构造方法实例化java对象
 */
public class Reflect15 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //不使用反射机制如何创建对象
        Vip v1 = new Vip();
        Vip v2 = new Vip(110,"zhangsan","2001-10-11",true);

        //使用机制如何创建对象
        Class c = Class.forName("com.bjpowernode._14Reflect.Relect08.bean.Vip");
        //调用无参数的构造方法
        Object obj = c.newInstance();
        //调用有参数的构造方法
        //第一步:先获取到有参数的构造方法,括号中传形参
        Constructor con = c.getDeclaredConstructor(int.class, String.class, String.class, boolean.class);
        //第二步:调用构造方法new对象,传参
        Object newObj = con.newInstance(110, "jackson", "2000-11-08",true);
        System.out.println(newObj);//Vip{no=110, name='jackson', birth='2000-11-08', sex=true}

        //获取无参数构造方法
        Constructor con2 = c.getDeclaredConstructor();
        Object newObj2 = con2.newInstance();
        System.out.println(newObj2);//Vip{no=0, name='null', birth='null', sex=false}


    }


}

18.9 反射获取父类和父接口

  1. getSuperclass(),getInterfaces()
java 复制代码
package com.bjpowernode._14Reflect.Relect08.reflect;

/**
 重点:给你一个类,怎么获取这个类的父类,已经实现了什么接口
 */
public class Reflect16 {
    public static void main(String[] args) throws ClassNotFoundException {
        //String举例
        Class stringClass= Class.forName("java.lang.String");

        //获取String的父类
        Class superclass = stringClass.getSuperclass();
        System.out.println(superclass.getName());//java.lang.Object

        //获取String类实现的所有接口(一个类可以实现多个接口)
        Class[] interfaces = stringClass.getInterfaces();
        for (Class in : interfaces) {
            System.out.println(in.getName());
        }
        //java.io.Serializable
        //java.lang.Comparable
        //java.lang.CharSequence
    }
}
相关推荐
木辰風6 小时前
PLSQL自定义自动替换(AutoReplace)
java·数据库·sql
heartbeat..6 小时前
Redis 中的锁:核心实现、类型与最佳实践
java·数据库·redis·缓存·并发
6 小时前
java关于内部类
java·开发语言
好好沉淀6 小时前
Java 项目中的 .idea 与 target 文件夹
java·开发语言·intellij-idea
gusijin6 小时前
解决idea启动报错java: OutOfMemoryError: insufficient memory
java·ide·intellij-idea
To Be Clean Coder6 小时前
【Spring源码】createBean如何寻找构造器(二)——单参数构造器的场景
java·后端·spring
吨~吨~吨~6 小时前
解决 IntelliJ IDEA 运行时“命令行过长”问题:使用 JAR
java·ide·intellij-idea
你才是臭弟弟6 小时前
SpringBoot 集成MinIo(根据上传文件.后缀自动归类)
java·spring boot·后端
短剑重铸之日6 小时前
《设计模式》第二篇:单例模式
java·单例模式·设计模式·懒汉式·恶汉式
码农水水6 小时前
得物Java面试被问:消息队列的死信队列和重试机制
java·开发语言·jvm·数据结构·机器学习·面试·职场和发展