java.lang.reflect(一)

  要梳理这个包,就必须要整理一下反射了。为了方便描述,我们假定已经写好了一个普通类,com.

反射API

接口
AnnotatedElement
GenericArrayType
GenericDeclaration
InvocationHandler
Member
ParameterizedType
Type
TypeVariable
WildcardType
类
AccessibleObject  (代表访问检查的能力)
Array  (代表数组)
Constructor  (代表构造方法)
Field  (代表类的成员变量,类属性)
Method   (代表类的方法)
Modifier
Proxy
ReflectPermission
异常
InvocationTargetException
MalformedParameterizedTypeException
UndeclaredThrowableException
错误
GenericSignatureFormatError

对于反射,除了上述java.lang.reflect包下的类外,还有一个非常重要的 java.lang.Class<T>。上面标黑的就是反射里最最常用的类了。下面先从Class说起

1.java.lang.Class

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。

Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

Class 的类关系图如下:其中,除了Serializable以外,其他三个接口都是java.lang.reflect包下的接口

获取一个类的Class对象一般有2种方法:

Class userClass=User.class;  //类名.class
Class<?> userClass = Class.forName("com.study.reflect.User");  //这种方法必须参数必须使用类全名

Class.forName还有一个重载方法是可以指定ClassLoader的。比如上面的写法相当于

Class<?> userClass = Class.forName("com.study.reflect.User",true, ClassLoader.getSystemClassLoader());

基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void不能够使用forName获取,只能用.class获取,比如:int.class,void.class

对于数组类型,直接写int[].class,Object[].class

Class c=int[].class;
c=Object[].class;

2.java.lang.reflect.Constructor

一般情况下,我们通过new Object()来生成一个类的实例,但有时我们没法直接new,只能通过反射动态生成。

通过反射生成对象有下面三种方法:

//方法一Class<?> userClass2 = Class.forName("com.study.reflect.User");
User user = (User)userClass2.newInstance();//方法二
User user2 = (User)userClass2.getConstructor().newInstance();//方法三
User user3 = (User)userClass2.getConstructor(String.class).newInstance("张三");

上面的userClass2.getConstructor() 就是在获取User的构造方法。可以有参数,也可以无参数。Class也可以直接获取一个类的所有public构造方法

public Constructor<?>[] getConstructors() throws SecurityException

再次强调一下,Class获取的构造方法全是public的。而且一般我们也都是通过Class方法来获取Constructor对象的。Constructor类本身没有public构造方法。

当然,也有获取非public修饰的构造方法的办法,可以使用

//获取某个构造方法Class.getDeclaredConstructor(Class<?>... parameterTypes);比如:User.class.getDeclaredConstructor(String.class);
//获取所有构造方法
Class.getDeclaredConstructors();比如:User.class.getDeclaredConstructors()

Constructor的类继承关系图如下:

Constructor常用的方法主要是下面几类:

1.获取构造方法上的注解,主要有三个方法。

public Annotation[] getAnnotations();
public Annotation[] getDeclaredAnnotations();
public <T extends Annotation> T getAnnotation(Class<T> annotationClass);

前两个都是获取方法上的所有注解。而且从源码看起来效果应该是完全一样的,下面是getAnnotations的源码:

    /**
     * @since 1.5
     */
    public Annotation[] getAnnotations() {
        return getDeclaredAnnotations();
    }

2.获取此构造方法对应的类。(就是这究竟是哪个类的构造方法)

public Class<T> getDeclaringClass();
Class<?> userClass2 = Class.forName("com.study.reflect.User");
Constructor<?> constructor = userClass2.getConstructor();
Class<?> declaringClass = constructor.getDeclaringClass();
System.out.println(declaringClass.getName());  //最后输出:com.study.reflect.User

如果要直接获取类名(String),可以调用getName方法

public String getName();

查看源码,实际上调用的就是上面的方法:

    /**
     * Returns the name of this constructor, as a string.  This is
     * the binary name of the constructor‘s declaring class.
     */
    public String getName() {
        return getDeclaringClass().getName();
    }

测试一下:

System.out.println(constructor.getName());  //最后输出:com.study.reflect.User

3.获取此构造方法抛出的异常类型

Class<?>[] exceptionTypes = constructor.getExceptionTypes();
Type[] genericExceptionTypes = constructor.getGenericExceptionTypes(); //Type是Class实现的一个接口,个人觉得和上面方法主要是返回类型不同,连Class对象都是同一个

4.获取参数的信息

Constructor<?> constructor2 = userClass2.getConstructor(String.class,int.class);
Type[] genericParameterTypes = constructor2.getGenericParameterTypes();
Class<?>[] parameterTypes = constructor2.getParameterTypes(); //和上面相比,只是返回类型不同,对象都是同一个。Annotation[][] parameterAnnotations = constructor2.getParameterAnnotations(); //需要注意的是这个获取到的是一个二维数组。因为每个参数上都可能都多个注解。

5.获取该方法的修饰符

int modifiers = constructor2.getModifiers();

该方法返回的并不是一个枚举,而是一个整数。这也许和java的历史版本有关。至于整数和修饰符的对应关系,我们后面说。

6.获取泛型

TypeVariable<? extends Constructor<?>>[] typeParameters = constructor2.getTypeParameters();

7.其他

boolean synthetic = constructor2.isSynthetic(); //是否是复合构造方法
boolean varArgs = constructor2.isVarArgs();   //是否有可变数量的参数,就是有没有参数是数组类型constructor.toGenericString();constructor.toString();  //这两种toString返回的基本差不多

比如构造方法是:

public User(String name,int ... args){
        this.age=args[0];
}
public User(String name,int[] args){
        this.age=args[0];
}

由于可变参数的本质也是数组,所以一个类中不可能同时有上面2个方法

如上两种情况,其中第二个参数本质都是数组,但是第一种可以任意赋值多个,则isVarArgs() 的结果就是true。但是第二种,则会返回false。重点还是参数个数是否可变。

Constructor<?> constructor3 = userClass2.getConstructor(String.class,int[].class); //任意参数个数本质也是数组,也是使用int[].class//如果是非public方法,要使用getDeclaredConstructor(Class<?>... parameterTypes)
boolean varArgs = constructor3.isVarArgs(); //针对int ... args的这种返回true, 如果参数是int[] args 则会返回false

isSynthetic好像很复杂,先留个坑,后面再填。

8.创建对象,一般用的最多的方法。

newInstance(Object... initargs)

就是正常方法的调用传参,比如用上面的构造商法生成一个User

User user = (User)constructor2.newInstance("name", new int[]{1, 2, 3});

3.java.lang.Field

先说一下怎么获取Field对象。这个类和Constructor一样,没有public构造方法。一般通过Class的如下方法获取

Class.getFields()

Class.getField(String)

Class.getDeclaredFields()

Class.getDeclaredField(String)

上述没有Declared就是获取public权限的,有Declared就是可以获取任意权限。

下面针对功能简单说一下Field方法的分类

1.取值get,赋值set

Field里面有一大堆的get,set方法,主要是针对各种Field可能是不同的类型而定的方法。简单来说,get就是获取某个对象当前属性的value,所以get方法的参数一般都是Object,代表一个实例对象。set是为某个实例对象把当前这个Field重新设置一个value,所以参数一般都有2个,第一个代表实例对象,第二个代表value.

方法很多,不一一列举。

2.获取该属性上的注解,或者判断是否有某个注解

public Annotation[] getAnnotations();
public Annotation[] getDeclaredAnnotations();

3.获取修饰符

getModifiers()

4.获取或修改权限,允许赋值

所有的类都基于jdk1.6

原文地址:https://www.cnblogs.com/andong2015/p/10627243.html

时间: 2024-10-17 15:26:12

java.lang.reflect(一)的相关文章

java.lang.reflect操作对象属性(域)的值

import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /*2015-10-28*/ public class RefactorDemo { /** * @param args * @throws NoSuchFieldException * @throws SecurityException * @throws Ill

自己写一个java.lang.reflect.Proxy代理的实现

前言 Java设计模式9:代理模式一文中,讲到了动态代理,动态代理里面用到了一个类就是java.lang.reflect.Proxy,这个类是根据代理内容为传入的接口生成代理用的.本文就自己写一个Proxy类出来,功能和java.lang.reflect.Proxy一样,传入接口.代理内容,生成代理. 抛砖引玉吧,个人觉得自己写一些JDK里面的那些类挺好的,写一遍和看一遍真的是两个不同的概念,写一遍既加深了对于这些类的理解.提升了自己的写代码水平,也可以在写完之后对比一下自己的实现有哪些写得不好

利用java.lang.reflect.Constructor动态实例化对象

1 public class Student { 2     private String name; 3     private Integer age; 4     private Student(String name,Integer age){ 5         this.name=name; 6         this.age=age; 7     } 8     public String getName() { 9         return name;10     }11 

java.lang.reflect.Method

java.lang.reflect.Method 一.Method类是什么 Method是一个类,位于java.lang.reflect包下. 在Java反射中 Method类描述的是 类的方法信息,通俗来讲 有一个类如下: 1 package com.testReflect; 2 3 public class MethodDemo { 4 private int num = 2; 5 private String str = "xixi"; 6 7 public int addRes

moon 反射机制---java.lang.reflect包

java反射机制:在运行状态中,对于一个已经加载到JVM的java对象/类 在程序中实现访问.检查.修改.描述java对象本身的信息(构造方法.方法.成员变量.类本身的信息) 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. C++,Java,C#不是动态语言.但是JAVA有着一个非常突出的动态相关机制:Reflection, 反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接. 二,反射机制的作用:

Java反射API研究(2)——java.lang.reflect详细内容与关系

对于最新的java1.8而言,reflect中接口的结构是这样的: java.lang.reflect.AnnotatedElement java.lang.reflect.AnnotatedType java.lang.reflect.AnnotatedArrayType java.lang.reflect.AnnotatedParameterizedType java.lang.reflect.AnnotatedTypeVariable java.lang.reflect.Annotated

java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType

DAO层有很多操作其实可以用范式加反射来实现的,所以我就开始构想我的万金油BaseDAO了. BaseHibernateDaoAdvance.java public class BaseHibernateDaoAdvance<T extends ModifyInfoEntity, PK extends Serializable, DTO extends BaseDto> extends HibernateDaoSupport implements BaseDaoAdvance<T, PK

严重: Dispatcher initialization failed java.lang.RuntimeException: java.lang.reflect.InvocationT

严重: Dispatcher initialization failed java.lang.RuntimeException: java.lang.reflect.InvocationT (2012-09-23 17:20:13) 转载▼ 标签: struts中jar包 dispatcherinitializa 分类: Struts2 错误提示:严重: Dispatcher initialization failed java.lang.RuntimeException: java.lang.

java.lang.reflect.Constructor

java.lang.reflect.Constructor 一.Constructor类是什么 Constructor是一个类,位于java.lang.reflect包下. 在Java反射中 Constructor类描述的是 类的构造方法信息,通俗来讲 有一个类如下: 1 package com.testReflect; 2 public class ConstructorDemo { 3 private int num; 4 private String str; 5 6 public Con

Hadoop中RPC协议小例子报错java.lang.reflect.UndeclaredThrowableException解决方法

最近在学习传智播客吴超老师的Hadoop视频,里面他在讲解RPC通信原理的过程中给了一个RPC的小例子,但是自己编写的过程中遇到一个小错误,整理如下: log4j:WARN No appenders could be found for logger (org.apache.hadoop.metrics2.lib.MutableMetricsFactory).log4j:WARN Please initialize the log4j system properly.log4j:WARN See