美文网首页
Java 反射

Java 反射

作者: 孤独的根号十二 | 来源:发表于2019-02-22 15:07 被阅读1次

什么是Class类

Class 类是在Java语言中定义一个特定类的实现。一个类的定义包含成员变量,成员方法,还有这个类实现的接口,以及这个类的父类。Class类的对象用于表示当前运行的 Java 应用程序中的类和接口。 比如:每个数组均属于一个 Class 类对象,所有具有相同元素类型和维数的数组共享一个Class 对象。基本的 Java 类型(boolean, byte, char, short,int, long, float 和 double) 和 void 类型也可表示为 Class 对象。

我们都知道所有的java类都是继承了object这个类,在object这个类中有一个方法:getclass().这个方法是用来取得该类已经被实例化了的对象的该类的引用,这个引用指向的是Class类的对象(呵呵,有点别扭)。我们自己无法生成一个Class对象(构造函数为private),而这个Class类的对象是在当各类被调入时,由 Java 虚拟机自动创建 Class 对象,或通过类装载器中的 defineClass 方法生成。 我们生成的对象都会有个字段记录该对象所属类在CLass类的对象的所在位置。我们可以把每个Class类的对象当做众多类的代理。而且在每个Class类对象中有会有字段记录他引用的这个类的类加载器。如果该字段为null,表示该类的加载器为bootstrap loader。如下图所示:


内存示意图.png

获取Class对象的三种方式

1.通过类名获取 类名.class

2.通过对象获取 对象名.getClass()

3.通过全类名获取 Class.forName(全类名)

forName(String classname)和 forName(Stringclassname,{}boolean initialze,ClassLoader loader)方法。该方法返回给定串名相应的Class对象。若给定一个类或接口的完整路径名,那么此方法将试图定位、装载和连接该类。若成功,返回该类对象。否则,抛出ClassNotFoundException异常。例如,下面代码段返回名为java.lang.Thread的运行Class描述器。Classt=Class.forName("java.lang.Thread");此方法是需要指定类加载器的,当用到仅有一个String参数的forName方法时,Class对象将默认调用当前类加载器作为加载器和将第二参数为true。第二个参数说明:如果是false时,调用forName方法只是在命令类加载器载入该类,而不初始化该类的静态区块,只有当该类第一次实例化时,静态区块才被调用。当为true时,则载入时就调用静态区块。

public class ReflectionTest {
    @Test
    public void testClass() throws ClassNotFoundException {
       Class clazz = null;
       
       //1.通过类名
       clazz = Person.class;
       

       //2.通过对象名
       //这种方式是用在传进来一个对象,却不知道对象类型的时候使用
       Person person = new Person();
       clazz = person.getClass();
       //上面这个例子的意义不大,因为已经知道person类型是Person类,再这样写就没有必要了
       //如果传进来是一个Object类,这种做法就是应该的
       Object obj = new Person();
       clazz = obj.getClass();
       

       //3.通过全类名(会抛出异常)
       //一般框架开发中这种用的比较多,因为配置文件中一般配的都是全类名,通过这种方式可以得到Class实例
       String className=" com.atguigu.java.fanshe.Person";
       clazz = Class.forName(className);       
       


       
       //字符串的例子
       clazz = String.class;
       
       clazz = "javaTest".getClass();
       
       clazz = Class.forName("java.lang.String");
       
       System.out.println(); 
    }
}

Class的常用方法

Object newInstance()

调用缺省构造函数,返回该Class对象的一个实例

Object newInstance(Object []args)

调用当前格式构造函数,返回该Class对象的一个实例

Class getSuperClass()

返回当前Class对象的父类的Class对象

Class [] getInterfaces

获取当前Class对象的接口

ClassLoader getClassLoader()

返回该类的类加载器

Method [] getMethods

获取取clazz对应类中的所有方法,不能获取private方法,且获取从父类继承来的所有方法

Method[] getDeclaredMethods()

获取所有方法,包括私有方法,所有声明的方法,都可以获取到,且只获取当前类的方法

Method getDeclaredMethod("funcName", Object.class);

获取指定的方法, 需要参数名称和参数列表,无参则不需要写

Field[] getDeclaredFields();

获取所有字段,可以获取公用和私有的所有字段,但不能获取父类字段

Field getDeclaredField("name");

获取指定字段

Constructor<Object> [] getConstructors()

获取全部 Constructor 对象

Constructor<Object> getConstructor(Class class)

获取某一个Constructor,需要参数列表,参数代表构造方法的参数类型

Method的常用方法

method.invoke(param1,param2 ...)

param1表示执行哪个对象的方法,剩下的参数是执行方法时需要传入的参数
私有方法的执行,必须在调用invoke之前加上一句method.setAccessible(true);

Annotation getAnnotation(Class class)

获取指定名称的注解

Annotation [] getDeclaredAnnotations()

返回所有声明的注解

Field 的常用方法

field.get(object)

获取指定对象的指定字段的值

field.set(object, value);

设置指定对象的指定对象Field值
如果字段是私有的,不管是读值还是写值,都必须先调用setAccessible(true)方法

Constructor的常用方法

newInstance/newInstance(Class ...)

调用构造器的newInstance() 方法创建对象

反射与泛型

定义一个泛型类:

public class DAO<T> {
    private  Class<T> tClass=null;
    //根据id获取一个对象
    T get(){
        Type type=this.getClass().getGenericSuperclass();
        if(type instanceof ParameterizedType){
            ParameterizedType parameterizedType = (ParameterizedType) type;
            Type [] arges = parameterizedType.getActualTypeArguments();
            Type arg = arges[0];
            if (arg instanceof  Class){
            tClass = (Class<T>) arg;
            }
                try {
                if (tClass!=null){
                    Constructor<T> constructor=tClass.getConstructor(String.class,int.class);
                    return  constructor.newInstance("abc",250);
                }
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
         return null;
    }

}

再定义一个子类,继承这个泛型类:

public class PersonDAO extends DAO<Person> {

}

注意子类不许指定泛型的具体类型,泛型不能从调用处指定。

People类:

public class People {
    public String name;
    public int age;

    public People() {
    }

    public People(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

使用时,用PeopleDao初始化

   PeopleDao dao=new PeopleDao();
                People people= dao.get();

相关文章

  • 博客地址

    java注解-01、java注解-02、Git面试资源java反射-01、java反射-02、java反射-03为...

  • Java反射机制入门

    Java反射机制入门 一、什么是反射 JAVA反射机制(The JAVA reflection mechanism...

  • Java基础之反射

    Java基础之—反射(非常重要)Java中反射机制详解Java进阶之reflection(反射机制)——反射概念与...

  • 反射之一

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • 反射之二

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • Java基础之反射

    Java基础之反射 反射基本介绍 反射的使用通过反射调用属性和方法通过反射获取配置文件 反射基本介绍 Java反射...

  • Java 反射机制

    Java 反射机制 什么是反射 Java 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”。 ...

  • 一探究竟:Java反射效率低的原因到底在哪?

    预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低...

  • 面试官说:大家都说 Java 反射效率低,你知道原因在哪里么

    预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低...

  • Java面试题之JavaSE高级

    一、Java中的反射 1.说说你对Java中反射的理解 java中的反射首先是能够获取到Java...

网友评论

      本文标题:Java 反射

      本文链接:https://www.haomeiwen.com/subject/ndvdyqtx.html