对象的编译类型和运行类型
对象有编译类型和运行类型
1 |
Object obj = new Date(); |
编译类型:Object
运行类型(其实就是obj对象真实的类型):Date
需求:根据对象obj调用Date类中的一个方法,toLocaleString,如何来做?
obj.toLocaleString()代码在编译阶段去编译类型Object中检查是否有该方法,若没有,编译失败。
解决方案:强制转为obj为Date类型,前提:必须知道对象的真实类型是什么?
12 |
Date d = (Date)obj;d.toLocaleString(); |
万物皆对象:从概念分析类也是一种对象,新的问题,既然类是一种对象,那么谁又来描述该对象呢?而我们又说描述对象的类都是对象
元数据:metadata描述数据的描述数据
反射:得到元数据的行为,既然Class是对一切类共同功能行为和状态的抽象
那么Class重有应该有类具备的成员:
getPackage() 表示类的包
getSuperClass() 表示类的父类
getMethods() 类的方法
getField() 类的字段
Class类和Class实例
Class类:用于描述一切类/接口,枚举是一种类,注解是一种借口。
Class实例:就是指JVM中的一份字节码
问题:那Class实例到底表示的是哪一份字节码,为了明确区分出Class实例表示的是谁的字节码。Class类提供了泛型。
Class clz1 = Date.class // clz1表示的是Date的字节码
Class clz2 = String.class // clz2表示的是String的字节码
如何得到Class的实例?
1、类型.class(就是一份字节码)
2、Class.forName(String className);根据一个类的全限定名来构建Class对象
3、每一个对象都有getClass()方法,obj.getClss();返回对象的真实类型
9个预定义Class对象
基本的Java类型(boolean、byte、char、short、int、long、float和double)和关键字void也表示为Class对象
表示int的Class对象:Class clz = int.class;
表示boolean的Class对象:boolean.class;
表示void的Class对象:void.class;
所有的数据类型都有class属性,表示都是Class对象。
在八大基本数据类型的包装类中都有一个常量:TYPE
TYPE表示的是该包装类对应的基本数据类型的Class实例
如Integer.TYPE == int.class //true
Integer.class == int.class //false
数组的Class实例
String[] sArr = {“A”, “C”};
String[] sArr2 = {};
String[][] sArr3 = {};
int[] sArr4 = {};
表示数组的Class实例:
所有具有相同元素类型和维数的数组都共享该Class对象。
注意:和数组中的元素没有一点关系。
反射的实例
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
package 面试题; import java.util.Arrays; /** * Created by piqiu on 3/3/16. */public class User { private String name; private int age; private int sex; public User() { System.out.println("public User()"); } private User(String name) { this.name = name; System.out.println("private User(String name): " + name); } public User(String name, int age, int sex) { this.name = name; this.age = age; this.sex = sex; System.out.println("public User(String name, int age, int sex): " + name + " " + age + " " + sex); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } private void sayHello() { System.out.println("hello..."); } public void sayHi(String name) { System.out.println("hi..." + name); } public double getMoney(String name) { double money = 200.12; System.out.println("get money " + money + " for " + name); return money; } public static void staticMethod() { System.out.println("invoke static method..."); } public static int show(int... args) { int ret = 0; for (int i : args) { ret += i; } return ret; } public static void show2(String... args) { System.out.println(Arrays.toString(args)); } @Override public String toString() { return "User -> name: " + ((name == null)?"无名氏":name) + " age: " + ((age == 0)?"无年龄":age) + " sex: " + ((sex == 1)?"男":(sex == 2)?"女":"无性别"); }} |
1234567891011 |
package 面试题; import java.util.Map; /** * Created by piqiu on 3/7/16. */public class OOXX { public Map<String, Object> cache;} |
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
package 面试题; import java.lang.reflect.*;import java.util.Arrays;import java.util.List; /** * Created by piqiu on 3/3/16. */public class ReflectionDemo { private static Class<User> clz = User.class; private static Class<OOXX> ooxxClass = OOXX.class; private ReflectionDemo(){} public static void main(String[] args) throws Exception {// getConstructors();// getConstructor();// getDeclaredConstructors();// getDeclaredConstructor();// invokeConstructor();// getAllMethods();// getOneMethod();// invokeMethod();// invokeStaticMethod();// invokeVariableLengthMethod();// getAllFields();// invokeField();// getFieldValue();// getOtherAPI();// invokeGenericMethod(); getGenericFieldType(); } /** * 获取所有的【public修饰】的构造器 */ private static void getConstructors() { Constructor<?>[] constructors = clz.getConstructors(); for (Constructor c : constructors) { System.out.println(c); System.out.println(Arrays.toString(c.getParameterTypes())); System.out.println(c.getDeclaringClass()); } /** public 面试题.User(java.lang.String,int,int) [class java.lang.String, int, int] class 面试题.User public 面试题.User() [] class 面试题.User */ } /** * 根据构造器参数的Class类型获得对应的Constructor,只能获取【public修饰】的 * @throws NoSuchMethodException */ private static void getConstructor() throws NoSuchMethodException { Constructor<User> constructor1 = clz.getConstructor(); System.out.println(constructor1); // public 面试题.User() Constructor<User> constructor3 = clz.getConstructor(String.class, int.class, int.class); System.out.println(constructor3); // public 面试题.User(java.lang.String,int,int) } /** * 获取所有构造器,和访问权限无关 */ private static void getDeclaredConstructors() { Constructor<?>[] declaredConstructors = clz.getDeclaredConstructors(); for (Constructor c : declaredConstructors) { System.out.println(c); System.out.println(Arrays.toString(c.getParameterTypes())); System.out.println(c.getDeclaringClass()); } /** public 面试题.User(java.lang.String,int,int) [class java.lang.String, int, int] class 面试题.User public 面试题.User(java.lang.String) [class java.lang.String] class 面试题.User private 面试题.User() [] class 面试题.User */ } /** * 获取指定参数类型的构造器,和访问权限无关 * @throws NoSuchMethodException */ private static void getDeclaredConstructor() throws NoSuchMethodException { Constructor<User> declaredConstructor = clz.getDeclaredConstructor(String.class); System.out.println(declaredConstructor); // private 面试题.User(java.lang.String) } private static void invokeConstructor() throws Exception { // 这种newInstance方法只能作用于 public 的 无参构造方法,局限性太大 User user1 = clz.newInstance(); System.out.println(user1); Constructor<User> constructor1 = clz.getDeclaredConstructor(); User user2 = constructor1.newInstance(); System.out.println(user2); Constructor<User> constructor2 = clz.getDeclaredConstructor(String.class); constructor2.setAccessible(true); // 不加这句就实例化不了私有(private)的构造器 User user3 = constructor2.newInstance("呵呵"); System.out.println(user3); Constructor<User> constructor3 = clz.getDeclaredConstructor(String.class, int.class, int.class); User user4 = constructor3.newInstance("哈哈", 22, 2); System.out.println(user4); /** public User() User -> name: 无名氏 age: 无年龄 sex: 无性别 public User() User -> name: 无名氏 age: 无年龄 sex: 无性别 private User(String name): 呵呵 User -> name: 呵呵 age: 无年龄 sex: 无性别 public User(String name, int age, int sex): 哈哈 22 2 User -> name: 哈哈 age: 22 sex: 女 */ } /** * getDeclaredMethods和getMethods区别 * getMethods获得包括自身和继承过来的所有public方法 * getDeclaredMathods获取自身所有的方法,不包括继承的,和访问权限无关 */ private static void getAllMethods() { Method[] methods = clz.getDeclaredMethods(); for (Method m : methods) { System.out.println(m); } /** public java.lang.String 面试题.User.toString() public java.lang.String 面试题.User.getName() public void 面试题.User.setName(java.lang.String) public int 面试题.User.getAge() public void 面试题.User.setAge(int) public int 面试题.User.getSex() public void 面试题.User.setSex(int) private void 面试题.User.sayHello() public void 面试题.User.sayHi(java.lang.String) */ } /** * 只有通过方法签名才能找到唯一的方法 * 方法名 + 参数列表 * 得到私有方法必须使用 getDeclaredMethod */ private static void getOneMethod() throws NoSuchMethodException { Method method1 = clz.getMethod("sayHi", String.class); System.out.println(method1); // public void 面试题.User.sayHi(java.lang.String) Method method2 = clz.getDeclaredMethod("sayHello"); System.out.println(method2); // private void 面试题.User.sayHello() } private static void invokeMethod() throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException { Method method = clz.getMethod("getMoney", String.class); double money = (Double)method.invoke(clz.newInstance(), "benjamin"); System.out.println(money); /** public User() get money 200.12 for benjamin 200.12 */ } /** * 调用静态方法 * 如果方法是静态的,那么可以忽略指定的obj参数,将obj参数设为null即可 */ private static void invokeStaticMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Method method = clz.getMethod("staticMethod"); method.invoke(null); // invoke static method... } /** * 调用可变参数的静态方法 */ private static void invokeVariableLengthMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Method method = clz.getMethod("show", int[].class); int result = (Integer)method.invoke(null, new int[]{2, 4}); System.out.println(result); // 6 Method method2 = clz.getMethod("show2", String[].class); // 下面这么写会报Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments // 基本类型和引用类型不同,引用类型会自动解包 // 对于数组类型的引用类型的参数,底层会自动进行解包,为了解决该问题,我们使用Object的一维数组把实际参数包装起来 // method2.invoke(null, new String[]{"A", "B", "C"}); method2.invoke(null, new Object[]{new String[]{"A", "B", "C"}}); // [A, B, C] } /** * 获取所有字段,包括私有的 * 如果想只获取public的字段以及父类的public字段,使用getFields()方法 */ private static void getAllFields() { Field[] declaredFields = clz.getDeclaredFields(); for (Field field : declaredFields) { System.out.println(field); } /** private java.lang.String 面试题.User.name private int 面试题.User.age private int 面试题.User.sex */ } /** * 设置字段的值 */ private static void invokeField() throws NoSuchFieldException, IllegalAccessException, InstantiationException { Field ageField = clz.getDeclaredField("age"); ageField.setAccessible(true); Object obj = clz.newInstance(); ageField.set(obj, 12); System.out.println(obj); /** public User() User -> name: 无名氏 age: 12 sex: 无性别 */ } /** * 获取字段值 */ private static void getFieldValue() throws NoSuchFieldException, IllegalAccessException, InstantiationException { Field ageField = clz.getDeclaredField("age"); ageField.setAccessible(true); Object obj = clz.newInstance(); Object age = ageField.get(obj); System.out.println(age); /** public User() 0 */ } private static void getOtherAPI() { int modifiers = clz.getModifiers(); System.out.println(modifiers); // 1 System.out.println(Modifier.toString(modifiers)); // public System.out.println(clz.getName()); // 面试题.User System.out.println(clz.getSimpleName()); // User System.out.println(clz.getPackage()); // package 面试题 System.out.println(clz.getSuperclass()); // class java.lang.Object System.out.println(clz.isArray()); // false System.out.println(clz.isEnum()); // false } /** * 调用泛型参数的方法 */ private static void invokeGenericMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Class clz = Arrays.class; Method asListMethod = clz.getDeclaredMethod("asList", Object[].class); List result = (List) asListMethod.invoke(null, new Object[]{new Object[]{"A", "B", "C"}}); System.out.println(result); // [A, B, C] } /** * 得到泛型字段的类型 */ private static void getGenericFieldType() throws NoSuchFieldException { Field cacheField = ooxxClass.getDeclaredField("cache"); Type genericType = cacheField.getGenericType(); System.out.println(genericType); // java.util.Map<java.lang.String, java.lang.Object> ParameterizedType parameterizedType = (ParameterizedType) genericType; Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); System.out.println(Arrays.toString(actualTypeArguments)); // [class java.lang.String, class java.lang.Object] }} |