黑马程序员----------Java新特性反射 泛型
2013-08-31 09:11
676 查看
反射技术:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,
都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
简单一句话:反射技术可以对类进行解剖。
如何获取Class对象呢?
方式一:
通过对象的getClass方法进行获取。
麻烦在于每次是不是都需要具体的类和该类的对象,以及调用getClass方法。
方式二:
任何数据类型都具备着一个静态的属性class,这个属性直接获取到该类型的对应Class对象。
比第一种简单,不用创建对象,不用调用getClass方法。
但是还是要使用具体的类,和该类中的一个静态属性class完成。
方式三:
这种方式较为简单,只要知道的类的名称即可。
不需要使用该类,也不需要去调用具体的属性和行为。
就可以获取到Class 对象了
获取Class对象的三种方式:
如果指定的类中没有空参数的构造函数。
或者要创建的类对象需要通过指定的构造函数进行初始化。
这时怎么办呢?这时就不能使用newInstance方法了。
既然要通过指定的构造函数进行对象的初始化。
就必须先获取这个构造函数。
对于一个Javabean可以通过实例化的形式得到对象,也可以通过反射的原理得到对象,并且给对象赋值
最基本的反射方法获取类字节码通过getClass方法获取
Student的类
数组的的反射
1. 具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
2. 代表数组的Class实例对象的getSuperClass()方法,返回的父类为Object类对应的Class
3. 基本类型的一维数组可以被当做Object类型使用,不能作为Object[]类型使用,不能当做Object[]类型使用,非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类使用
4. 注意区别 Array.asList()方法处理int[]和String[]时的差异
5. Array工具类用于完成对数组的反射操作
JDK1.5以后出现的技术:泛型。
泛型的由来:
1,泛型的出现将运行时期的问题ClassCastException 转移到了编译时期变成了编译失败。
2,泛型的出现避免了类型强制转换的麻烦。
3,泛型技术是用在编译时期的技术。
4,泛型的出现提高了类型的安全性。
泛型的限定:
明确具体类型代表一个类型。
明确?代表所有类型。
下限:? super E:接收E类型或者E的父类型。
当一个类要操作的引用数据类型不确定的时候,可以将该类型定义一个形参。
用到的这类时,有使用者来通过传递类型参数的形式,来确定要操作的具体的对象类型。
意味着在定义这个类时,需要在类上定义形参。用于接收具体的类型实参。
这就是将泛型定义在类上。这就是泛型类。
泛型是提供给java编译器使用的,让编译器挡住程序的非法输入,对于参数化的泛型,getClass返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的信息,只要跳过编译器,就可以往泛型集合中加入其它类型的数据,如:用反射得到集合,再调用其add方法即可。
collection3.getClass().getMethod("add",Object.class).invoke(collection3, "abc");
ArrayList<E>类定义和ArrayList<Integer>类引用中涉及的术语:
1、整个ArrayList<E>称为泛型类型
2、ArrayList<E>中E称为类型变量或类型参数
3、整个ArrayList<Integer>称为参数化的类型
4、ArrayList<Integer>中的Integer叫类型参数的实例或实际类型参数
5、ArrayList<Integer>中的<>念typeof
6、ArrayList称为原始类型
泛型的例子
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,
都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
简单一句话:反射技术可以对类进行解剖。
如何获取Class对象呢?
方式一:
通过对象的getClass方法进行获取。
麻烦在于每次是不是都需要具体的类和该类的对象,以及调用getClass方法。
方式二:
任何数据类型都具备着一个静态的属性class,这个属性直接获取到该类型的对应Class对象。
比第一种简单,不用创建对象,不用调用getClass方法。
但是还是要使用具体的类,和该类中的一个静态属性class完成。
方式三:
这种方式较为简单,只要知道的类的名称即可。
不需要使用该类,也不需要去调用具体的属性和行为。
就可以获取到Class 对象了
获取Class对象的三种方式:
public class ReflectDemo { public static void main(String[] args) throws ClassNotFoundException { getObject_3(); } public static void getObject_3() throws ClassNotFoundException { String className = "com.itheima.bean.Person"; Class clazz = Class.forName(className); System.out.println(clazz); } //方式二: public static void getObject_2() { Class clazz = Person.class; } //方式一。 public static void getObject_1(){ Person p = new Person(); Class clazz = p.getClass(); Person p1 = new Person(); Class clazz1 = p1.getClass(); System.out.println(p==p1); System.out.println(clazz==clazz1); }
如果指定的类中没有空参数的构造函数。
或者要创建的类对象需要通过指定的构造函数进行初始化。
这时怎么办呢?这时就不能使用newInstance方法了。
既然要通过指定的构造函数进行对象的初始化。
就必须先获取这个构造函数。
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, Exception { createNewObj_2(); } public static void createNewObj_2() throws Exception { /* * 如果指定的类中没有空参数的构造函数。 * 或者要创建的类对象需要通过指定的构造函数进行初始化。 * 这时怎么办呢?这时就不能使用newInstance方法了。 * * 既然要通过指定的构造函数进行对象的初始化。 * 就必须先获取这个构造函数。 * */ String className = "cn.itcast.bean.Person"; Class clazz = Class.forName(className); //获取指定类中的指定的构造函数。 Constructor constructor = clazz.getConstructor(String.class,int.class); //创建对象。对象的建立都需要构造函数的初始化。 怎么创建对象可以通过构造器对象完成。 Object obj = constructor.newInstance("lisi",20); System.out.println(obj); } /* * 通过Class创建对象。 */ public static void createNewObj() throws ClassNotFoundException, InstantiationException, IllegalAccessException{ /* * 1,查找并加载Person.class文件进内存,并将该文件封装成Class对象。 * 2,在依据Class对象创建该类具体的实例。 * 3,调用构造函数对对象进行初始化。 */ /* * 1,查找并加载指定名字的字节码文件进内存,并被封装成Class对象。 * 2,通过Class对象的newInstance方法创建该Class对应的类的实例。 * 3,调用newInstance()方法会去使用该类的空参数构造函数进行初始化。 * */ String className = "cn.itcast.bean.Person"; Class clazz = Class.forName(className); Object obj = clazz.newInstance(); }
对于一个Javabean可以通过实例化的形式得到对象,也可以通过反射的原理得到对象,并且给对象赋值
最基本的反射方法获取类字节码通过getClass方法获取
Student的类
import java.util.*; public class Student { private String name; private int age; private String sex; private Date birthday; public Student() { } public Student(String name, int age, Date birthday) { this.name = name; this.age = age; this.birthday = birthday; } 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 String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
import java.util.List; import java.lang.reflect.Field; import java.util.Date; import java.text.SimpleDateFormat; import java.util.ArrayList; public class ReflectTest { public static void main(String[] args) throws RuntimeException, Exception { // 反射构造方法设定类中的值 Student s = Student.class.getConstructor( new Class[] { String.class, int.class, Date.class }) .newInstance(new Object[] { "李四", 32, new Date() }); System.out.println(s.getName() + "::" + s.getAge() + "::" + s.getBirthday()); // 反射实例化对象 Student stu = Student.class.newInstance(); //得到对象中所有field属性 //不用getMethods,因为javabean中还有其它继承至Object的方法 Field[] fieldName = stu.getClass().getDeclaredFields(); for (Field f : fieldName) { String name = f.getName(); //得到为set+属性的方法名 String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1); //直接给方法注入参数 if (int.class == f.getType()) { stu.getClass().getMethod(methodName, f.getType()).invoke(stu, 19); } if (String.class == f.getType()) { stu.getClass().getMethod(methodName, f.getType()).invoke(stu, "张三"); } if (Date.class == f.getType()) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date d = (Date) sdf.parse("1988-5-5"); stu.getClass().getMethod(methodName, f.getType()) .invoke(stu, d); } } System.out.println(stu.getName() + "::" + stu.getAge() + "::" + stu.getBirthday()); } }
数组的的反射
1. 具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
2. 代表数组的Class实例对象的getSuperClass()方法,返回的父类为Object类对应的Class
3. 基本类型的一维数组可以被当做Object类型使用,不能作为Object[]类型使用,不能当做Object[]类型使用,非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类使用
4. 注意区别 Array.asList()方法处理int[]和String[]时的差异
5. Array工具类用于完成对数组的反射操作
private static void printObject(Object obj) { Class clazz = obj.getClass(); if(clazz.isArray()){ int len = Array.getLength(obj); for(int i=0;i<len;i++){ System.out.println(Array.get(obj, i)); } }else{ System.out.println(obj); } }泛型:
JDK1.5以后出现的技术:泛型。
泛型的由来:
1,泛型的出现将运行时期的问题ClassCastException 转移到了编译时期变成了编译失败。
2,泛型的出现避免了类型强制转换的麻烦。
3,泛型技术是用在编译时期的技术。
4,泛型的出现提高了类型的安全性。
泛型的限定:
明确具体类型代表一个类型。
明确?代表所有类型。
下限:? super E:接收E类型或者E的父类型。
当一个类要操作的引用数据类型不确定的时候,可以将该类型定义一个形参。
用到的这类时,有使用者来通过传递类型参数的形式,来确定要操作的具体的对象类型。
意味着在定义这个类时,需要在类上定义形参。用于接收具体的类型实参。
这就是将泛型定义在类上。这就是泛型类。
泛型是提供给java编译器使用的,让编译器挡住程序的非法输入,对于参数化的泛型,getClass返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的信息,只要跳过编译器,就可以往泛型集合中加入其它类型的数据,如:用反射得到集合,再调用其add方法即可。
collection3.getClass().getMethod("add",Object.class).invoke(collection3, "abc");
ArrayList<E>类定义和ArrayList<Integer>类引用中涉及的术语:
1、整个ArrayList<E>称为泛型类型
2、ArrayList<E>中E称为类型变量或类型参数
3、整个ArrayList<Integer>称为参数化的类型
4、ArrayList<Integer>中的Integer叫类型参数的实例或实际类型参数
5、ArrayList<Integer>中的<>念typeof
6、ArrayList称为原始类型
泛型的例子
public class GenericTest { public static void main(String[] args) throws Exception { ArrayList<String> collection2 = new ArrayList(); collection2.add("abc"); String str = collection2.get(0); Constructor constructor1 = String.class .getConstructor((StringBuffer.class)); String str2 = (String) constructor1 .newInstance(new StringBuffer("abc"));// 需要产生同样类型的对象 System.out.println(str2); ArrayList<Integer> collection3 = new ArrayList(); System.out.println(collection3.getClass() == collection2.getClass()); collection3.getClass().getMethod("add", Object.class) .invoke(collection3, "abc"); System.out.println(collection3.get(0)); printCollection(collection3); HashMap<String, Integer> maps = new HashMap<String, Integer>(); maps.put("ytang", 20); maps.put("yiyi", 23); maps.put("chaox", 24); Set<Map.Entry<String, Integer>> entrySet = maps.entrySet(); for (Map.Entry<String, Integer> entry : entrySet) { System.out.println(entry.getKey() + ":" + entry.getValue()); } add(3, 5); Number x1 = add(3.5, 3); Object str6 = add(3, "abc"); swap(new String[] { "abc", "xyz", "itcast" }, 1, 2); } public static void printCollection(Collection<?> collection) { System.out.println(collection.size()); for (Object obj : collection) { System.out.println(obj); } } public static <T> void swap(T[] a, int i, int j) { T tmp = a[i]; a[i] = a[j]; a[j] = tmp; } private static <T> T add(T x, T y) { return null; } }
相关文章推荐
- 黑马程序员——java高新技术(新特性、反射、泛型)
- 黑马程序员--Java基础加强--13.利用反射操作泛型II【TypeVariable】【GenericArrayType】【WildcardType】【Type及其子接口的来历】【个人总结】
- 黑马程序员 Java高新技术-jdk1.5深入反射和泛型
- 黑马程序员——Java1.5新特性之泛型
- 01-java基础加强,eclipse工具使用,快捷键,断点调试,单元测试,jdk5新特性,增强for循环,集合map,list,可变参数,枚举,反射,泛型
- 黑马程序员--Java基础加强--14.利用反射操作泛型III【解析关于泛型类型的细节信息的获取方法】【Method与泛型相关的方法】【个人总结】
- 黑马程序员 高新技术——JAVA1.5新特性及反射
- 黑马程序员-java基础加强-JDK1.5新特性-泛型
- 黑马程序员_java1.5新特性泛型集合
- 黑马程序员________Java集合Map及其JDK1.5新特性泛型机制的学习笔记
- 黑马程序员 Java高新技术-jdk1.5新特性和反射基础
- 黑马程序员---Java基础加强---JDK1.5新特性:泛型
- 黑马程序员————java基础--------JDK1.5新特性之泛型、自动拆装箱、增强for、静态导入、可变参数
- 黑马程序员--Java基础加强--15.利用反射操作泛型IV【通过反射Method解析泛型方法思路】【通过Method对四种Type子接口类型进行解剖】【使用递归对任意复合泛型类型进行彻底解剖】【个人
- 黑马程序员--Java基础加强--17.利用反射操作泛型VI【泛型类型变量的语义】【GenericDeclaration接口】【泛型接口TypeVariable】【通过Class反射解析泛型类】
- 黑马程序员——java5特性之枚举和泛型概述
- 黑马程序员——Java高新技术——JDK1.5版本的新特性泛型
- 黑马程序员_Java语言_反射及jdk新特性
- 黑马程序员——Java基础---泛型和反射
- 黑马程序员--Java基础加强--12.利用反射操作泛型I【与反射+泛型相关的接口类型综述】【Type】【ParameterizedType】【个人总结】