java基础-反射2(反射,Class对象的使用,类型信息的获取)
通过反射的第一篇文章java基础-反射1(类型信息,Class对象简介,Class对象初始化)我们可以知道java通过class对象来表示运行时类型信息,并且了解了RTTI,下面我们来学习Class对象的使用。
Class对象,反射
Class对象表示了运行时类型信息,但是如果要获取这些信息我们就要通过反射来获取这些运行时类型信息。
首先我们来先创建一个类,然后通过Class对象获取类的基本信息
/**
* Created by IntelliJ IDEA.
* User:hubin
* Description:
* Date:2017/12/4
* Time:13:25
*/
@Deprecated
@Service
public class Person extends PersronParent implements PersonInterfance {
public String name;
public double weight;
protected double height;
private Integer age;
public Person(){
System.out.println("public Person()");
}
protected Person(String name){
System.out.println("protected Person()");
}
public void show() throws Exception{
System.out.println("show()");
}
protected void disPlay(){
System.out.println("disPlay()");
}
@Deprecated
private int testParamter(String paramter1,String paramter2) throws NullPointerException{
return 1;
}
@Deprecated
public int testPublicParamter(String paramter1,String paramter2) throws NullPointerException{
return 1;
}
@Override
public void parentSay(){
super.parentSay();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
通过Class对象和反射获取类的变量信息
通过Class对象来获取类的变量信息可以通过这个java.lang.reflect.Field;类表示类的变量信息,Field类表示类的变量。
Class对象有一系列的方法来获取类的Field,常见的如下:
- 获取类申明的为public作用域的变量 getFields();
- 获取类申明的所有变量 getDeclaredFields();
- 通过变量名称,获取类申明的为public作用域的变量 getField();
- 通过变量名称,获取类申明的(public ,protect,private,缺省)变量getDeclaredField();
获取类的Field后可以通过Field的一些方法获取变量的信息如下:
- 获取变量的名称:getName();
- 获取变量的作用域:getModifiers();
- 获取变量的类型:getType();
下面通过获取person类的变量信息来了解一下:
/**
* Created by IntelliJ IDEA.
* User:hubin
* Description:
* Date:2017/12/4
* Time:13:32
*/
public class TestField {
public static void main(String agrs[]) {
Class<Person> personClass = Person.class;
/**
* 获取类中作用域申明为public 的变量
*/
System.out.println();
System.out.println("获取类所有申明为public的变量:");
Field[] fields = personClass.getFields();
for (Field field : fields) {
printFieldInfo(field);
}
/**
* 获取类中所有申明的变量
*/
System.out.println();
System.out.println("获取类所有申明的变量(public ,protect,private,缺省):");
Field[] declaredFields = personClass.getDeclaredFields();
for (Field field : declaredFields) {
printFieldInfo(field);
}
try {
/**
* 获取某个申明为public的变量
*/
System.out.println();
System.out.println("获取某个申明为public的变量:");
Field publicField = personClass.getField("name");
printFieldInfo(publicField);
/**
* 获取某个申明的变量(public ,protect,private,缺省)
*/
System.out.println();
System.out.println("获取某个申明的变量:(public ,protect,private,缺省):");
Field protectField = personClass.getDeclaredField("weight");
printFieldInfo(protectField);
Field privateField = personClass.getDeclaredField("age");
printFieldInfo(privateField);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
/**
* 打印类的变量信息
* @param field
*/
public static void printFieldInfo(Field field) {
System.out.print("作用域 :" + Modifier.toString(field.getModifiers()));
System.out.print(" 名称 :" + field.getName());
System.out.println(" 类型 :" + field.getType());
}
}
运行结果如下图:
通过CLass对象和反射获取类的方法信息
通过CLass对象也可以获取类的方法信息,类的方法信息通过java.lang.reflect.Method这个类表示,Class对象有一系列的方法获取Method对象,然后通过Method对象可以获取类的方法信息(方法的注解,权限修饰符,返回值类型,方法名,形参列表,异常等)。
在类中还有一些特殊的方法:比如构造函数,
通过CLass对象来获取Method的主要方法如下:
- 获取类申明的为public作用域的方法 getMethods();
- 获取类申明的所有方法getDeclaredMethods();
- 通过方法名称,获取类申明的为public作用域的方法getField();
- 通过变量名称,获取类申明的(public ,protect,private,缺省)方法getDeclaredMethod();
- 获取类申明的为public作用域的构造器getConstructors();
- 获取类申明的所有构造器getDeclaredConstructors();
- 通过参数列表获取构造器getDeclaredConstructor();
获取Method后通过对method的操作可以获取方法的详细信息
- 获取方法的注解getAnnotations();
- 获取方法的权限修饰符getModifiers();
- 获取方法返回值类型getReturnType();
- 获取方法名getName();
- 获取参数列表getParameterTypes();
- 获取异常信息getExceptionTypes();
获取类方法信息详细操作如下:
public class TestMethod {
public static void main(String agrs[]){
printPublicMethod();
printMethod();
printPublicMethodByName("testPublicParamter",String.class,String.class);
printMethodByName("testParamter",String.class,String.class);
}
/**
* 打印方法信息
* @param methods
*/
public static void printMethodInfo(Method[] methods){
System.out.println("注解");
System.out.println("作用域 返回值 方法名 (形参列表) throw 异常信息");
for(Method method : methods){
//注解
Annotation[] annotations = method.getAnnotations();
for(Annotation annotation : annotations){
System.out.println(annotation);
}
//权限修饰符
System.out.print(Modifier.toString(method.getModifiers()) + " ");
//返回值类型
System.out.print(method.getReturnType().getName()+ " ");
//方法名
System.out.print(method.getName());
//形参列表
Class[] params = method.getParameterTypes();
System.out.print("(");
for (Class param :params){
System.out.print(param.getName());
}
System.out.print(") ");
//异常信息
Class[] exps = method.getExceptionTypes();
if(0 != exps.length){
System.out.print("throws ");
for (Class exp :exps){
System.out.print(exp.getName());
}
}
System.out.print("{");
System.out.println();
System.out.print("}");
System.out.println();
System.out.println();
}
}
/**
* 打印申明为public的方法
*/
public static void printPublicMethod(){
Class<Person> personClass = Person.class;
/**
* 获取类中作用域申明为public 的方法
*/
System.out.println();
System.out.println("获取类所有申明为public的方法:");
Method[] publicMethods = personClass.getMethods();
printMethodInfo(publicMethods);
}
/**
* 打印申明的所有方法
*/
public static void printMethod(){
Class<Person> personClass = Person.class;
/**
* 获取类中所有的方法
*/
System.out.println();
System.out.println("获取类所有的方法:");
Method[] allMethods = personClass.getDeclaredMethods();
printMethodInfo(allMethods);
}
/**
* 根据名称和参数类型打印类中的申明为Public的方法
*/
public static void printPublicMethodByName(String name,Class ...parameterTypes){
Class<Person> personClass = Person.class;
/**
* 获取类中所有的方法
*/
System.out.println();
System.out.println("据名称和返回值打印类中的申明为Public的方法");
Method[] printMethod = new Method[1];
try {
printMethod[0] = personClass.getMethod(name,parameterTypes);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
printMethodInfo(printMethod);
}
/**
* 根据名称和参数类型打印类中的申明的方法
*/
public static void printMethodByName(String name,Class ...parameterTypes){
Class<Person> personClass = Person.class;
/**
* 获取类中所有的方法
*/
System.out.println();
System.out.println("据名称和返回值打印类中申明的方法");
Method[] printMethod = new Method[1];
try {
printMethod[0] = personClass.getDeclaredMethod(name,parameterTypes);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
printMethodInfo(printMethod);
}
}
运行结果如下(运行结果过长,只截取一部分):
下面是获取类构造器信息的代码
public class TestConstructors {
public static void main(String agrs[]){
printPublicConstructor();
printConstructor();
printConstructorByParameter(String.class);
}
/**
* 打印构造器信息
* @param constructors
*/
public static void printConstructorInfo(Constructor[] constructors){
for (Constructor constructor :constructors ){
System.out.println(constructor);
}
}
/**
* 打印申明为public的构造器
*/
public static void printPublicConstructor(){
Class<Person> personClass = Person.class;
Constructor[] constructors = personClass.getConstructors();
System.out.println();
System.out.println(" 打印申明为public的构造器");
printConstructorInfo(constructors);
}
/**
* 打印申明的所有构造器
*/
public static void printConstructor(){
Class<Person> personClass = Person.class;
System.out.println();
System.out.println(" 打印申明的所有构造器");
Constructor[] constructors = personClass.getDeclaredConstructors();
printConstructorInfo(constructors);}
/**
* 根据参数类型打印类中的申明的构造器
*/
public static void printConstructorByParameter(Class ...parameterTypes){
Class<Person> personClass = Person.class;
Constructor[] constructors = new Constructor[1];
System.out.println();
System.out.println(" 根据参数类型打印类中的申明的构造器");
try {
constructors[0] = personClass.getDeclaredConstructor(parameterTypes);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
printConstructorInfo(constructors);}
}
运行结果如下:
通过CLass对象和反射获取类实现的接口, 父类,注解,所在包等。
下面来看获取类的父类信息,以及实现的接口信息等
/**
* Created by IntelliJ IDEA.
* User:hubin
* Description:
* Date:2017/12/5
* Time:13:25
*/
public class TestParent {
public static void main(String agrs[]){
Class<Person> personClass = Person.class;
/**
* 获取父类
* Type parentClass = personClass.getGenericSuperclass();
* getGenericSuperclass 是获取带泛型的父类
*/
Type parentClass = personClass.getSuperclass();
System.out.println("获取类的父类:");
System.out.println(parentClass);
/**
* 获取类实现的接口
* personClass.getGenericInterfaces()
* getGenericInterfaces获取带泛型的接口
*/
Class[] interfaceClass = personClass.getInterfaces();
System.out.println("获取类实现的接口:");
for(Class interF :interfaceClass){
System.out.println(interF);
}
/**
* 获取类所在的包
*/
System.out.println("获取类所在的包:");
Package paceage = personClass.getPackage();
System.out.println(paceage);
/**
* 获取类的类注解
*/
System.out.println("获取类的类注解:");
Annotation[] annotations = personClass.getAnnotations();
for(Annotation annotation :annotations){
System.out.println(annotation);
}
}
}
运行结果为:
以上就是一些获取类的类型信息的一些操作,更多的操作可以通过JDK文档查看
获取信息了解之后,我们来看通过反射来创建对象,调用方法
通过反射来创建对象,调用方法。
通常在java中我们有以下4中方式创建对象
- 通过new 关键字 创建对象
- 通过Object clone();方法
- 通过反序列化
- 通过反射创建
这里我们来了解通过反射来创建对象和调用方法
首先我们来看通过反射来创建对象
我们通过newInstance()来创建对象,如果对于无参数的构造方法我们直接用Class的对象的newInstance()就可以创建对象
如果对于有参数的构造方法,我们需要先获取带参数的构造器(注意权限修饰符),然后通过构造器的newInstance()方法创建对象。
public class TestReflect {
public static void main(String[] agrs){
Class<Person> personClass = Person.class;
try {
/**
* 通过无参数的构造方法创建对象
*/
Person personOne = personClass.newInstance();
/**
* 通过有参数的构造方法创建对象
*/
Constructor constructor = personClass.getDeclaredConstructor(String.class);
Person personTwo = (Person) constructor.newInstance("带参数");
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
运行结果如下
这样我们就可以通过反射来创建对象。
下面我们来看通过反射来调用方法以及通过反射为属性赋值。
通过反射来为对象赋值