什么是反射?
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
通过反射来了解类
1、类由属性,方法,构造函数等组成
2、给定一个类或对象,通过反射机制可以动态的了解类的属性方法,构造函数,创建对象,调用方法,改写属性
3、应用场景:(1)运行时,动态的情况下应对外面传入的“类名”,对象实例等。(2)只知道类名字符串。(3)通常应用到框架中 。
常用的反射操作 (以Dog这个类为例子)
package learnReflect;
public class Dog {
public String name;
public int age;
private String owner;
public Dog(){
}
public Dog(String name,int age){
this.name = name;
this.age = age;
}
public void bark(){
System.out.println("汪汪");
}
public void celebrateBirthday(){
System.out.println(name+"生日快乐");
addAge();
}
private void addAge(){
age = age+1;
}
}
1、通过一个对象获得完整的包名和类名
public static void getClassFullName(Dog d){
System.out.println("1.获取包名和类名");
Class c = d.getClass();
System.out.println("类名: "+c.getName());
System.out.println("包名: "+c.getPackage().getName());
}
2、获得Class对象 3种方法
public static void getClassInstance(){
System.out.println("2.获得类实例 - 2种方法");
try {
String className = "learnReflect.Dog";
Class c = Class.forName(className);
System.out.println("method 1:"+c.getName());
Class d = Dog.class;
System.out.println("method 2:"+c.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
3、了解类的各种信息
1、获取本类的声明方法,调用类的方法。
public static void getClassMethod(){
Class
Method[] methods = dogClazz.getMethods();//能获取Dog类所有的public方法,不能获取private
Method[] methods2 = dogClazz.getDeclaredMethods();//只能获取Dog类自己定义的所有方法包括私有方法
for(Method m : methods)
System.out.println(m.getName());
try {
//"bark"是方法名,不存在时会抛出异常,new Class[]{}是参数类型数组,无参数就为空
Method method = dogClazz.getMethod("bark", new Class[]{});
//invoke方法用于调用方法,参数为类的实例和方法的参数
method.invoke(dogClazz.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
>2、获得父类信息
>```
public static void getClassSuperClassInfo(){
Class dogClazz = Dog.class;
System.out.println("Dog父类的名字是:"+dogClazz.getSuperclass());
}
3、获得接口信息
public static void getClassInterfaceInfo(){
Class
for(int i = 0; i< dogClazz.getInterfaces().length;i++)
System.out.println(dogClazz.getInterfaces()[i].getName());
}
4、根据Class对象创建instance实例
public static void getInstance(){
System.out.println("创建对象实例======");
Class
try {//方法1:无参的构造方法
Object o = dogClazz.newInstance();
System.out.println("创建的对象是:"+o);
//方法2:有参数的构造方法
Constructor c = dogClazz.getConstructor(new Class[]{String.class,int.class});
Dog o2 = (Dog) c.newInstance("大黄",4);
System.out.println("创建的对象是:"+o2.name);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
5、操作成员变量
public static void changeFiled(){
System.out.println("改变成员变量======");
Class
try {
Object o = dogClazz.newInstance();
//方法2
Constructor c = dogClazz.getConstructor(new Class[]{String.class,int.class});
Dog o2 = (Dog) c.newInstance("大黄",4);
Field[] fields = dogClazz.getFields();
for(Field f : fields){
System.out.println(f.getName());
}
Field[] fields2 = dogClazz.getDeclaredFields();
for(Field f : fields2){
System.out.println(f.getName());
}
Field f = dogClazz.getField("name");
f.set(o2, "大黑");
System.out.println(f.get(o2));
// getDeclaredField()用于获取私有成员变量,必须设置setAccessible(true)才能改变
Field f2 = dogClazz.getDeclaredField("owner");
f2.setAccessible(true);
f2.set(o2, "张三");
System.out.println(f2.get(o2));
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}