您的位置:首页 > 编程语言 > Java开发

Java Reflection深入理解Class对象

2018-02-22 18:18 363 查看
使用Java反射机制可以在运行时期检查Java类的信息,检查Java类的信息往往是你在使用Java反射机制的时候所做的第一件事情,
通过获取类的信息你可以获取以下相关的内容:

.Class对象
.类名

.修饰符
.包信息

.父类
.实现的接口

.构造器
.方法

.变量
.注解

除了上述这些内容,还有很多的信息你可以通过反射机制获得。

Class对象
在你想检查一个类的信息之前,你首先需要获取类的Class对象。Java中的所有类型包括基本类型(int, long, float等等),

即使是数组都有与之关联的Class类的对象。有如下三种方式获取Class对象:

以下知识点实例涉及共有代码:

MyObject.java

package com.lanhuigu.reflect.cls;

import com.lanhuigu.reflect.annotations.MyAnnotation;

@MyAnnotation(name = "testAnnoation", value = "hello world")
public class MyObject {
/** 公有变量*/
public static final String testFieldName = "test-field-name";
/** 私有变量 */
private String username;
private int age;

public MyObject () {
username = "Test1-Class";
age = 27;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

}MyAnnotation.java
package com.lanhuigu.reflect.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
public String name();
public String value();
}
(1) 如果能够new某个对象,可以通过如下方式获取Class对象:
MyObject myObject = new MyObject();

Class myObjectClass = myObject.getClass();
eg:

package com.lanhuigu.reflect.cls;

import java.lang.reflect.Method;

/**
* 如果能够new某个对象,可以通过如下方式获取Class对象:
* MyObject myObject = new MyObject();
* Class myObjectClass = myObject.getClass();
*/
public class Test1 {
public static void main(String[] args) {
/** 获取Class对象 */
MyObject myObject = new MyObject();
Class myObjectClass = myObject.getClass();

/** 获取Method */
Method[] methods = myObjectClass.getMethods();

/** 打印Method名称 */
for (Method myMethod : methods) {
System.out.println("MyObject中的方法名:" + myMethod.getName());
}
}
}

(2) 如果你在编译期知道一个类的名字的话,那么你可以使用如下的方式获取一个类的Class对象:

Class myObjectClass = MyObject.class;

eg:
package com.lanhuigu.reflect.cls;

import java.lang.reflect.Method;

/**
* 如果你在编译期知道一个类的名字的话,那么你可以使用如下的方式获取一个类的Class对象:
* Class myObjectClass = MyObject.class;
*/
public class Test2 {
public static void main(String[] args) {
/** 获取Class对象 */
Class myObjectClass = MyObject.class;

/** 获取Method */
Method[] methods = myObjectClass.getMethods();

/** 打印Method名称 */
for (Method myMethod : methods) {
System.out.println("MyObject中的方法名:" + myMethod.getName());
}
}
}

(3) 如果你在编译期不知道类的名字,但是你可以在运行期获得到类名的字符串,那么你则可以这么做来获取Class对象

String className = ... ; //在运行期获取的类名字符串

Class class = Class.forName(className);
在使用Class.forName()方法时,你必须提供一个类的全名,这个全名包括类所在的包的名字。

例如MyObject类位于com.lanhuigu.reflect.cls包,那么他的全名就是com.lanhuigu.reflect.cls.MyObject。
如果在调用Class.forName()方法时,没有在编译路径下(classpath)找到对应的类,那么将会抛出ClassNotFoundException。

eg:

package com.lanhuigu.reflect.cls;

import java.lang.reflect.Method;

/**
* 如果你在编译期不知道类的名字,但是你可以在运行期获得到类名的字符串,那么你则可以这么做来获取Class对象:
* String className = ... ; //在运行期获取的类名字符串
* Class class = Class.forName(className);
*
* 在使用Class.forName()方法时,你必须提供一个类的全名,这个全名包括类所在的包的名字。
* 例如MyObject类位于com.lanhuigu.reflect.cls包,那么他的全名就是com.lanhuigu.reflect.cls.MyObject。
* 如果在调用Class.forName()方法时,没有在编译路径下(classpath)找到对应的类,那么将会抛出ClassNotFoundException。
*/
public class Test3 {
public static void main(String[] args) {
try {
/** 获取Class对象 */
String className = "com.lanhuigu.reflect.cls.MyObject";
Class  myObjectClass = Class.forName(className);

/** 获取Method */
Method[] methods = myObjectClass.getMethods();

/** 打印Method名称 */
for (Method myMethod : methods) {
System.out.println("MyObject中的方法名:" + myMethod.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

类名
你可以从Class对象中获取两个版本的类名。

通过getName()方法返回类的全限定类名(包含包名):
Class myClass = ... //获取Class对象,参考上面的Class对象获取的三种方法

String className = myClass.getName();

eg:

package com.lanhuigu.reflect.classname;

import com.lanhuigu.reflect.cls.MyObject;

/**
* 通过getName()方法返回类的全限定类名(包含包名):
* Class myClass = ... //获取Class对象,参考上面的Class对象获取的三种方法
* String className = myClass.getName();
*/
public class Test1 {
public static void main(String[] args) {
Class myClass = MyObject.class;
String className = myClass.getName();
System.out.println("className:" + className);
}
}


如果你仅仅只是想获取类的名字(不包含包名),那么你可以使用getSimpleName()方法:
Class myClass = ... //获取Class对象,参考上面的Class对象获取的三种方法

String simpleClassName = myClass.getSimpleName();

eg:

package com.lanhuigu.reflect.classname;

import com.lanhuigu.reflect.cls.MyObject;

/**
* 如果你仅仅只是想获取类的名字(不包含包名),那么你可以使用getSimpleName()方法:
* Class myClass = ... //获取Class对象,参考上面的Class对象获取的三种方法
* String simpleClassName = myClass.getSimpleName();
*/
public class Test2 {
public static void main(String[] args) {
Class myClass = MyObject.class;
String simpleClassName = myClass.getSimpleName();
System.out.println("simpleClassName:" + simpleClassName);
}
}

修饰符
可以通过Class对象来访问一个类的修饰符,即public,private,static等等的关键字,你可以使用如下方法来获取类的修饰符:

Class  myClass = ... //获取Class对象,参考上面的Class对象获取的三种方法
int modifiers = myClass.getModifiers();

修饰符都被包装成一个int类型的数字,这样每个修饰符都是一个位标识(flag bit),这个位标识可以设置和清除修饰符的类型。
可以使用java.lang.reflect.Modifier类中的方法来检查修饰符的类型:

Modifier.isAbstract(int modifiers);
Modifier.isFinal(int modifiers);

Modifier.isInterface(int modifiers);
Modifier.isNative(int modifiers);

Modifier.isPrivate(int modifiers);
Modifier.isProtected(int modifiers);

Modifier.isPublic(int modifiers);
Modifier.isStatic(int modifiers);

Modifier.isStrict(int modifiers);
Modifier.isSynchronized(int modifiers);

Modifier.isTransient(int modifiers);
Modifier.isVolatile(int modifiers);

eg:
package com.lanhuigu.reflect.modifier;

import java.lang.reflect.Modifier;

public class Test1 {
public static void main(String[] args) {
try {
Class myClass = Class.forName("com.lanhuigu.reflect.cls.MyObject");
int modifiers = myClass.getModifiers();
System.out.println("isPrivate:" + Modifier.isPrivate(modifiers));
System.out.println("isPublic:" + Modifier.isPublic(modifiers));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

包信息
可以使用Class对象通过如下的方式获取包信息:

Class  myClass = ... //获取Class对象,参考上面的Class对象获取的三种方法
Package package = myClass.getPackage();

通过Package对象你可以获取包的相关信息,比如包名,你也可以通过Manifest文件访问位于编译路径下jar包的指定信息,
比如你可以在Manifest文件中指定包的版本编号。

eg:
package com.lanhuigu.reflect.packages;

import com.lanhuigu.reflect.cls.MyObject;

public class Test1 {
public static void main(String[] args) {
Class myClass = MyObject.class;
Package packages = myClass.getPackage();
System.out.println("packages.name:" + packages.getName());
}
}

父类

通过Class对象你可以访问类的父类,如下例:

Class  myClass = ... //获取Class对象,参考上面的Class对象获取的三种方法

Class superclass = myClass.getSuperclass();
可以看到superclass对象其实就是一个Class类的实例,所以你可以继续在这个对象上进行反射操作。

eg:

package com.lanhuigu.reflect.parent;

import com.lanhuigu.reflect.cls.MyObject;

public class Test1 {
public static void main(String[] args) {
Class myClass = MyObject.class;
Class superClass = myClass.getSuperclass();
System.out.println("superClass name:" + superClass.getName());
}
}

实现的接口
可以通过如下方式获取指定类所实现的接口集合:

Class  myClass = ... //获取Class对象,参考上面的Class对象获取的三种方法
Class[] interfaces = myClass.getInterfaces();

由于一个类可以实现多个接口,因此getInterfaces();方法返回一个Class数组,在Java中接口同样有对应的Class对象。

注意:
getInterfaces()方法仅仅只返回当前类所实现的接口。当前类的父类如果实现了接口,

这些接口是不会在返回的Class集合中的,尽管实际上当前类其实已经实现了父类接口。

eg:

package com.lanhuigu.reflect.interfaces;

import com.lanhuigu.reflect.cls.MyObject;

public class Test1 {
public static void main(String[] args) {
Class myClass = MyObject.class;
Class[] interfaces = myClass.getInterfaces();
for (Class c : interfaces) {
System.out.println("interfaces name:" + c.getName());
}
}
}

构造器
你可以通过如下方式访问一个类的构造方法:

Constructor[] constructors = myClass.getConstructors();
eg:

package com.lanhuigu.reflect.constructors;

import com.lanhuigu.reflect.cls.MyObject;

import java.lang.reflect.Constructor;

public class Test1 {
public static void main(String[] args) {
Class myClass = MyObject.class;
Constructor[] constructors = myClass.getConstructors();
for (Constructor constructor : constructors) {
System.out.println("constructor name:" + constructor.getName());
}
}
}

方法
你可以通过如下方式访问一个类的所有方法:

Class myClass = ... //获取Class对象,参考上面的Class对象获取的三种方法
Method[] method = myClass.getMethods();

eg:
package com.lanhuigu.reflect.methods;

import com.lanhuigu.reflect.cls.MyObject;

import java.lang.reflect.Method;

public class Test1 {
public static void main(String[] args) {
Class myClass = MyObject.class;
Method[] methods = myClass.getMethods();
for (Method method : methods) {
System.out.println("method name:" + method.getName());
}
}
}

变量
你可以通过如下方式访问一个类的成员变量:

Class myClass = ... //获取Class对象,参考上面的Class对象获取的三种方法
Field[] method = myClass.getFields();

eg:
package com.lanhuigu.reflect.fields;

import com.lanhuigu.reflect.cls.MyObject;

import java.lang.reflect.Field;

public class Test1 {
public static void main(String[] args) {
Class myClass = MyObject.class;
/** 返回公有变量集合 */
Field[] fields = myClass.getFields();
for (Field field : fields) {
System.out.println("field name:" + field.getName());
}
}
}

注解
你可以通过如下方式访问一个类的注解:

Class myClass = ... //获取Class对象,参考上面的Class对象获取的三种方法
Annotation[] annotations = myClass.getAnnotations();

eg:

package com.lanhuigu.reflect.annotations;

import com.lanhuigu.reflect.cls.MyObject;

import java.lang.annotation.Annotation;

public class Test1 {
public static void main(String[] args) {
Class myClass = MyObject.class;
Annotation[] annotations = myClass.getAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof MyAnnotation) {
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("myAnnotation name:" + myAnnotation.name());
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: