黑马程序员----------Java新特性反射 泛型

来源:互联网 发布:知乎日报接口 编辑:程序博客网 时间:2024/05/20 21:46

反射技术:

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;}}