java反射机制
- 获取运行时类的完整结构
- 可以再运行时的代码可以根据某些条件改变自身结构
- 反射对性能有影响。
- 一个类在内存中只有一个class对象
- 一个类被加载后,类的整个结构都会被封装在class对象中。
测试1-常用反射类、方法
package com.fh.base;
import java.lang.reflect.*;
import java.util.*;
public class T {
public static void main(String[] args) throws Exception {
getGeneric();
}
/**
* 获得类实例!!!
*/
static void getInstance() throws Exception {
/*Constructor<Stu> declaredConstructor = stuClass.getDeclaredConstructor(int.class, String.class);
Stu stu1 = declaredConstructor.newInstance(12,"Jay");
System.out.println("【通过构造器实现类的实例化】" + stu1);*/
Class stuClass = Class.forName("com.fh.base.Stu");
Stu stu = (Stu) stuClass.newInstance();
System.out.println("【new 类的实例化】" + stu);
System.out.println("【通过反射操作方法 Method invoke(对象,值)。为哪个对象赋值】");
Method setName = stuClass.getDeclaredMethod("setName", String.class);
setName.invoke(stu, "Jay");
System.out.println("【通过反射操作方法 Method invoke(对象)。获取哪个对象的值】");
Method getName = stuClass.getDeclaredMethod("getName");
String name = (String) getName.invoke(stu);
System.out.println(name);
System.out.println("【通过反射操作属性 Field set(对象,值)");
Field name1 = stuClass.getDeclaredField("name");
name1.setAccessible(true);//java.lang.IllegalAccessException: Class com.fh.base.T can not access a member of class com.fh.base.Stu with modifiers "private"
name1.set(stu, "周杰伦");
System.out.println(stu.getName());
}
/**
* 获得包信息
*/
static void getPackeage() {
System.out.println("【获得类所在包】");
Class stuClass = Stu.class;
Package aPackage = stuClass.getPackage();
System.out.println(aPackage);
}
/**
* 获得Class信息
*/
static void getClassz() throws Exception {
//System.out.println("【Java 类路径】" + System.getProperty("java.class.path"));
System.out.println("【获取类的加载器】" + T.class.getClassLoader()
+ ";Object根加载器:" + Object.class.getClassLoader());
Class<T> tClass1 = T.class;
Class<?> tClass2 = Class.forName("com.fh.base.T");
T t = new T();
Class<? extends T> tClass3 = t.getClass();
System.out.println("【一个类在内存中只有一个class对象】" + (tClass1.hashCode() == tClass2.hashCode() && tClass2.hashCode() == tClass3.hashCode()));
System.out.println("【获得类名】" + tClass1.getName());
T t1 = tClass1.newInstance();
T t2 = tClass1.newInstance();
Stu stu = Stu.class.newInstance();
System.out.println("【类的实例化】" + (t1 == t2));
System.out.println("【类的实例化】" + stu);
System.out.println("【用来判断A是否是B的实例对象或者B子类的实例对象】" + (t1 instanceof T));
}
/**
* 获得属性信息
*/
static void getField() throws Exception {
Class stuClass = Stu.class;
System.out.println("【获取所有属性】");
Field[] declaredFields = stuClass.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field);
}
System.out.println("【获取public属性】");
Field[] fields = stuClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
Field name = stuClass.getDeclaredField("name");
System.out.println("【获取指定属性】" + name);
}
/**
* 获得方法
*/
static void getMehtods() throws Exception {
Class stuClass = Stu.class;
System.out.println("【获取所有方法(包括Object putlic方法)】");
Method[] declaredMethods = stuClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("【获取public方法】");
Method[] methods = stuClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("【获取指定方法】");
Method setName = stuClass.getDeclaredMethod("setName", String.class);
System.out.println(setName);
}
/**
* 获得构造器
*/
static void getConstruct() throws Exception {
Class stuClass = Stu.class;
System.out.println("【获取所有构造器】");
Constructor[] declaredConstructors = stuClass.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
System.out.println("【获取所有public构造器】");
Constructor[] constructors = stuClass.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("【获取指定构造器】");
Constructor declaredConstructor = stuClass.getDeclaredConstructor(int.class, String.class);
System.out.println(declaredConstructor);
}
/**
* 反射对性能有影响
*/
static void wasteTime() throws Exception {
/*******************正常获取属性消耗**********************/
long startTime = System.currentTimeMillis();
Stu stu = new Stu();
for (int i = 0; i < 10_0000_0000; i++) {
stu.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("正常获取属性消耗:" + (endTime - startTime) + "ms");
/*********************反射获取属性消耗********************/
startTime = System.currentTimeMillis();
Class<?> stuClass = Class.forName("com.fh.base.Stu");
Method getName = stuClass.getDeclaredMethod("getName");
stu = (Stu) stuClass.newInstance();
for (int i = 0; i < 10_0000_0000; i++) {
getName.invoke(stu);
}
endTime = System.currentTimeMillis();
System.out.println("反射获取属性消耗:" + (endTime - startTime) + "ms");
/*********************反射获取属性消耗********************/
startTime = System.currentTimeMillis();
getName.setAccessible(true);
for (int i = 0; i < 10_0000_0000; i++) {
getName.invoke(stu);
}
endTime = System.currentTimeMillis();
System.out.println("反射获取属性消耗:" + (endTime - startTime) + "ms");
}
/**
* 反射机制操作泛型
* 泛型擦除机制引入泛型,java中的泛型仅仅是给编译器javac使用的,确保
* 数据的安全性和免去强制类型转换问题。一旦编译完成,所有和泛型有关的类型
* 全部被擦除。
*/
static void getGeneric() throws Exception {
Method method = Stu.class.getDeclaredMethod("getStu", List.class, Map.class);
System.out.println("【获取方法中的所有泛型参数】");
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println("***" + genericParameterType);
if (genericParameterType instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("【获取泛型参数具体参数】" + actualTypeArgument);
}
}
}
method = Stu.class.getDeclaredMethod("getStu");
Type genericReturnType = method.getGenericReturnType();
if (genericReturnType instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("【获取泛型返回值的具体参数】" + actualTypeArgument);
}
}
}
}
class Stu {
private int id;
private String name;
private String sex;
public String hobby;
String schooh;
private Stu(int id, String name, String sex) {
this.id = id;
this.name = name;
this.sex = sex;
}
public Stu() {
}
public Stu(int id, String name) {
this.id = id;
this.name = name;
}
public Map<String, Stu> getStu() {
return null;
}
public void getStu(List<Stu> list, Map<String, Stu> map) {
}
public int getId() {
return id;
}
public Stu setId(int id) {
this.id = id;
return this;
}
public String getName() {
return name;
}
public Stu setName(String name) {
this.name = name;
return this;
}
public String getSex() {
return sex;
}
public Stu setSex(String sex) {
this.sex = sex;
return this;
}
private void test1() {
}
@Override
public String toString() {
return "Stu{" +
"id=" + id +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", hobby='" + hobby + '\'' +
", schooh='" + schooh + '\'' +
'}';
}
}
测试2-通过反射设置表和类关系映射Annotation
package com.fh.gaoji.anotation;
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class ClassAndTableYingSheTest {
public static void main(String[] args) throws NoSuchFieldException {
Class<Stu> stuClass = Stu.class;
//获取类上的所有注解
Annotation[] annotations = stuClass.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println("【获取Stu类所有注解】"+annotation);
}
//获取ClassAndTable注解
ClassAndTable classAndTable = stuClass.getAnnotation(ClassAndTable.class);
System.out.println("【获取指定类注解的值】"+classAndTable.value());
System.out.println("【获取Stu类所有属性】");
Field[] fields = stuClass.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field =fields[i];
FildAndColum annotation = field.getAnnotation(FildAndColum.class);
System.out.println(annotation.name() + "***" +annotation.type() + "***" + annotation.length());
}
//获取FildAndColum注解
Field field = stuClass.getDeclaredField("name");
FildAndColum annotation = field.getAnnotation(FildAndColum.class);
System.out.println("【获取指定类属性的值】"+annotation.name() + "***" +annotation.type() + "***" + annotation.length());
}
}
@ClassAndTable("db_student")
class Stu{
@FildAndColum(name = "db_id",type = "int",length = 10)
private int id;
@FildAndColum(name = "db_name",type = "varchar",length = 100)
private String name;
public int getId() {
return id;
}
public Stu setId(int id) {
this.id = id;
return this;
}
public String getName() {
return name;
}
public Stu setName(String name) {
this.name = name;
return this;
}
@Override
public String toString() {
return "Stu{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
/**
* 类和【表】的映射
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface ClassAndTable{
String value();//调用一个value属性时候,value可以省略,如 @MyAnnotation1("")
}
/**
* 属性和【列】的映射
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FildAndColum{
String name();
String type();
int length();
}
//@Target({ElementType.TYPE,ElementType.METHOD})
//@Retention(RetentionPolicy.RUNTIME)
//@interface MyAnnotation1{
// //注解参数:参数类型+参数名()
// String name() default "fh";//没有默认值,调用注解必须加上此参数!!!
// int age() default 14;
// String value();//调用一个value属性时候,value可以省略,如 @MyAnnotation1("")
// String[] school() default {"AA","BB"};
//
//}