您的位置:首页 > 职场人生

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

2013-08-31 09:11 676 查看
反射技术:
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;
}
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐