Class类的方法:
获取构造函数
getConstructor
方法,反射返回一个Constructor类对象,包括子类的构造器
getDeclaredConstructor
方法,也是反射返回一个Constructor类对象,不包括继承的子类构造器
//返回 Constructor 对象数组
Constructor<?>[] getDeclaredConstructors()
Constructor<?>[] getConstructors()
// 返回指定参数的 Constructor 对象
Constructor<T> getConstructor(Class<?>... parameterTypes)
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
获取成员变量
getFiled
方法,反射返回一个Field类对象,仅包括public声明的字段属性。
getDeclaredFiled
方法,反射返回一个Field类对象,包括所有声明的字段属性
// 返回 Field 对象数组
Field[] getFields()
Field[] getDeclaredFields()
// 返回指定的 Field 对象
Field getField(String name)
Field getDeclaredField(String name)
获取成员方法
getMethod
方法,反射返回的是一个Method类对象,返回的是公共成员方法
getDeclaredMethod
方法,反射返回一个Method类对象,返回的是所有声明的成员方法。
// 返回 Method 对象数组
Method[] getMethods()
Method[] getDeclaredMethods()
/ 返回指定的 Method 对象
Method getMethod(String name, Class<?>... parameterTypes)
Method getDeclaredMethod(String name, Class<?>... parameterTypes)
获取注解方法
// 返回指定 Annotation 对象
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
// 返回 Annotation 对象数组
Annotation[] getDeclaredAnnotations()
public Annotation[] getAnnotations ()
创建对象的方法
forName(String ClassName)
静态方法,获取一个类的Class对象,在类加载器的加载阶段就获取到了。
isInstance
方法,是一个Native方法,与instanceof
关键字产生的效果是一样的。
newInstance
方法,创建指定类型T的一个实例,主要是反射出来其构造器,再调用构造器创建新实例对象。
cast
强制类型转换方法
// 创建此 Class 对象所表示的类的一个新实例
T newInstance()
返回字符串(String)的方法
// 返回底层类的规范化名称
String getCanonicalName()
// 返回全限定名(全限定名:包名.类名)
String getName()
// 返回源代码中给出的底层类的简称
String getSimpleName()
返回 boolean 的方法
// 判断是不是局部类,也就是方法里面的类
boolean isLocalClass()
// 判断是不是成员内部类,也就是一个类里面定义的类
boolean isMemberClass()
// 判断当前类是不是匿名类,匿名类一般用于实例化接口
boolean isAnonymousClass()
// 如果指定类型的注释存在于此元素上
isAnnotationPresent (Class<? extends Annotation> annotationClass)
// 判断当前Class对象是否是注释类型
boolean isAnnotation() ;
// 判断该类是否是枚举类
boolean isEnum()
// 判断指定的 Object 是否 Class 的实例
boolean isInstance(Object obj)
// 判断指定的 Class 对象是否表示一个接口类型
boolean isInterface()
// 判断指定的 Class 对象是否表示一个基本类型
boolean isPrimitive()
获取 Class 的修饰符
//返回此类或接口以整数编码的 Java 语言修饰符。
public int getModifiers();
我们可以使用 Class.getModifiers() 获得调用类的修饰符的二进制值,然后使
用 Modifier.toString(int modifiers) 将获取到的二进制值转换为字符串。
如何得到Class的对象呢?有三种方法可以的获取:
1、调用Object类的getClass()方法来得到Class对象,这也是最常见的产生Class对象的方法。例如:
MyObject x;
Class c1 = x.getClass();
2、使用Class类的中静态forName()方法获得与字符串对应的Class对象。例如:
Class c2=Class.forName("MyObject"),Employee必须是接口或者类的名字。
3、获取Class类型对象的第三个方法非常简单。如果T是一个Java类型,那么T.class就代表了匹配的类对象。例如
Class cl1 = Manager.class;
Class cl2 = int.class;
Class cl3 = Double[].class;
注意:Class对象实际上描述的只是类型,而这类型未必是类或者接口。例如上面的int.class是一个Class类型的对象。由于历史原因,数组类型的getName方法会返回奇怪的名字。
Class的一些使用技巧
1、forName和newInstance结合起来使用,可以根据存储在字符串中的类名创建对象。例如
Class<?> clazz = Class.forName("类名");
Object obj = clazz.newInstance();
2、虚拟机为每种类型管理一个独一无二的Class对象。因此可以使用==操作符来比较类对象。例如:
if(e.getClass() == Employee.class){}
package xq.com.cn;
/**
* Created by lenovo on 2017/7/4.
*/
public class ClassDemos {
/**
* 构造函数
*/
public ClassDemos() {
System.out.println("构造方法:classDemo!");
}
public static void main(String[] args) throws Exception {
/**
* Class.forName(String):要求JVM查找并加载String指定的类
* 返回String字符串指定的类
*/
Class clazz = Class.forName("xq.com.cn.ClassDemos");
System.out.println("forName==" + clazz);//class xq.com.cn.ClassDemos
/**
* clazz.newInstance()
* 返回的类所代表的一个实例和new ClassDemo()效果是一样的。
*/
ClassDemos classDemo = (ClassDemos) clazz.newInstance();
System.out.println("newInstance==" + classDemo);//xq.com.cn.ClassDemos@1540e19d
}
}
打印结果:
forName==class xq.com.cn.ClassDemos
构造方法:classDemo!
newInstance==xq.com.cn.ClassDemos@1540e19d
可见:
Class.forName(“”)返回的是类
Class.forName(“”).newInstance()返回的是类的对象
// 以下为一样的效果。
A a = (A)Class.forName("pacage.A").newInstance();
A a = new A();
从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。但是使用newInstance()方法的时候,就必须保证:1、这个 类已经加载;2、这个类已经连接了。而完成上面两个步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,即加载 java API的那个加载器。
newInstance()和new的区别:
首先,newInstance( )是一个方法,而new是一个关键字,
其次,Class下的newInstance()的使用有局限,因为它生成对象只能调用无参的构造函数,而使用 new关键字生成对象没有这个限制。
newInstance()实际上是把new这个方式分解为两步,即首先调用Class加载方法加载某个类,然后实例化。 这样分步的好处是显而易见的。我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了一种降耦的手段。
newInstance: 弱类型。低效率。只能调用无参构造。
new: 强类型。相对高效。能调用任何public构造。
forName()方法
这个方法总是返回要加载的类的Class类的实例
1、forName(String className)单参数时, initialize=true
a.总是使用当前类装载器(也就是装载执行forName()请求的类 的类装载器)
b.总是初始化这个被装载的类(当然也包括:装载、连接、初始化)
2、forName(String className, boolean initialize, ClassLoader loader)
a.loader指定装载参数类所用的类装载器,如果null则用bootstrp装载器。
b.initialize=true时,肯定连接,而且初始化了;
c.false时,绝对不会初始化,但是可能被连接了,但是这里有个例外,如果在调用这个forName()前,已经被初始化了,那么返回的类型也肯定是被初始化的(当然,这里也暗含着:被同一个loader所装载的,而且这个类被初始化了)
关于用户自定义的类装载器的loadClass()方法
1、loadClass(String name)单参数时, resolve=false
a.如果这个类已经被这个类装载器所装载,那么,返回这个已经被装载的类型的Class的实例,否则,就用这个自定义的类装载器来装载这个class,这时不知道是否被连接。绝对不会被初始化
b.这时唯一可以保证的是,这个类被装载了。但是不知道这个类是不是被连接和初始化了
2、loadClass(String name, boolean resolve)
a.resolve=true时,则保证已经装载,而且已经连接了。resolve=falses时,则仅仅是去装载这个类,不关心是否连接了,所以此时可能被连接了,也可能没有被连接
参考: 关于Class.forName(className).newInstance()介绍
反射的使用:
写一个简单的类:
package xq.com.cn;
/**
* Created by lenovo on 2017/7/4.
*/
public class Simple {
private void displayMessage(String strMsg) {//注意方法私有Private
System.out.println("message is:" + strMsg);
}
}
测试类:
import xq.com.cn.Simple;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Created by lenovo on 2017/7/4.
*/
public class Test {
public static void main(String[] args) {
/*获取类的方法一: 通过类直接获取*/
Class<Simple> simpleClass1 = Simple.class;
System.out.println("class111==" + simpleClass1);//直接获取类
/*获取类的方法二: 通过对象获取*/
Simple simple = new Simple();
Class<? extends Simple> aClass = simple.getClass();//通过对象获取类
System.out.println("class222===" + aClass);
try {
/*获取类的方法三: 通过反射获取*/
Class simpleClass = Class.forName("xq.com.cn.Simple");//通过反射获取类
System.out.println("class333===" + simpleClass);
Object simpelObject = simpleClass.newInstance();//获取类的实例
System.out.println("object===" + simpelObject);
Class[] args1 = new Class[1];
args1[0] = String.class;
//获取类的方法,参数为:方法名,参数类型
Method simpleMethod = simpleClass.getDeclaredMethod("displayMessage", args1);
//类中的方法为private,故必须进行此操作,
//如果变量为private则变量需要调用此方法才可访问
simpleMethod.setAccessible(true);
String[] argments = new String[1];
argments[0] = "Hello,world";
//方法的调用,参数为:对象,参数
simpleMethod.invoke(simpelObject, argments);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
打印结果
class111==class xq.com.cn.Simple
class222===class xq.com.cn.Simple
class333===class xq.com.cn.Simple
object===xq.com.cn.Simple@1540e19d
message is:Hello,world
getDeclaredMethod与getMethod 区别:
getDeclaredMethod() 获取的是类自身声明的所有方法,包含public、protected和private方法。
getMethod () 获取的是类的所有共有方法,这就包括自身的所有public方法,和从基类继承的、从接口实现的所有public方法。
public Method getDeclaredMethod(String name, Class<?>... parameterTypes){
...
}
java.lang.Class.getDeclaredMethod()方法返回一个Method对象,它反映此Class对象所表示的类或接口的指定已声明方法。
name 参数是一个字符串,指定所需的方法的简单名称,即方法名。
parameterTypes 参数是一个数组的Class对象识别方法的形参类型,在声明的顺序。
参考:
java.lang.Class.getDeclaredMethod()方法详解