cn.itcast.java.introspector.Demo1:用SUN提供内省API,操作JavaBean属性
package cn.itcast.java.introspector;
//狭义的JavaBean
public class Student {
public String getName() {
return "jack";
}
public int getAge() {
return 31;
}
public String getWC(){
return "WC";
}
}
package cn.itcast.java.introspector;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import org.junit.Test;
public class Demo1 extends Object{ // 因为Object类中有名为“class”的属性
@Test
public void test1() throws Exception{
Student s = new Student(); // 也可以使用反射的方法获得Student对象;
//pd引用Student的name属性
PropertyDescriptor pd = new PropertyDescriptor("name",Student.class); // 参数一:属性名, 参数二:属性所属的类
//m = setName()
Method m = pd.getWriteMethod(); // 内省一定是站在反射的高度上看问题;
//s.setName("berry")
m.invoke(s,"berry");
//s.getName()
m = pd.getReadMethod();
String returnValue = (String) m.invoke(s,null); // invoke()默认返回Object对象
System.out.println("returnValue="+returnValue);
// -------- 这就是内省API操作javaBean;(站在反射的角度)
}
// 解决一个类有有哪些属性, 个数
@Test
public void test2() throws Exception{
//BeanInfo表示该Student对象所有的属性情况(所有的属性集合)
BeanInfo bi = Introspector.getBeanInfo(Student.class);
//取得Student对象所有属性集合
PropertyDescriptor[] pds = bi.getPropertyDescriptors(); // 单个属性getPropertyDescriptor()
for(PropertyDescriptor pd : pds){
System.out.println(pd.getName());
}
}
}
1) 内省,一定是站在“反射”的高度,
2)PropertyDescriptor就代表了某个属性,比如name属性,和它的setter和getter方法
PropertyDescriptor[] pds = bi.getPropertyDescriptors(); 就代表bi这个javabean的所有属性及属性对应的setter和getter方法
3) 内省API(SUN公司开发)站在反射角度
1) 在操作JavaBean时,即对JavaBean进入setter和getter操作时
2)属性和getXxxxx()有关,同时getXxxxx()必须有返回值
没有对应的 getXxxxx()的只能叫做字段,不能成为属性,
3)任何一个JavaBean都有一个class属性,来自于Object类。
总结:
sun公司的内省的作用:操作javabean的存取方法; 取得某个javabean的属性的名字,和属性的个数
*3 BeanUtils框架/工具(APACHE开源组织开发)
因为sun公司的内省API操作javabean的属性不太方便,所以这里有了“BeanUtils框架”新的替代它;
需要自己下载commons-beanutils-1.8.0-sources包
在day02目录下 -- 建立lib文件夹 -- 拷贝commons-beanutils-1.8.0.jar
选中lib中的commons-beanutils-1.8.0.jar -- 右键 -- add to build path
commons-beanutils-1.8.0.jar包依赖于commons-logging.jar这个日志包
选中lib中的commons-logging.jar -- 右键 -- add to build path
1)BeanUtils框架能够完成内省API的一切功能,而且优化
2)BeanUtils框架能够对String<->8种基本类型自动转化
3)BeanUtils框架自定义转换器:
ConvertUtils.register( 转换规则 ,目标对象的Class)
Student s = new Student();
BeanUtils bu = new BeanUtils();
/*
//向BeanUtils框架注册自定义的转换器(String -> java.util.Date) , 项目中可能会有各种各样的类型转换,就可以使用这个模式;
//因为BeanUtils默认是不可以将String类型转成Date类型; BeanUtils只能完成String和基本类型的转换;
ConvertUtils.register(new Converter(){
public Object convert(Class clazz, Object type) {
//参数一:java.util.Date.class(目标类型)
//参数二:是传入的参数类型,即java.lang.String
String strBirthday = (String) type; // Object强转为String;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");// SimpleDateFormat就具有Date和String相互转换的功能
try {
return sdf.parse(strBirthday);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
},java.util.Date.class);
bu.setProperty(s,"birthday","2011-10-09"); // 自定义转换器要在此句话之前;
String birthday = bu.getProperty(s,"birthday");
System.out.println("birthday="+new Date(birthday).toLocaleString());
4) 向BeanUtils框架注册自定义转换器必须放在bu.setProperty()代码之前
5) 使用BeanUtils内置String->Date的转换器:
ConvertUtils.register(new DateLocaleConverter(),java.util.Date.class);
6) 绑定源码,--- 按住Ctrl,并点击 Collections -- attache -- External folder -- C盘下的jdk目录 -- 选中src.zip -- 确定
7) 查看源码时,如何想看某个类都有哪些方法 -- IDE -- Window -- show view -- outline -
cn.itcast.java.beanutils.Demo1:用APACHE提供Bean工具API操作JavaBean类属性
package cn.itcast.java.beanutils;
import java.util.Date; // 注意一遇见Date,就导入这个包;
//狭义JavaBean
public class Student {
private String name;
private int age;
private Date birthday;
public Student(){}
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 Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
package cn.itcast.java.beanutils;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import org.junit.Test;
public class Demo1 {
@Test
public void test1() throws Exception{
Student s = new Student();
BeanUtils bu = new BeanUtils();
/*
//向BeanUtils框架注册我们自定义的转换器(String -> java.util.Date) , 项目中可能会有各种各样的类型转换,就可以使用这个模式;
//因为BeanUtils默认是不可以将String类型转成Date类型; BeanUtils只能完成String和基本类型的转换;
ConvertUtils.register(new Converter(){
public Object convert(Class clazz, Object type) {
//参数一:java.util.Date.class(目标类型)
//参数二:是传入的参数类型,即java.lang.String
String strBirthday = (String) type; // Object强转为String;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");// SimpleDateFormat就具有java.util.Date和String相互转换的功能
try {
return sdf.parse(strBirthday);
} catch (Exception e) {
e.printStackTrace();
return null;
}
// 注意这里是不能抛的,只能catch; 自己体会原因
}
},java.util.Date.class);
// 这里Converter是一个接口,在基础班中讲过的,当某个接口中只有一个或者两个为实现的方法时;我们可以使用匿名内部类的方式实现类
bu.setProperty(s,"birthday","2011-10-09"); // 自定义转换器要在此句话之前;
String birthday = bu.getProperty(s,"birthday");
System.out.println("birthday="+new Date(birthday).toLocaleString());
*/
ConvertUtils.register(new DateLocaleConverter(),java.util.Date.class); // 使用BeanUtils框架自带的String -> java.util.Date转换器DateLocaleConverter;
bu.setProperty(s,"name","张三");
bu.setProperty(s,"age","31"); // 本来age是int型的, 这里传入的是String类型; --- BeanUtils框架能够对String<->基本类型自动转化
bu.setProperty(s,"birthday","2011-10-09"); // BeanUtils默认不能将String类型转成Date类型; Date不是基本类型;
String name = bu.getProperty(s,"name");
String age = bu.getProperty(s,"age");
String birthday = bu.getProperty(s,"birthday");
System.out.println("name="+name);
System.out.println("age="+age);
// System.out.println("birthday="+new Date(birthday).toLocaleString()); //这句运行会报错
System.out.println("birthday="+birthday);
// System.out.println("birthday=" + birthday); 默认等价于 System.out.println("birthday=" + birthday.toString() )
}
}
*4 泛型
1) 在编译时,由编译器约束放入集合中的类型
2)在运行时,编译器会擦除原泛型类型
3)泛型两边要么都不使用约束,要么二边约束一致类型,同时二边必须使用引用类型
4)为了与JDK1.4兼容,泛型可以一边有约束,一边无约束
思考:不利用中间变量,将二个数交互
5)当一个类中出大量的泛型方法或属性/字段,此时可以将该类作成泛型类
6)如果使用泛型通配符,只能获取与泛型具体类型无关的信息,例如:长度。
7)有两个类,初学者一定要注意:Collections和Arrays, 重点掌握
Collections.reverse(stringList); // 现成的reverse方法; 还有sort方法,swap,
// 有二个类,初学者一定要注意:Collections和Arrays, 提供了很多已有的工具
cn.itcast.java.generic.Demo1:传统方式下运行时对集合内容安全检查,统计各类型变量的数量
package cn.itcast.java.generic;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
//传统方式下,对集合判断
public class Demo1 {
public static void main(String[] args) {
List<Boolean> list = new ArrayList<Boolean>();
list.add(true);
list.add(false);
for(Boolean b : list){
System.out.println(b);
// System.out.println(b.toString()); 和上面等价;
}
/*
int stringNum = 0,integerNum=0,booleanNum = 0;
List list = new ArrayList();
list.add("jack");
list.add("marry");
list.add("sisi");
list.add(100);
list.add(200);
list.add(true);
Iterator it = list.iterator();
while(it.hasNext()){
Object obj = it.next();
if(obj instanceof String){
stringNum++;
}else if(obj instanceof Integer){ // 判断obj引用是是否为Integer类型;
integerNum++;
}else if(obj instanceof Boolean){
booleanNum++;
}
}
System.out.println("stringNum="+stringNum);
System.out.println("integerNum="+integerNum);
System.out.println("booleanNum="+booleanNum);
*/
}
}
cn.itcast.java.generic.Demo3:使用泛型方法交换二元素
package cn.itcast.java.generic;
public class Demo3 {
public static void main(String[] args) {
Boolean numA = false;
Boolean numB = true;
System.out.println("numA" + numA);
System.out.println("numB" + numB);
swap(numA,numB); // 这里都是把numA和numB的副本传递了过去;
}
//泛型方法(通用方法)
public static <T> void swap(T numA,T numB) { // <T>表示声明T是一种类型;
T temp = numA;
numA = numB;
numB = temp;
System.out.println("numA" + numA);
System.out.println("numB" + numB);
}
/*public static <T,V> V getValue(K key){
return map.get(key);
}
*/
}
cn.itcast.java.generic.Demo4:泛型通配符
package cn.itcast.java.generic;
// 泛型类 -- 当一个类中有大量的泛型方法,或者泛型属性
public class Apple<T> {
/*
public void buy(Integer num){
System.out.println("苹果:" + num + "个");
}
public void buy(Double price){
System.out.println("苹果:" + price + "元");
}
*/
//泛型方式
public void buy(T t){
System.out.println("苹果:" + t + "信息");
}
}
package cn.itcast.java.generic;
public class Demo4 {
public static void main(String[] args) {
/*
Apple a1 = new Apple();
a1.buy(10);
a1.buy(5.5);
*/
Apple<Integer> a1 = new Apple<Integer>();
a1.buy(10);
Apple<Double> a2 = new Apple<Double>();
a2.buy(5.5);
}
}
cn.itcast.java.generic.Demo5:有限制的通配符
package cn.itcast.java.generic;
import java.util.ArrayList;
import java.util.List;
//泛型通配符?号的使用
public class Demo5 {
public static void main(String[] args) {
List<Boolean> booleanList = new ArrayList<Boolean>();
booleanList.add(true);
booleanList.add(false);
show(booleanList);
/*Vector<? extends Number> x = new Vector<Integer>(); // 限定通配符的上界 , 因为Number是Integer的父类
Vector<? super Integer> x = new Vector<Number>(); // 限定通配符的下界
*/
// String在API文档中定义的是final, 也就是String类任何人都无法继承它;
}
public static void show(List<?> list) { // List<?> list
System.out.println("集合长度为:" + list.size());
for(Object o : list){ // 这里一定要写Object o,不能写具体类型;
System.out.println(o);
}
}
}
1) 我自己写了一个show()方法,但是我们不知道别的人穿过来的list中放的数据的具体类型
就可以使用:List<?> list,来接收参数
2) 遍历这个List<?> list时,就只能用Object来保存临时元素