所有的变量类型或者是一个引用,或者是原始类型, 字符串,类,枚举,数组,接口,注解,都是引用
对所有的对象,JVM都会立即生产一个java.lang.Class的不可变实例,包含各种方法来检测这个对象的运行时属性
Class也可以创建新类和新对象,也是所有反射API的主入口
java.lang.reflect 包中的所有类都没有public的构造,只能调用Class的相关方法获得他们的实例
1.如果存在一个实例对象,最简单的方法就是调用Object.getClass()来获得Class对象
2.如果没有实例,只有一个类型,可以使用XX.class,当然更适合于原始类型.class,也适用于多重数组,包括void类型
3.Class.forName("com.duke.MyLocaleServiceProvider");
一般用于全名,是Class类的static方法,可以直接用,不过原始类型只能用第二种
Class cDoubleArray = Class.forName("[D");//类似于double[].class Class cStringArray = Class.forName("[[Ljava.lang.String;");//类似于String[][].class
4.每个包装类包括Void,都有个TYPE字段,也会获得Class对象
5.有的方法也会返回另一个Class对象,不过前提是已经有了一个Class对象
Class.getSuperclass()//父类
Class.getEnclosingClass()//外部类
Class.getClasses()//返回所有内部类,枚举,接口,包括继承过来的
Character也有几个方法(略)
XX.getDeclaringClass()//可以是Class,Field,Method,Constractor
当然匿名内部类是没有名字的,名字是null
每个类和成员都会有不同的修饰符(modifiers),包括注解,java.lang.reflect.Modifier
但不是所有注解都能通过反射得到
getDeclaredField()会返回包括private字段,但不包括继承的
getField()会返回public的字段,也包括继承的
字段和方法都是这样,但构造是没有继承这一说
private static void printMembers(Member[] mbrs, String s) {//这是一个通用的成员打印方法 out.format("%s:%n", s); for (Member mbr : mbrs) { if (mbr instanceof Field) out.format(" %s%n", ((Field)mbr).toGenericString()); else if (mbr instanceof Constructor) out.format(" %s%n", ((Constructor)mbr).toGenericString()); else if (mbr instanceof Method) out.format(" %s%n", ((Method)mbr).toGenericString()); } if (mbrs.length == 0) out.format(" -- No %s --%n", s); out.format("%n"); }
Class.newInstance()可以用来实例化一个对象,但调用的是无参的那个构造,没有无参构造会异常
所以应该用Constructor.newInstance(),可以传入参数
reflect包中有个Member接口,代表类中的成员,
实现它的类有Field,Method,和Constructor
按照最新规范,继承来的东西也属于成员,而构造并不属于成员,reflect包的这个实现是比较特殊的
另外三个类的父类是AccessibleObject 类,里面有方法setAccessible(true),和static方法
还有,反射里,对字段重新赋值的话,是没有自动装箱拆箱的
Field类里的setXX方法会降低很多性能,因为涉及到很多操作,不过在JRE看来效果是一样的
在没有setAccessible(true)之前,final的字段是不能修改的,但有了权限后的确可以修改
public field 都包括:
这个类中定义的
这个类的父类中定义的
这个类实现的接口中定义的
这个类实现的接口所继承的接口中的
public static void main(String... args) {//这样写跟以前是一样的,数组完全可以取代可变长度参数列表