java反射机制
java反射机制是一种动态机制,它允许我们加载一个类实例化一个类,调用方法或操作属性从编码期间确定转为在运行期间确定。
这样做可以大大提高代码的灵活度,但是反射有更大的资源开销。所以不能过度依赖反射。
Class 用来描述类本身
Class类
Class类的每一个实例用于表示JVM已经加载的一个类。并且在JVM内部每个被加载的类都有且只有一个Class的实例与之对应。通过类对象我们可以:
获取其表示的类的名字,构造方法,方法,属性,并可以快速实例化。
获取一个类的类对象有以下方式:
1:直接通过类的静态属性class得到。
比如像获取String的类对象,我们可以:
Class cls = Person.class;
2:通过Class的静态方法forName加载:
Class cls = Class.forName(“java.lang.String”);
3:通过类加载器ClassLoader
对象.getClass();
Package 类中的包
Field 用来描述类中的属性
Method 描述类中的方法
Constructor 类的构造方法
Annotation 类中的注解
public static void main(String[] args) {
try {
//获得类的三种方法
System.out.println(Class.forName("atm.Test$Person"));
System.out.println(Person.class);
System.out.println(new Test().new Person().getClass());
Class clazz1 = Class.forName("atm.Test$Person");
System.out.println("类的修饰符"+clazz1.getModifiers());;
Class clazz = Class.forName("java.util.ArrayList");
System.out.println(clazz);
System.out.println(ArrayList.class);
System.out.println(new ArrayList<String>().getClass());
System.out.println("类的修饰符"+clazz.getModifiers());
System.out.println("类的名字有包"+clazz.getName());
System.out.println("类的名字"+clazz.getSimpleName());
Package package1 = clazz.getPackage();
System.out.println("类所在的包"+package1.getName());
Class class1 = clazz.getSuperclass();
System.out.println("父类"+class1);
Class[] classes = clazz.getInterfaces();
for (Class class2 : classes) {
System.out.println("实现的接口"+class2);
}
//相当于调用无参数构造方法创建对象,如果没有无参数构造方法,会抛出异常
Object object = clazz.newInstance();
//获取类的属性,只能看到public修饰的
Class class3 = Atm.class;
Atm atm = (Atm) class3.newInstance();
Field field = class3.getField("size");
//属性的修饰符
System.out.println(field.getModifiers());
//属性的类型
System.out.println(field.getType());
//属性的名字
System.out.println(field.getName());
//给属性赋值
field.set(atm, "张三");
//取出属性的值
System.out.println(field.get(atm));
//获取类中的所有属性,自己的和父类的所有public的
Field[] fields = class3.getFields();
for (Field field2 : fields) {
System.out.println(field2);
}
//获得其他权限修饰符的属性
Field field1 = class3.getDeclaredField("age");
//修改属性被操作的状态(允许私有属性被赋)
field1.setAccessible(true);
field1.set(atm, 1);
System.out.println(field1.get(atm));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
//通过反射修改String的不可变特性
try {
String string = "李四";
Class clazz1 = String.class;
Field value = clazz1.getDeclaredField("value");
value.setAccessible(true);
//获取value的内存地址
char[] cs = (char[])value.get(string);
cs[0]='张';
cs[1]='三';
System.out.println(string);
} catch (Exception e) {
e.printStackTrace();
}
}
获取类中的方法
public static void main(String[] args) {
Class clazz = Atm.class;
//获取类中的所有方法
//获取自己类和父类的所有public方法
Method[] methods = clazz.getMethods();
System.out.println(methods);
try {
//根据方法名字获得类中的一个方法
//根据名字获取自己类和父类的所有public方法
Method method = clazz.getMethod("eat");
//........
int a = method.getModifiers();
Class b = method.getReturnType();
String c = method.getName();
Class[] d = method.getParameterTypes();
Class[] e = method.getExceptionTypes();
//调用方发执行
method.invoke(clazz.newInstance());
//获得有参数的方法并执行
Method method2 = clazz.getMethod("eat", int.class,String.class);
Object object = method2.invoke(clazz.newInstance(), 10,"张三");
System.out.println((Integer)object);
//获得其他修饰符的方法
Method method3 = clazz.getDeclaredMethod("slep");
//此时不能直接赋值,需要设置方法的准入权
method3.setAccessible(true);
method3.invoke(clazz.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
获取类中的构造方法
public static void main(String[] args) {
try {
Class clazz = Atm.class;
clazz.getConstructors();
Constructor cons = clazz.getConstructor();
//执行构造方法
cons.newInstance();
Constructor cons1 = clazz.getConstructor(String.class,Integer.class);
cons1.newInstance("张三",111);
} catch (Exception e) {
e.printStackTrace();
}
}