# java反射
1、反射就是把Java类中的各个成分映射成一个个的Java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫Java的反射机制。
2、在方法区存在的类对象(Class),当new对象时,通过方法区的类对象在堆里创建实例;即每个堆里的对象都有在方法区里对应的类对象
java反射机制是在运行状态中,对任意类都能够操作其属性和方法。
3、Java反射机制主要提供了以下功能:
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法(动态代理)
## test所需类
/**
* 战士类
*/
public class FighterEntity {
protected String name;//姓名
public String sex;//性别
protected int age;//年龄
private String star;//所属星球
private String sects;//所属门派
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getStar() {
return star;
}
public void setStar(String star) {
this.star = star;
}
/**
* 类注解
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassAnn {
String value() default "";
}
/**
* 字段注解
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldAnn {
String value() default "";
}
public String getSects() {
return sects;
}
public void setSects(String sects) {
this.sects = sects;
}
}
@ClassAnn("类注解测试")
public class SaiyaEntity extends FighterEntity{
@FieldAnn("字段注解测试")
private String arms;
public SaiyaEntity(String name){
this.name = name;
}
private SaiyaEntity(String name,String arms){
this.name = name;
this.arms = arms;
}
public SaiyaEntity(){
}
public String getArms() {
return arms;
}
public void setArms(String arms) {
this.arms = arms;
}
//变身 无参 无返回值
public void evolution(){
System.out.println(getName()+"变身为超级赛亚人");
}
//变身 有参 无返回值
public void evolution(int no){
System.out.println(getName()+"变身为超级赛亚人"+no);
}
//变身 有参 有返回值
public String getEvolution(int no){
return getName()+"变身为超级赛亚人"+no;
}
private void isHungry() {
System.out.println(getName()+"饿了");
}
}
## 获取类对象方法
1、 通过类名获取
2、 通过类路径获取
3、通过实例对象获取
/**
* 获取类名
* @throws Exception
*/
@Test
public void getClassObjTest() throws Exception {
//1、通过类名获取
Class clazz1 = FighterEntity.class;
System.out.println(clazz1.getCanonicalName());
//2、通过类路径获取
Class clazz2 = Class.forName("com.example.entity.FighterEntity");
//3、通过实例对象获取
FighterEntity kklt = new FighterEntity();
Class clazz3 = kklt.getClass();
}
## 类对象操作
@Test
public void classOpt(){
Class clazz = SaiyaEntity.class;
//获取类名称
String name = clazz.getName();
System.out.println("类名称:"+name);
//得到父类
Class superClass = clazz.getSuperclass();
System.out.println("父类名:"+superClass.getName());
//获取类加载器
ClassLoader classLoader = clazz.getClassLoader();
//获取资源
URL resource = clazz.getResource("");
//判断一个类是不是接口
boolean anInterface = clazz.isInterface();
//判断一个类是否是数组
boolean isArray = clazz.isArray();
//......
}
## 属性操作
1、 获取属性对象Field
- getField获取public属性(包含父类属性)
- getDeclaredField获取所有属性(不包含父类的属性)
2、 属性对象Field操作
- public属性可以直接操作(包含父类属性)
- 非public属性需要setAccessible(true)(不包含父类属性)
/**
* 类属性操作
*/
@Test
public void classFieldOpt() throws Exception {
Class clazz = SaiyaEntity.class;
Field[] pubFields = clazz.getFields();//public属性 可以拿到父类
System.out.println("public属性:");
for(Field field : pubFields){
System.out.println(field.getName());
}
Field[] allFields = clazz.getDeclaredFields();//所有属性 不能拿到父类的属性
System.out.println("所有属性:");
for(Field field : allFields){
System.out.println(field.getName());
}
SaiyaEntity kklt = new SaiyaEntity();//创建赛亚人战士
kklt.setName("卡卡罗特");
//public field操作
Field sexField = clazz.getField("sex");
sexField.set(kklt,"男");
System.out.println(kklt.getName() +"性别:"+kklt.getSex());
System.out.println("反射获取"+kklt.getName() +"性别:"+sexField.get(kklt));
Field armsField = clazz.getDeclaredField("arms");//武器属性
armsField.setAccessible(true);//操作权限
armsField.set(kklt,"金箍棒");
System.out.println(kklt.getName() +"武器:"+kklt.getArms());
System.out.println("反射获取"+kklt.getName() +"武器:"+armsField.get(kklt));
}
## 方法操作
1、 获取方法对象
- getMethod获取public方法(包含父类方法)
- getDeclaredMethod获取所有方法(不包含父类的方法)
2、方法对象Method操作
- public方法可以直接操作(包含父类方法)
- 非public方法需要setAccessible(true)(不包含父类方法)
- 通过invoke()调用方法(4种情况)
- 无参,无返回值
- 有参无返回值
- 有参有返回值
- 无参,有返回值
/**
* 类方法操作
*/
@Test
public void classMethodOpt() {
try {
Class<?> clazz = SaiyaEntity.class;//获取类对象
SaiyaEntity kklt = new SaiyaEntity();//创建赛亚人战士 卡卡罗特
kklt.setName("卡卡罗特");
kklt.setArms("金箍棒");
System.out.println("----------------无参数 无返回值test");
Method evolution1 = clazz.getMethod("evolution");//无参数 无返回值 调用
evolution1.invoke(kklt);
System.out.println("----------------无参数 无返回值test--------------------");
System.out.println("----------------有参数 无返回值test");
Method evolution2 = clazz.getMethod("evolution",int.class);//有参数 无返回值 调用
System.out.println("参数个数:"+evolution2.getParameterCount());//方法参数个数
System.out.println("参数类型数组:"+ Arrays.toString(evolution2.getParameterTypes()));//方法参数类型数组
evolution2.invoke(kklt,2);
System.out.println("----------------有参数 无返回值test--------------------");
System.out.println("----------------有参数 有返回值test");
Method getEvolution = clazz.getMethod("getEvolution",int.class);//有参数 有返回值 调用
System.out.println("参数类型数组:"+ getEvolution.getReturnType().getName());//返回值类型
String str = (String)getEvolution.invoke(kklt,2);
System.out.println(str);
System.out.println("----------------有参数 有返回值test--------------------------");
System.out.println("----------------非public方法test");
//非public方法
Method isHungry = clazz.getDeclaredMethod("isHungry");
isHungry.setAccessible(true);
isHungry.invoke(kklt);
System.out.println("----------------非public方法test-------------------------");
}catch (NoSuchMethodException e){
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
## 构造器(特殊的方法)
### getConstructor获取public构造器
### getDeclaredConstructor获取所有构造器
### 创建对象newInstance()
### 非public方法需要setAccessible(true)
/**
* 类构造器操作
*/
@Test
public void classConstructorOpt() {
try {
Class<?> clazz = SaiyaEntity.class;//获取类对象
Constructor[] pubConstructors = clazz.getConstructors();
for(Constructor obj : pubConstructors){
System.out.println("构造器名称:"+obj.getName()+"----构造器参数:"+obj.getParameterCount());
}
Constructor pubConstructor = clazz.getConstructor();
System.out.println("构造器名称:"+pubConstructor.getName()+"----构造器参数:"+pubConstructor.getParameterCount());
Constructor[] constructors = clazz.getDeclaredConstructors();
for(Constructor obj : constructors){
System.out.println("构造器名称:"+obj.getName()+"----构造器参数:"+obj.getParameterCount());
}
//创建无参对象
Constructor constructor1 = clazz.getDeclaredConstructor();
Object obj1 = constructor1.newInstance();
//创建有参对象
Constructor constructor2 = clazz.getDeclaredConstructor(String.class,String.class);
constructor2.setAccessible(true);
Object obj2 = constructor2.newInstance("卡卡罗特","金箍棒");
System.out.println();
}catch (NoSuchMethodException e){
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
## 注解操作
/**
* 注解操作
*/
@Test
public void classAnnotationOpt() {
try {
Class<?> clazz = SaiyaEntity.class;//获取类对象
ClassAnn classAnn = clazz.getAnnotation(ClassAnn.class);//获取类注解
System.out.println(classAnn.value());
Field armsField = clazz.getDeclaredField("arms");
FieldAnn fieldAnn = armsField.getAnnotation(FieldAnn.class);
System.out.println(fieldAnn.value());
}catch (NoSuchFieldException e){
e.printStackTrace();
}
}