Java反射概念:
Java反射机制是在运行状态中,对于任意一个类,都够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。Class类:
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。
Class 没有公共构造方法,获取Class类的三种方法:1:MyObject x;
Class c1 = x.getClass(); //getClass()方法为Object类的方法,所有类均可使用此方法
2:Class c2=Class.forName("MyObject");
3:Class cl2 = int.class;
通过Class对象,可以返回用来访问用来返回该对象的描述信息。其主要方法有
最主要的是get方法:
<A extends Annotation>
A
getAnnotation(Class<A> annotationClass)
如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。
Annotation[] getAnnotations()
返回此元素上存在的所有注释。
String getCanonicalName()
返回 Java Language Specification 中所定义的底层类的规范化名称。
Class<?>[] getClasses()
返回一个包含某些 Class 对象的数组,这些对象表示属于此 Class 对象所表示的类的成员的所有公共类和接口。
ClassLoader getClassLoader()
返回该类的类加载器。
Class<?> getComponentType()
返回表示数组组件类型的 Class。
Constructor<T> getConstructor(Class<?>... parameterTypes)
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
Constructor<?>[] getConstructors()
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
Annotation[] getDeclaredAnnotations()
返回直接存在于此元素上的所有注释。
Class<?>[] getDeclaredClasses()
返回 Class 对象的一个数组,这些对象反映声明为此 Class 对象所表示的类的成员的所有类和接口。
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
Constructor<?>[] getDeclaredConstructors()
返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
Field getDeclaredField(String name)
返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
Field[] getDeclaredFields()
返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
Method getDeclaredMethod(String name, Class<?>... parameterTypes)
返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
Method[] getDeclaredMethods()
返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
Class<?> getDeclaringClass()
如果此 Class 对象所表示的类或接口是另一个类的成员,则返回的 Class 对象表示该对象的声明类。
Class<?> getEnclosingClass()
返回底层类的立即封闭类。
Constructor<?> getEnclosingConstructor()
如果该 Class 对象表示构造方法中的一个本地或匿名类,则返回 Constructor 对象,它表示底层类的立即封闭构造方法。
Method getEnclosingMethod()
如果此 Class 对象表示某一方法中的一个本地或匿名类,则返回 Method 对象,它表示底层类的立即封闭方法。
T[] getEnumConstants()
如果此 Class 对象不表示枚举类型,则返回枚举类的元素或 null。
Field getField(String name)
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
Field[] getFields()
返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
Type[] getGenericInterfaces()
返回表示某些接口的 Type,这些接口由此对象所表示的类或接口直接实现。
Type getGenericSuperclass()
返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type。
Class<?>[] getInterfaces()
确定此对象所表示的类或接口实现的接口。
Method getMethod(String name, Class<?>... parameterTypes)
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
Method[] getMethods()
返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
int getModifiers()
返回此类或接口以整数编码的 Java 语言修饰符。
String getName()
以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
Package getPackage()
获取此类的包。
ProtectionDomain getProtectionDomain()
返回该类的 ProtectionDomain。
URL getResource(String name)
查找带有给定名称的资源。
InputStream getResourceAsStream(String name)
查找具有给定名称的资源。
Object[] getSigners()
获取此类的标记。
String getSimpleName()
返回源代码中给出的底层类的简称。
Class<? super T> getSuperclass()
返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。
TypeVariable<Class<T>>[] getTypeParameters()
按声明顺序返回 TypeVariable 对象的一个数组,这些对象表示用此 GenericDeclaration 对象所表示的常规声明来声明的类型变量。
访问构造方法(Construction类)
Construction类型为类的构造函数的对象或者数组。
Construction对象为Class对象调用下列四种方法获取的:
1.getConstructor(Class<?>... parameterTypes) ;2.getConstructors();
3.getDeclaredConstructor(Class<?>... parameterTypes) ;4.getDeclaredConstructors() ;
示例:
/**
*定义一个标准的JavaBean,名叫Person,包含属性name、age。使用反射的方式创建一个实例、调用构造函数初始化name、age,
*使用反射方式调用setName方法对名称进行设置,不使用setAge方法直接使用反射方式对age赋值。
*/
package com.itheima;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @author liangpeng
*
*/
class Person //创建JavaBean
{
private String name;
private int age;
public Person()
{
}
public Person(String name,int age)
{
this.name = name;
this.age = age;
}
public void setName(String name)
{
this.name = name;
}
public void setAge(int age)
{
this.age = age;
}
public int getAge()
{
return age;
}
public String getName()
{
return name;
}
}
public class Test6 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO 自动生成的方法存根
try
{
Class<?> class1 = Class.forName("com.itheima.Person");
Constructor<?> constructor = class1.getDeclaredConstructor(String.class,int.class);
//通过反射方式获取类的构造函数
System.out.println("通过反射方式创建实例");
Person person = (Person)constructor.newInstance("wangwu",25);
System.out.println("Name:"+person.getName()+" Age:"+person.getAge());
System.out.println("通过反射方式调用setName方法");
Method setNameMethod = class1.getDeclaredMethod("setName", String.class);
setNameMethod.invoke(person, "lisi");
System.out.println("Name:"+person.getName()+" Age:"+person.getAge());
System.out.println("通过反射方式访问成员函数");
Field ageField = class1.getDeclaredField("age");
ageField.setAccessible(true); //设置忽略权限可以访问成员变量
ageField.set(person, 30); //设置对象person的age成员变量值为30
System.out.println("Name:"+person.getName()+" Age:"+person.getAge());
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Modifier类
可以用来解析出getModifiers()方法返回值所表示的修饰符信息,在该类中提供了一系列用来解析的静态方法。既可以用来判断修饰符类型,又可以获取修饰符的字符串形式。访问成员变量(Field类)
Field类型为类的成员变量的对象或者数组。Field对象为Class对象调用下列四种方法获取的:
getDeclaredField(String name);getDeclaredFields();
getField(String name);getFields();
访问方法(Method类)
Method类型为类的成员变量的对象或者数组。Method对象为Class对象调用下列四种方法获取的:
getDeclaredMethod(String name, Class<?>... parameterTypes)
getDeclaredMethods();
getMethod();
getMethods();
注:invoke(Object obj,Object...args) 可以利用指定的参数执行指定对象中的该方法invoke(null,new Object[]{new String[]{"xxx"}})这种情况编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了。
/**
* 8、 编写一个类,增加一个实例方法用于打印一条字符串。并使用反射手段创建该类的对象, 并调用该对象中的方法。
*/
package com.itheima;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* @author liangpeng
*
*/
class ClassDemo
{
public ClassDemo()
{
}
public void run()
{
System.out.println("Welcome to itheima");
}
}
public class Test8 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO 自动生成的方法存根
try {
Class<?> class1 = Class.forName("com.itheima.ClassDemo");//创建类的Class对象
Constructor<?> constructor = class1.getConstructor(); //创建类的构造函数对象
Method method = class1.getDeclaredMethod("run"); //创建类的方法对象
method.invoke(constructor.newInstance()); //创建类并执行该方法
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
Annotation
Annotation功能可用于类、构造方法、成员变量、方法、参数等的声明中,不影响程序的运行,对编译器警告灯辅助工程产生作用。
定义Annotation类型 @interface,其隐含意义就是继承了java.lang.annotation.Annotation接口
定义Annotation类型时,还可以通过Annotation类型@Target来设置Annotation类型适用的程序元素种类,使用枚举型ElementType的枚举常量来设置@Target;使用枚举型RetentionPolicy中的枚举常量来设置@Retention。
如果在定义Annotation类型时将@Retention设置为RetentionPolicy.RUNTIME,那么在运行程序时通过反射就可以获取到相关的Annotation信息。