Rubin's Blog

  • 首页
  • 关于作者
  • 隐私政策
享受恬静与美好~~~
分享生活的点点滴滴~~~
  1. 首页
  2. 面试
  3. 正文

java面试系列之反射

2021年 4月 26日 992点热度 0人点赞 0条评论

前言

我们在编码学习或者面试过程中经常会提到反射这个概念。今天我们就简单聊一下反射。

概念

反射是什么呢?或者说,反射机制是什么呢?Java的反射机制,就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和访问它的任意属性;这种动态获取信息,以及任意动态调用对象方法的功能称之为Java的反射机制。

类加载器

概念

ClassLoader在Java中有着非常重要的作用,它主要工作在Class装载的阶段,其重要作用是从系统外部获得Class的二进制数据流。它是Java的核心组件,所有的Class都是由ClassLoader加载的,ClassLoader负责将Class文件的二进制数据流装载进系统,然后交给Java虚拟机进行连接初始化等操作。

分类

  • BootstrapClassLoader:C++编写,加载核心库java.*。
  • ExtClassLoader:Java编写,加载扩展库javax.*。
  • AppClassLoader:Java编写,加载程序所在目录。
  • 自定义ClassLoader:Java编写,定制化加载。

自定义ClassLoader

重点关注findClass和defineClass两个方法:

package com.rubin;
import java.io.*;
/**
 * Created by rubin on 2019/5/4.
 */
public class MyClassLoader extends ClassLoader {

    private String path;

    public MyClassLoader(String path) {
        this.path = path;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] cByte = this.loadClassData(name);
        return defineClass(name, cByte, 0, cByte.length);
    }

    private byte[] loadClassData(String s) {

        FileInputStream in = null;
        ByteArrayOutputStream out = null;

        try {
            in = new FileInputStream(new File(path + s + ".class"));
            out = new ByteArrayOutputStream();
            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return out.toByteArray();
    }
}

调用示例:

public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        MyClassLoader m = new MyClassLoader("/Users/rubin/Desktop/");
        Class c = m.findClass("Test");
        c.newInstance();
}

双亲委派机制

概念

双亲委派机制,简单来说就是在ClassLoader加载类的时候,首先查找父ClassLoader加载的类中有没有该类,有的话,就不重复加载,而是直接使用已经加载的类。如下图所示:

作用

避免重复加载相同的字节码

loadClass和forName的区别

如下图所示:

图中我们可以看到,类的加载过程分为三步:加载、链接和初始化。Class.forName方法,会执行类加载的全部步骤,而ClassLoader.loadClass只会执行类的加载过程,并不会执行链接和初始化。

常用方法

getName()

解释

获取类的类类型对象在Java虚拟机中的名称

示例

  • String.class.getName() -> "java.lang.String"
  • byte.class.getName() -> "byte"
  • (new Object[3]).getClass().getName() -> "[Ljava.lang.Object;"
  • (new int[3][4][5][6][7][8][9]).getClass().getName() -> "[[[[[[[I"

getClassLoader()

解释

获取类的类加载器

getTypeParameters()

解释

获取类的泛型数组

示例

  • Map.class.getTypeParameters() -> [K, V]
  • List.class.getTypeParameters() -> [E]

getSuperclass()

解释

获取类的父类(注意:如果类没有父类,将返回Object的Class,如果是接口话,调用该方法将返回null)

示例

  • Map.class.getSuperclass() -> null
  • HashMap.class.getSuperclass -> java.util.AbstractMap
  • Object.class.getSuperclass() -> null
  • HashMap[].class.getSuperclass() -> java.lang.Object

getGenericSuperclass()

解释

获取类的父类(如果有泛型也会返回父类的泛型)(注意:如果类没有父类,将返回Object的Class,如果是接口话,调用该方法将返回null)

示例

  • Map.class.getGenericSuperclass() -> null
  • HashMap.class.getGenericSuperclass-> java.util.AbstractMap<K, V>
  • Object.class.getGenericSuperclass() -> null
  • HashMap[].class.getGenericSuperclass()-> java.lang.Object

getPackage()

解释

获取类所在的包(如果没有包,将返回null,比如数组)

示例

  • HashMap.class.getPackage().getName() -> java.util
  • HashMap[].class.getPackage().getName() -> null

isPrimitive()

解释

判断该类是不是原始类型(八种基本类型)

getInterfaces()

解释

获取该类所实现的接口类列表(注意:只包含自己的,不包含父类实现的接口)

getGenericInterfaces()

解释

获取该类所实现的接口类型(Type)列表(如果有泛型也会返回父类的泛型)(注意:只包含自己的,不包含父类实现的接口)

getComponentType()

解释

获取数组类的元素的类类型,如果是基本类型,则返回null(提示:可以通过Array.newInstance()来反射生成数组对象)

示例:

  • char.class.getComponentType() -> null
  • char[].class.getComponentType() -> char
  • char[] charArr = (char[])Array.newInstance(char[].class.getComponentType(), 10)

getModifiers()

解释

获取类的访问修饰符,该方法返回一个int类型的数字,通过Modifier.toString(i)来获取修饰符的文案。

示例

  • Modifier.toString(Integer.class.getModifiers()) -> public final

getDeclaringClass()

解释

获取类的声明类。源码中的解释是如果此类是另外一个类中声明的属性或者方法,则返回声明类的类类型。数组或者泛型或者void等等基础类均返回null。如果该类不是另一个类中声明的变量或者方法,则返回null。

示例

  • HashMap.class.getDeclaringClass() -> null

getSimpleName()

解释

获取类在源码中的名称(不包含包的名称),如果是数组,将返回类的名称并拼接上[],如果是匿名内部类,则返回空串。

示例

  • HashMap.class.getSimpleName() -> HashMap
  • HashMap[].class.getSimpleName() -> HashMap[]

getTypeName()

解释

获取类的类型的名称,如果是数组,将返回名称的基础上拼接上[]。匿名内部类将返回引用类的类名称。

示例

  • Map.class.getTypeName() -> java.util.Map
  • public class Test {
    
        public static void main(String[] args) throws Exception {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // 这个输出将打印 com.rubin.aspect.Test$1
                    System.out.println(this.getClass().getTypeName());
                }
            }).start();
        }
    
    }

getCanonicalName()

解释

将按照java语言规范来反回类的名称。匿名内部类将返回null。

示例

  • Map.class.getCanonicalName() -> java.util.Map
  • Map[].class.getCanonicalName() -> java.util.Map[]

isAnonymousClass()

解释

判断是不是匿名类。

示例

  • Map.class.isAnonymousClass() -> false
  • Map[].class.isAnonymousClass() -> false

isMemberClass()

解释

判断是不是内部类。

示例

  • Map.class.isMemberClass() -> false
  • Map.Entry.class.isMemberClass() -> true

getClasses()

解释

返回该类声明为public的成员内部类或者接口类的集合(包括自己声明的以及继承父类的所有的public的成员内部类的类型)。基本类型或者数组将返回空集合。

示例

  • Arrays.toString(HashMap.class.getClasses()) -> [class java.util.AbstractMap$SimpleEntry, class java.util.AbstractMap$SimpleImmutableEntry]
  • Arrays.toString(HashMap[].class.getClasses()) -> []

getFields()

解释

返回该类声明的所有public的、继承父类(包括父类的父类,一直到最顶级)的public的以及实现所有接口(包括接口的父接口,一直到最顶级)的属性集合。集合类和基本类返回空数组。

示例

  • Arrays.toString(Connection.class.getFields()) -> [public static final int java.sql.Connection.TRANSACTION_NONE,...]
  • Arrays.toString(Connection[].class.getFields()) -> []

getMethods()

解释

返回该类声明的所有public的(这里面包括了所有实现接口的方法)、继承父类(包括父类的父类,一直到最顶级)的public的方法集合。集合类返回Object类定义的public的方法。基本类返回空数组。

示例

  • Arrays.toString(Connection.class.getMethods()) -> [public abstract void java.sql.Connection.setReadOnly(boolean) throws java.sql.SQLException,...]
  • Arrays.toString(Connection[].class.getMethods()) -> [public final void java.lang.Object.wait() throws java.lang.InterruptedException,...]

getConstructors()

解释

返回该类所声明的所有public的构造器列表。数组、接口或者基本类型返回空数组。

示例

  • Arrays.toString(HashMap.class.getConstructors()) -> [public java.util.HashMap(int), public java.util.HashMap(), public java.util.HashMap(java.util.Map), public java.util.HashMap(int,float)]
  • Arrays.toString(HashMap[].class.getConstructors()) -> []

getField(String name)

解释

通过属性名称来获取该类中或者父类中(包含弗雷德父类,一直到顶级父类)或者实现的接口中(包括接口的父接口,一直到顶级接口)声明的public的属性。查找顺序为先查找本类中,本类查不到的话会去查找实现的所有接口(包括父类实现的接口),接口查不到会再去查找所有父类。如果均查不到,会抛出异常。数组或者基本类型会抛出异常。

getMethod(String name, Class<?>... parameterTypes)

解释

通过方法名称和参数列表(按照声明顺序传值,为了准确查找重载的方法)来获取该类中或者父类中(包含弗雷德父类,一直到顶级父类)或者实现的接口中(包括接口的父接口,一直到顶级接口)声明的public的方法。查找顺序为先查找本类中,本类查不到的话会去查找实现的所有接口(包括父类实现的接口),接口查不到会再去查找所有父类。如果均查不到,会抛出异常。

getConstructor(Class<?>... parameterTypes)

解释

获取本类中参数列表相符合(顺序也要一致)的public的构造器对象。找不到会抛出异常。

getDeclaredClasses()

解释

返回该类声明的所有成员内部类或者接口类的集合(但是不包括继承的)。基本类型或者数组将返回空集合。

getDeclaredFields()

解释

返回该类所声明的所有属性集合(不包括继承的)。数组将返回空集合。

getDeclaredMethods()

解释

返回该类所声明的所有方法集合(不包括继承的)。数组将返回空集合。

getDeclaredConstructors()

解释

返回该类所声明的所有构造器集合(不包括继承的)。数组、基本类型、接口将返回空集合。

getDeclaredField(String name)

解释

获取该类中声明的(不包括父类)名为name的属性。找不到则抛出异常。数组、基本类型无任何声明属性。

getDeclaredMethod(String name, Class<?>... parameterTypes)

解释

返回该类所声明的参数列表匹配(类型和顺序)的方法对象(不包含父类),找不到会抛出异常。数组、基本类型无任何声明方法。

getDeclaredConstructor(Class<?>... parameterTypes)

解释

获取本类中参数列表相符合(顺序也要一致)的构造器对象(不区分访问标识符)。找不到会抛出异常。

getResourceAsStream(String name)

解释

将classpath下的文件加载为输入流,name为当前类的相对路径。如果从classpath根目录下加载,在路径上面加/。例如/com/rubin/demo/Demo.class。也可以通过相对路径加载,比如当前文件同目录下的文件:Test.class。

getAnnotation(Class<A> annotationClass)

解释

获取某个类下(如果次注解被@Inherited元注解标注,则会向上查找父类标注的注解有无此注解)指定类型的注解实体。

isAnnotationPresent(Class<? extends Annotation> annotationClass)

解释

判断当前类的实体上(如果次注解被@Inherited元注解标注,则会向上查找父类标注的注解有无此注解)是否标有某个注解。

getAnnotations()

解释

获取当前类(以及父类上面的被@Inherited元注解标注的注解)上面标注的所有的注解集合。没有注解返回空数组。

getAnnotationsByType(Class<T> annotationClass)

解释

源码当中的解释是查找相关联的注解列表。也就是说,如果要查找的注解类型是可继承的(注解被@Inherited元注解标注),则会首先查找本类上面是否有该注解,没有的话,会查找他的父类,看是否有该注解,并返回注解集合(通常找到了就只有目标注解一个元素,没找到则返回空集合)。

getDeclaredAnnotation(Class<T> annotationClass)

解释

获取当前类(会忽略父类上的任意注解)上的某个直接标注的注解。

getDeclaredAnnotationsByType(Class<T> annotationClass)

解释

通过类型获取当前类上直接标注的注解中的关联注解集合列表。通常有的话,会返回含有该注解一个元素的集合,没有返回空集合。

getDeclaredAnnotations()

解释

获取该类上直接标注(忽略所有父类的任意注解)的注解的集合。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: 面试
最后更新:2022年 6月 9日

RubinChu

一个快乐的小逗比~~~

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复
文章目录
  • 前言
  • 概念
  • 类加载器
    • 概念
    • 分类
    • 自定义ClassLoader
    • 双亲委派机制
      • 概念
      • 作用
    • loadClass和forName的区别
  • 常用方法
    • getName()
      • 解释
      • 示例
    • getClassLoader()
      • 解释
    • getTypeParameters()
      • 解释
      • 示例
    • getSuperclass()
      • 解释
      • 示例
    • getGenericSuperclass()
      • 解释
      • 示例
    • getPackage()
      • 解释
      • 示例
    • isPrimitive()
      • 解释
    • getInterfaces()
      • 解释
    • getGenericInterfaces()
      • 解释
    • getComponentType()
      • 解释
      • 示例:
    • getModifiers()
      • 解释
      • 示例
    • getDeclaringClass()
      • 解释
      • 示例
    • getSimpleName()
      • 解释
      • 示例
    • getTypeName()
      • 解释
      • 示例
    • getCanonicalName()
      • 解释
      • 示例
    • isAnonymousClass()
      • 解释
      • 示例
    • isMemberClass()
      • 解释
      • 示例
    • getClasses()
      • 解释
      • 示例
    • getFields()
      • 解释
      • 示例
    • getMethods()
      • 解释
      • 示例
    • getConstructors()
      • 解释
      • 示例
    • getField(String name)
      • 解释
    • getMethod(String name, Class<?>... parameterTypes)
      • 解释
    • getConstructor(Class<?>... parameterTypes)
      • 解释
    • getDeclaredClasses()
      • 解释
    • getDeclaredFields()
      • 解释
    • getDeclaredMethods()
      • 解释
    • getDeclaredConstructors()
      • 解释
    • getDeclaredField(String name)
      • 解释
    • getDeclaredMethod(String name, Class<?>... parameterTypes)
      • 解释
    • getDeclaredConstructor(Class<?>... parameterTypes)
      • 解释
    • getResourceAsStream(String name)
      • 解释
    • getAnnotation(Class<A> annotationClass)
      • 解释
    • isAnnotationPresent(Class<? extends Annotation> annotationClass)
      • 解释
    • getAnnotations()
      • 解释
    • getAnnotationsByType(Class<T> annotationClass)
      • 解释
    • getDeclaredAnnotation(Class<T> annotationClass)
      • 解释
    • getDeclaredAnnotationsByType(Class<T> annotationClass)
      • 解释
    • getDeclaredAnnotations()
      • 解释
最新 热点 随机
最新 热点 随机
问题记录之Chrome设置屏蔽Https禁止调用Http行为 问题记录之Mac设置软链接 问题记录之JDK8连接MySQL数据库失败 面试系列之自我介绍 面试总结 算法思维
MyBatis之延迟加载 Kafka高级特性之物理存储 Redis之Codis集群搭建 SpringCloud Alibaba之微服务开发 Nginx之一致性hash负载均衡器 java面试系列之Linux

COPYRIGHT © 2021 rubinchu.com. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

京ICP备19039146号-1