java入门篇9 --- 反射
Posted 灬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java入门篇9 --- 反射相关的知识,希望对你有一定的参考价值。
反射
我们自己定义的class其实是JVM在运行时动态加载的,每读到一个class,JVM就会床架一个CLASS实例,并加载到内存中
我们首先看一下Class的源码,从源码可以看出,在进行实例化时,它是一个私有方法,因此,我们写的java程序无法将其实例化,通过分析源码,我们可以确认,我们定义的每个类最终都是Class的实例,因此他们都指向数据类型class或者interface,Class里面有很多字段,因此每个Class的实例里面包含这个类所有的信息
public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement, TypeDescriptor.OfField<java.lang.Class<?>>, Constable { private Class(ClassLoader loader, Class<?> arrayComponentType) { // Initialize final field for classLoader. The initialization value of non-null // prevents future JIT optimizations from assuming this final field is null. classLoader = loader; componentType = arrayComponentType;
... } }
public class HelloWorld { public static void main(String[] args) throws Exception { Class t = new Class(ClassLoader.getPlatformClassLoader(), String.class); //java: Class(java.lang.ClassLoader,java.lang.Class<?>) 在 java.lang.Class 中是 private 访问控制 } }
接下来看一下我们反射调用,这个一般自己写框架时会用到
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; class Person { public String name; public Person(String name) { this.name = name; } public void eat(){ System.out.println("Person eat"); } public String run(String s){ return String.format("Person is running on %s", s); } public void nothing(){ } } class Student extends Person { private String sex; public int age; public Student(String name, String sex, int age) { super(name); this.sex = sex; this.age = age; } @Override public void eat(){ System.out.println("Student eat"); } @Override public String run(String s){ return String.format("Student is running on %s", s); } private void getSex(){ System.out.println(this.sex); } public static void ss(){ System.out.println("static"); } } public class HelloWorld { public static void main(String[] args) throws Exception { // 获取string的Class实例 Class c1 = String.class; Class c2 = "h".getClass(); Class c3 = Class.forName("java.lang.String"); // 因为Class实例是JVM中唯一的,都是String.class,因此可以使用 == 来进行比较 System.out.println(c1 == c2); // true 从结果分析,我们更可以断定,实例是唯一的 System.out.println(c1 == c3); // true // 我们以前用过 instanceof 来判断是否是可以向上转型 Integer n = Integer.valueOf(1); System.out.println(n instanceof Number); // true 因为Integer是Number的子类 // System.out.println(n.getClass() == Number.class); // Error:(14, 42) java: 不可比较的类型: java.lang.Class<capture#1, 共 ? extends java.lang.Integer>和java.lang.Class<java.lang.Number> System.out.println("".getClass().getName()); // java.lang.String System.out.println("".getClass().getSimpleName()); // String System.out.println("".getClass().isInterface()); // false System.out.println("".getClass().isPrimitive()); // false System.out.println("".getClass().isArray()); // false Class stud = Student.class; // 获取字段,可以使用getField来获取指定字段,但是对于private字段,无法获取,需要使用getDeclaredField System.out.println(stud.getField("age")); // public int Student.age System.out.println(stud.getField("name")); // public java.lang.String Person.name System.out.println(stud.getDeclaredField("sex")); // private java.lang.String Student.sex // System.out.println(stud.getField("sex")); // Exception in thread "main" java.lang.NoSuchFieldException: sex // 使用getFields,来获取全部非privte字段 Field[] f = stud.getFields(); System.out.println("----"); for (Field ff : f) { System.out.println(ff); } // public int Student.age public java.lang.String Person.name System.out.println("----"); // 使用getDeclaredFields,来获取当前类全部字段 Field[] f1 = stud.getDeclaredFields(); for (Field ff1 : f1) { System.out.println(ff1); } // private java.lang.String Student.sex public int Student.age Field f2 = stud.getField("age"); Field f3 = stud.getDeclaredField("sex"); System.out.println(f2.getName()); // age 获取这个字段的名称 System.out.println(f3.getName()); // name 获取这个字段的名称 System.out.println(f2.getType()); // int 获取这个字段的类型 System.out.println(f3.getType()); // class java.lang.String 获取这个字段的类型 System.out.println(f2.getModifiers()); // 1 获取这个字段的修饰符 该字段修饰符是public,不同的int值代表不同 System.out.println(f3.getModifiers()); // 2 获取这个字段的修饰符 int ff2 = f2.getModifiers(); System.out.println(Modifier.isFinal(ff2)); // false System.out.println(Modifier.isPrivate(ff2)); // false System.out.println(Modifier.isPublic(ff2)); // false // 获取字段的值 Student s = new Student("ming", "male", 25); Class st = s.getClass(); Field f4 = st.getDeclaredField("sex"); // Object v = f4.get(s); // java.lang.IllegalAccessException: class HelloWorld cannot access a member of class Student with modifiers "private" 被阻止 f4.setAccessible(true); // 对于private字段,使用setAccessible(true),但是仍然有可能会报IllegalAccessException错误 Object v = f4.get(s); System.out.println(v); // male 获取字段的值 // 重置字段的值 Field f5 = st.getField("name"); f5.set(s, "ning"); f5.setAccessible(true); // 对于private,都需要设置这个 f4.set(s, "female"); System.out.println(s.name); // ning System.out.println(f4.get(s)); // female // 获取方法 Class ss = Student.class; System.out.println(ss.getMethod("run", String.class)); // public java.lang.String Student.run(java.lang.String) System.out.println(ss.getMethod("eat")); // public void Student.eat() // System.out.println(ss.getMethod("getSex")); // 无法获取私有方法,java.lang.NoSuchMethodException: Student.getSex() System.out.println(ss.getDeclaredMethod("getSex")); // private void Student.getSex() Method[] sm = ss.getMethods(); Method[] sm1 = ss.getDeclaredMethods(); System.out.println("---"); for(Method smm : sm){ System.out.println(smm); } //public java.lang.String Student.run(java.lang.String) public void Student.eat() public void Person.nothing() public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException // public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException // public final void java.lang.Object.wait() throws java.lang.InterruptedException // public boolean java.lang.Object.equals(java.lang.Object) // public java.lang.String java.lang.Object.toString() // public native int java.lang.Object.hashCode() // public final native java.lang.Class java.lang.Object.getClass() // public final native void java.lang.Object.notify() // public final native void java.lang.Object.notifyAll() System.out.println("---"); // 无法获取父类的方法 for(Method smm : sm1){ System.out.println(smm); } // public java.lang.String Student.run(java.lang.String) public void Student.eat() private void Student.getSex() Method smm = ss.getMethod("run", String.class); Method smm1 = ss.getMethod("eat"); // 获取方法名 System.out.println(smm.getName()); // run System.out.println(smm1.getName()); // eat // 获取返回类型 System.out.println(smm.getReturnType()); // class java.lang.String System.out.println(smm1.getReturnType()); // void // 获取参数数量 System.out.println(smm.getParameterCount()); // 1 System.out.println(smm1.getParameterCount()); // 0 // 方法的调用 System.out.println(smm.invoke(s, "floor")); // Student is running on floor smm1.invoke(s); // Student eat // Method smm2 = ss.getMethod("getSex"); // java.lang.IllegalArgumentException: object is not an instance of declaring class Method smm2 = ss.getDeclaredMethod("getSex"); smm2.setAccessible(true); // 如果不设置这个会报错,私有属性必须设置 smm2.invoke(s); // female // 多态 Method p = Person.class.getMethod("eat"); p.invoke(s); // Student eat 虽然方法是person的,但传入的实例属于Student,因此但因Student方法 // 调用静态方法 Method ssm = Student.class.getMethod("ss"); ssm.invoke(null); // static // 获取构造方法 Constructor pp = Person.class.getConstructor(String.class); Person ppp = (Person) pp.newInstance("ming"); System.out.println(ppp.name); // ming // 获取继承关系 Class s5 = Student.class; System.out.println(s5.getSuperclass()); // class Person System.out.println(s5.getSuperclass().getSuperclass()); // class java.lang.Object // 获取interface 值返回直接实现的 Class[] s5i = s5.getInterfaces(); System.out.println("---"); for(Class s5s : s5i){ System.out.println(s5s); } // System.out.println("---"); Class[] i5 = Integer.class.getInterfaces(); for(Class i5s : i5){ System.out.println(i5s); } // interface java.lang.Comparable interface java.lang.constant.Constable interface java.lang.constant.ConstantDesc } }
以上是关于java入门篇9 --- 反射的主要内容,如果未能解决你的问题,请参考以下文章