首页 > 编程 > Java > 正文

java基础加强(枚举,反射,增强for循环,可变参数,自动拆箱装箱,内省)

2019-11-06 07:53:05
字体:
来源:转载
供稿:网友

一  Eclipse的使用和程序的断点调试

错误:Bad version number in .class file-编译器的版本过高,运行环境版本过低(如果编译器的版本是低的,而运行环境是高的,不会出问题)

解决方案,1 编译环境变低 2运行环境变高

改变运行环境:工程右键,选择属性(PRoperties)选择java Build Path->Libraries

改变编译环境:工程右键,选择属性(Properties)选择java Compiler

断点调试

在想要停顿的地方双击当前行的最前面

然后Debug As

快捷键:F5:跳入(step into)

F6:跳过(step over),跳过当前行代码

F7:跳出(step return)

观察变量或表达式的值,点击变量,选择Watch

drop to frame 回跳,跳到当前方法的最上面

resume 跳到下一个断点(如果没有下一个断点,则运行完整个程序)

清除所有断点:Breakpoints视图

二  eclipse常用快捷键

配置快捷键

windows->Prefernces->搜索框输入k->点击Keys

内容提示:Alt+/

快速修复:Ctrl+1

导包:Ctrl+shift+O

格式化代码块:Ctrl+shift+F

向前向后:Alt+方向键

添加注释:Ctrl+shift+/

除去注释:Ctrl+shift+/

F2:查看方法说明

重置透视图:windows->Reset Perspective

更改为大写:Ctrl+Shift+X

更改为小写:Ctrl+Shift+Y

复制行Ctrl+Alt+向下键(有些不能用)

查看类的继承关系:Ctrl+T

查看源代码

1

2  ctrl +shift+T

Ctrl+Shift+L查看所有快捷键

三  junit测试框架

public class Person {	public void run(){		System.out.println("跑");	}	public String eat(){		System.out.println("吃");		return "1";	}}

import org.junit.After;import org.junit.AfterClass;import org.junit.Before;import org.junit.BeforeClass;import org.junit.Test;public class PersonTest {	Person p;	// 提取测试方法所需要的外界资源	// before after 每个测试方法都运行	// beforeClass afterClass 在类加载的时候运行,只运行一边	@Before	public void before() {		p = new Person();	}	@BeforeClass	public static void beforeClass() {		System.out.println("beforeClass");	}	@Test	public void testRun() {		p.run();	}	// 释放外界资源	@After	public void after() {		System.out.println("after");	}	@AfterClass	public static void afterClass() {		System.out.println("afterClass");	}}

import junit.framework.Assert;import org.junit.Test;public class PersonTest1 {	public void testRun() {		Person p=new Person();		p.run();	}	@Test	public void testEat() {		Person p=new Person();		//断言		//判断测试是否通过		//Assert.assertEquals("2", p.eat());		Assert.assertEquals(new int []{1,1}, new int[]{1,2});			}}

四  java5的静态导入和自动装箱拆箱

静态导入用于简化程序对类静态属性和方法的调用

语法:import static 包名.类名.静态属性|静态方法|*

例:import static java.lang.System.out

import static java.lang.Math.*

自动装箱:指开发人员可以把一个基类数据类型直接赋值给对应的包装类

自动拆箱:指开发人员可以把一个包装类对象直接赋值给对应的进本数据类型

典型应用:

List list =new ArrayList();

list.add(1);

int j=(Interger)list.get(0);

五  增强for循环

引入增强for循环的原因,在JDK5以前的版本中,遍历数组或集合中的元素,需先获得数组的长度或集合的迭代器,比较麻烦

JDK5中定义了一种新的语法——增强for循环,以简化此类操作。增强for循环只能用在数组,或实现Iterable接口的集合类上。

语法格式:

for(变量类型 变量 :需迭代的数组或集合){

}

import java.util.HashMap;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.List;import java.util.ArrayList;import java.util.Map;import java.util.Map.Entry;import java.util.Set;import org.junit.Test;/* * 增强for */public class StrongFor {	@Test	public void Test1() {		int arr[] = { 1, 2, 3 };		for (int num : arr) {			System.out.println(num);		}	}	@Test	public void Test2() {		List list = new ArrayList();		list.add(1);		list.add(2);		list.add(3);		for (Object obj : list) {			int i = (Integer) obj;			System.out.println(i);		}	}	@Test	public void Test3() {		Map map=new HashMap();		map.put("1", "aaa");		map.put("2", "bbb");		map.put("3", "ccc");		//传统方式1		Set set =map.keySet();		Iterator it=set.iterator();		while (it.hasNext()){			String key= (String) it.next();			String value=(String) map.get(key);			System.out.println(key+"="+value);		}			}	@Test	public void Test4() {		Map map=new LinkedHashMap();//LinkedHashMap()正序。常用语购物车		map.put("1", "aaa");		map.put("2", "bbb");		map.put("3", "ccc");		//传统方式2		Set set =map.entrySet();		Iterator it=set.iterator();		while (it.hasNext()){			Map.Entry entry=(Entry)it.next();			String key=(String) entry.getKey();			String value=(String) entry.getValue();			System.out.println(key+"="+value);		}			}	@Test	public void Test5() {		Map map=new LinkedHashMap();//LinkedHashMap()正序。常用语购物车		map.put("1", "aaa");		map.put("2", "bbb");		map.put("3", "ccc");		//增强for取Map的第一种方法				for(Object obj:map.keySet()){//把map集合转换成set集合			String key=(String)obj;			String value =(String) map.get(key);			System.out.println(key+"="+value);		}	}			@Test	public void Test6() {		Map map=new LinkedHashMap();//LinkedHashMap()正序。常用语购物车		map.put("1", "aaa");		map.put("2", "bbb");		map.put("3", "ccc");		//增强for取Map的第二种方法		for(Object obj :map.entrySet()){			Map.Entry entry=(Entry)obj;			String key=(String) entry.getKey();			String value=(String) entry.getValue();			System.out.println(key+"="+value);		}		Set set =map.entrySet();					}	//使用增强for需要注意的几个问题:增强for只适合取数据,要修改数组或集合中的数据,使用传统方式	@Test	public void Test7() {		int arr[]={1,2,3};	for(int i:arr){		i=10;	}	System.out.println(arr[0]);	System.out.println(arr[1]);	System.out.println(arr[2]);		List list =new ArrayList();		list.add("1");		for(Object obj:list){			obj="10";		}		System.out.println(list.get(0));	}}

六  可变参数

测试JDK中具有可变参数的类Array.asList().分别传多个参,传数组,传数组又传参的情况

注意:传入基本数类型数组的问题

从JDK5开始,java允许为方法定义长度可变的参数,

语法:public void foo(int...args){

}

注意事项:

调用可变参数的方法时,编译器将自动创建一个数组保存传递给方法的可变参数,因此,程序员可以在方法体中以数组的形式访问可变参数

可变参数只能处于参数列表的最后,所以一个方法最多只能有一个长度可变的参数。

import java.util.Arrays;import java.util.List;import org.junit.Test;public class ChangeableArgs {		@Test	public void testSum(){		int arr[]={1,2,3,4,5};		sum(arr);		sum(1,2,3,4,5,6);	}	public void sum(int...num){		//可变参数看成数组		int sum=0;		for(int i:num){			sum+=i;		}		System.out.println(sum);	}	@Test	public void testAa(){		aa(1,2,3,4,5);	}	public void aa(int ...nums){			}	@Test	public void bb(){		List list=Arrays.asList("a","b","c");		System.out.println(list);		String arr[]={"1","2","3","4"};		list =Arrays.asList(arr);		System.out.println(list);				//需要的是对象,所以把数组当成了对象,输出的结果不是预期的		int nums[]={1,2,3}; //把int改成Integer就可以		list=Arrays.asList(nums);		System.out.println(list);	}}

七  什么是枚举类型和定义枚举

为什么需要枚举?

一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,此类问题在JDK5以前采用自定义带有枚举功能的类解决,java5以后可以直接使用枚举予以解决

JDK5新增的enum关键字用于定义一个枚举类

八  定义枚举的构造函数,方法和字段

package cn.pack;import org.junit.Test;public class EnumerationTest {	@Test	public void test(){		print(Grade.B);	}		public void print(Grade g){  //输出成绩A,B,C,D,E		String value =g.getValue();		System.out.println(value);//89-80	}}/*class Grade{	private Grade(){	}	public static final Grade A=new Grade(); 	public static final Grade B=new Grade();	public static final Grade C=new Grade();	public static final Grade D=new Grade();	public static final Grade E=new Grade();}*///==//如何定义枚举的构造函数,方法和字段,去封装更多的信息enum Grade{ //class  A 100-90 B 89-80 C 79-70  D 69-60	A("100-90"),B("89-80"),C("79-70"),D("69-60"),E("59-0");//Object单独写A,B,C,D,E;会报错,因为没有了默认的构造函数	private String value;//封装每个对象对应的分数	//声明了一个有参的构造函数,	private Grade(String value){		this.value=value;	}	public String getValue(){		return this.value;	}}

九  定义抽象方法的枚举

import org.junit.Test;public class AbstractEnumeration {	@Test	public void test() {		print(GradeToo.B);	}	public void print(GradeToo g) { // 输出成绩A,B,C,D,E		String value = g.getValue();		System.out.println(value);// 89-80	}}/* * class Grade{ private Grade(){ } public static final Grade A=new Grade(); * public static final Grade B=new Grade(); public static final Grade C=new * Grade(); public static final Grade D=new Grade(); public static final Grade * E=new Grade(); } */// ==// 如何定义枚举的构造函数,方法和字段,去封装更多的信息enum GradeToo { // class A 100-90 B 89-80 C 79-70 D 69-60	A("100-90") {		public String localeVlaue() {			return "优";		}	},	B("89-80") {		public String localeVlaue() {			return "良";		}	},	C("79-70") {		public String localeVlaue() {			return "一般";		}	},	D("69-60") {		public String localeVlaue() {			return "差";		}	},	E("59-0") {		public String localeVlaue() {			return "不及格";		}	};// Object单独写A,B,C,D,E;会报错,因为没有了默认的构造函数	private String value;// 封装每个对象对应的分数	// 声明了一个有参的构造函数,	private GradeToo(String value) {		this.value = value;	}	public String getValue() {		return this.value;	}	public abstract String localeVlaue();}

十  枚举的常用方法和其它细节

枚举类具有如下特性:

枚举类也是一种特殊形式的java类

枚举类中声明的每一个枚举值代表枚举类的一个实例对象

与java中的普通类一样,在声明枚举类时,也可以声明属性,方法和构造函数,但枚举类的构造函数必须为私有的(如果为公有的,别人就可以创建实例了)

枚举类也可以实现接口,或继承抽象类

JDK5中扩展了switch语句,他除了可以接收int ,byte,char,short外,它还可以接受一个枚举类型

若枚举类型只有一个枚举值,则可以当作单态设计模式(保存类对象在内存中始终只有一个)使用

java中声明的枚举类,均是java.lang.Enum类的孩子,他继承了Enum类的所有方法,常用方法:

name()

ordinal()

valueof(class enumClass,String name)

values()此方法虽然在JDK文档中查不到,但每个枚举类都具有该方法,它用于遍历枚举的所有枚举值

实际开发中,用户提交的大部分都是String类型,如果用户提交的数据正确,就能转换成枚举

//测试枚举类的常用方法	@Test	public void test1(){		System.out.println(Grade.C.name());		System.out.println(Grade.C.ordinal());		String str="B";		Grade g=Grade.valueOf(str);		System.out.println(g);				Grade gs[]=Grade.values();		for(Grade g1:gs){			System.out.println(g1);		}	}

十一  反射技术概述

(做框架必须会的技术)

反射就是加载类,并解剖出类的各个组成部分

编程时什么情况下才需要加载类,并解剖出类的各个组成部分呢?

加载类:

java中有一个Class类用于代表某一个类的字节码。

Class类既然代表某个类的字节码,它当然就要提供加载某个类字节码的方法:forName()。forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装

另外两种得到class对象的方式:类名.class;对象.getClass()

Class对象提供了如下常用的方法,这些方法分别用于从类中解剖出构造函数,方法和成员变量(属性)。解剖出的成员分别使用Constructor,Method,Field对象表示

十二  反射类的构造函数

利用Constructor创建对象

Constructor类提供了如下方法,用于创建类的对象:

public Object newInstance(Object...initargs)

initargs 用于指定构造函数接收的参数

package cn.reflec;import java.util.List;/* * 反射,加载类,获得类的字节码 */public class Person {		/*public static void main(String [] args){		//1		Class clazz=Class.forName("cn/reflec/Person");//加载Person类到内存,返回class对象,保存类的字节码				//2		Class clazz1=new Person().getClass();				//3		Class clazz2=Person.class;			}*/	public String name="aaaa";	public Person(){		System.out.println("person");	}	public Person(String name){		System.out.println("Person XXXX");	}	public Person(String name,int passWord){		System.out.println(name+" "+password);	}	private Person (List list){		System.out.println("list");	}}
package cn.reflec;import java.lang.reflect.Constructor;import java.util.ArrayList;import java.util.List;import org.junit.Test;//解剖(反射)类的构造函数,创建类的对象public class ReflectConstructor {	// 反射构造函数:public Person()	@Test	public void test1() throws Exception {		Class clazz = Class.forName("cn.reflec.Person");		Constructor c = clazz.getConstructor(null);		Person p = (Person) c.newInstance(null);// 创建实例		System.out.println(p.name);	}	// 反射构造函数public Person(String name)	@Test	public void test2() throws Exception {		Class clazz = Class.forName("cn.reflec.Person");		Constructor c = clazz.getConstructor(String.class);		Person p = (Person) c.newInstance("XXXX");// 创建实例		System.out.println(p.name);	}	// 反射构造函数 public Person(String name,int password)	@Test	public void test3() throws Exception {		Class clazz = Class.forName("cn.reflec.Person");		Constructor c = clazz.getConstructor(String.class, int.class);		Person p = (Person) c.newInstance("XXXX", 13);// 创建实例		System.out.println(p.name);	}	// 反射构造函数private Person (List list)	@Test	public void test4() throws Exception {		Class clazz = Class.forName("cn.reflec.Person");		Constructor c = clazz.getDeclaredConstructor(List.class);		c.setaccessible(true);// 暴力反射		Person p = (Person) c.newInstance(new ArrayList());// 创建实例		System.out.println(p.name);	}// 私有的东西不能被外界访问,但是反射可以做到	@Test	//另一种创建对象方法,要求类中必须有一个无参的构造函数	//以下代码=test1()	public void test5() throws Exception {		Class clazz = Class.forName("cn.reflec.Person");		Person p=(Person)clazz.newInstance();		System.out.println(p.name);	}}

十三  反射类的方法

利用Method执行方法

Method对象提供了如下方法,用于执行它所代表的方法:public Object invoke(Object obj,Object...args)

jdk1.4和jdk1.5的invoke方法的区别:

jdk1.5:public Object invoke(Object obj,Object...args)

jdk1.4:public Object invoke(Object obj,Object[]args)

Person类

public void aa1(){		System.out.println("aa1");	}	public void aa1(String name,int password){		System.out.println(name+" "+password);	}	public Class[] aa1(String name,int[] paaword){		return new Class[]{String.class};	}	private void aa1(InputStream in){		System.out.println(in);	}	public static void aa1(int num){		System.out.println(num);	}
package cn.reflec;import java.io.FileInputStream;import java.io.InputStream;import java.lang.reflect.Method;import org.junit.Test;//反射类的方法public class ReflectMethod {	// 反射类的方法public void aa1()	@Test	public void test1() throws Exception {		Person p = new Person();		Class clazz = Class.forName("cn.reflec.Person");		Method method = clazz.getMethod("aa1", null);		method.invoke(p, null);// 指定谁的方法跑起来,指定一个对象	}	// 反射类的方法public void aa1(String name,int password){v	@Test	public void test2() throws Exception {		Person p = new Person();		Class clazz = Class.forName("cn.reflec.Person");		Method method = clazz.getMethod("aa1", String.class, int.class);		method.invoke(p, "ZXX", 38);	}	// 反射类的方法public Class[] aa1(String name,int[] paaword)	@Test	public void test3() throws Exception {		Person p = new Person();		Class clazz = Class.forName("cn.reflec.Person");		Method method = clazz.getMethod("aa1", String.class, int[].class);		Class cs[] = (Class[]) method.invoke(p, "shuzu", new int[] { 1, 2, 3 });		System.out.println(cs[0]);	}	// 反射类的方法private void aa1(InputStream in)	@Test	public void test4() throws Exception {		Person p = new Person();		Class clazz = Class.forName("cn.reflec.Person");		Method method = clazz.getDeclaredMethod("aa1", InputStream.class);		method.setAccessible(true);		method.invoke(p, new FileInputStream("c://1.txt"));	}	// 反射类的方法private static void aa1(int num)	@Test	public void test5() throws Exception {		Person p = new Person();		Class clazz = Class.forName("cn.reflec.Person");		Method method = clazz.getMethod("aa1", int.class);		method.invoke(null, 13);// 静态的方法在调用的时候不用对象	}}

十四  反射类的main方法

public static void main(String []args){		System.out.println("main!!!");			}
package cn.reflec;import java.lang.reflect.Method;import org.junit.Test;public class reflectMain {	@Test	//利用反射调用一个参数有数组的方法,为了保存向前(1.5->1.4)兼容	public void test1() throws Exception {		Person p = new Person();		Class clazz = Class.forName("cn.reflec.Person");		Method method = clazz.getMethod("main", String[].class);		//method.invoke(null, new String[]{"aa","bb"});//main{String s1,String s2}		//method.invoke(null, new Object[]{new String[]{"aa","bb"}});//第一种		method.invoke(null, (Object)new String[]{"aa","bb"});	}}

十五  反射类的字段

public String name="aaaa";	private int password=123;	private static int age=23;
package cn.reflec;import java.io.File;import java.lang.reflect.Field;import org.junit.Test;//反射字段public class ReflectValue {	// 反射public String name="aaaa";	@Test	public void test1() throws Exception {		Person p = new Person();		Class clazz = Class.forName("cn.reflec.Person");		Field f = clazz.getField("name");		String name = (String) f.get(p);		System.out.println(name);		Object value = f.get(p);// 获取字段的值		f.set(p, "XXXXXXXXXXXXX");// 设置字段的值		// Class type =f.getType();//在不知道字段的类型的情况下获取字段的类型	}	// 反射private int password;	@Test	public void test2() throws Exception {		Person p = new Person();		Class clazz = Class.forName("cn.reflec.Person");		Field f = clazz.getDeclaredField("password");		f.setAccessible(true);		System.out.println(f.get(p));	}	// 反射private static int age=23;	@Test	public void test3() throws Exception {		Person p = new Person();		Class clazz = Class.forName("cn.reflec.Person");		Field f = clazz.getDeclaredField("age");		f.setAccessible(true);		System.out.println(f.get(p));//是静态方法,但是也需要传入一个对象进去	}}

十六  内省操作javabean的属性

内省(Introspector)

为什么要学内省?

开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都是用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性

什么是java对象的属性和属性的读写方法?

内省访问javaBean属性的两种方式:

通过PropertyDescriptor类操作Bean的属性

通过Instrospecor类获得Bean对象的BeanInfo,然后通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter,setter方法,然后通过反射机制来调用这些方法。

package cn.introspector;public class PersonJavaBean {//操作 javabean的属性封装用户的数据	//默认有一个继承自Object的class属性	// 当字段对外提供了get或set方法时,叫属性		private String name;// 字段	private String password;	private int age;	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public String getPassword() {		return password;	}	public void setPassword(String password) {		this.password = password;	}	public int getAge() {		return age;	}	public void setAge(int age) {		this.age = age;	}	public String getAe(){//也是一个属性		return null;	}}
package cn.introspector;import java.beans.BeanInfo;import java.beans.Introspector;import java.beans.PropertyDescriptor;import java.lang.reflect.Method;import org.junit.Test;//使用内省api操作bean的属性public class ApiOperateBean {	// 得到bean的所有属性	@Test	public void test1() throws Exception {		BeanInfo info = Introspector.getBeanInfo(PersonJavaBean.class);		// BeanInfo		// info=Introspector.getBeanInfo(PersonJavaBean.class,Object.class);//得到bean自己的属性,去掉继承的属性		PropertyDescriptor[] pds = info.getPropertyDescriptors();		for (PropertyDescriptor pd : pds) {			System.out.println(pd.getName());		}	}	// 操作bean指定的属性age	@Test	public void test2() throws Exception {		PersonJavaBean p = new PersonJavaBean();		PropertyDescriptor pd = new PropertyDescriptor("age",				PersonJavaBean.class);		// 得到属性的写方法,为属性赋值		Method method = pd.getWriteMethod();		method.invoke(p, 28);		System.out.println(p.getAge());		// 获取属性的值		method = pd.getReadMethod();		System.out.println(method.invoke(p, null));	}	// 获取当前操作的属性的类型	@Test	public void test3() throws Exception {		PersonJavaBean p = new PersonJavaBean();		PropertyDescriptor pd = new PropertyDescriptor("age",				PersonJavaBean.class);		System.out.println(pd.getPropertyType());	}}

十七  使用beanUtils操纵javabean

package cn.beanutils;import java.util.Date;import javax.xml.crypto.Data;public class PersonJavaBean {//操作 javabean的属性封装用户的数据	//默认有一个继承自Object的class属性	// 当字段对外提供了get或set方法时,叫属性		private String name;// 字段	private String password;	private int age;	private Date birthday;	public Date getBirthday() {		return birthday;	}	public void setBirthday(Date birthday) {		this.birthday = birthday;	}	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public String getPassword() {		return password;	}	public void setPassword(String password) {		this.password = password;	}	public int getAge() {		return age;	}	public void setAge(int age) {		this.age = age;	}	public String getAe(){//也是一个属性		return null;	}}
package cn.beanutils;import java.lang.reflect.InvocationTargetException;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Map;import javax.xml.crypto.Data;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.beanutils.ConversionException;import org.apache.commons.beanutils.ConvertUtils;import org.apache.commons.beanutils.Converter;import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;import org.junit.Test;//使用beanUtils(第三方)操纵bean的属性//第一步,把beanUtils的开发包集成到程序里来//本例使用commons-beanutils-1.7.0.jar,commons-logging-1.1.1.jarpublic class BeanUtilsTest {	@Testpublic void test1() throws IllegalAccessException, InvocationTargetException{	PersonJavaBean p=new PersonJavaBean();	BeanUtils.setProperty(p, "name", "XCC");		System.out.println(p.getName());}	//这个人的数据由用户提交,由于在表单里提交,在服务器接收全是String	@Test	public void test2() throws IllegalAccessException, InvocationTargetException{		String name="name";		String password="123";		String age="34";		String birthday="1995-10-20";		//拿到数据要将其放入对象		PersonJavaBean p=new PersonJavaBean();		BeanUtils.setProperty(p, "name", name);		BeanUtils.setProperty(p, "password", password);		BeanUtils.setProperty(p, "age", age);//自动转换,只支持8种基本数据类型		//BeanUtils.setProperty(p, "birthday", birthday);//默认不能支持,需要给beanutils注册转换器		System.out.println(p.getAge()+p.getName()+p.getPassword());			}	//为了让日期赋到beanutils属性上,我们给beanutils注册一个日期转换器	@Test	public void test3() throws IllegalAccessException, InvocationTargetException{		String name="name";		String password="123";		String age="34";		String birthday="1995-10-20";		ConvertUtils.register(new Converter(){//需导入源码			public Object convert(Class type,Object value){				//使用数据的时候,使用前一定要先检查				if(value==null){					return null;				}				if(!(value instanceof String)){					//System.out.println("数据类型不对,不转换");//需要告诉上一层程序					throw new ConversionException("只支持String类型的转换");				}				String str=(String) value;				if(str.trim().equals("")){					return null;				}				SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd");				try {					return df.parse(str);				} catch (ParseException e) {//出现异常一定报告上一层程序,采用抛出异常的方式					throw new RuntimeException(e);//异常链不能断,需要把原来的异常封装进去				}							}		}, Date.class);		PersonJavaBean p=new PersonJavaBean();		BeanUtils.setProperty(p, "name", name);		BeanUtils.setProperty(p, "password", password);		BeanUtils.setProperty(p, "age", age);//		BeanUtils.setProperty(p, "birthday", birthday);		Date date =p.getBirthday();		System.out.println(p.getAge()+p.getName()+p.getPassword()+p.getBirthday());			}	//Converter接口中已经写好了许多转换器	@Test	public void test4() throws IllegalAccessException, InvocationTargetException{		String name="name";		String password="123";		String age="34";		String birthday="";		ConvertUtils.register(new DateLocaleConverter(),Date.class);//有bug,如果传入一个空的,如上面的birthday,没有检测这种情况					PersonJavaBean p=new PersonJavaBean();		BeanUtils.setProperty(p, "name", name);		BeanUtils.setProperty(p, "password", password);		BeanUtils.setProperty(p, "age", age);//		BeanUtils.setProperty(p, "birthday", birthday);		Date date =p.getBirthday();		System.out.println(p.getAge()+p.getName()+p.getPassword()+p.getBirthday());			}	@Test	public void test5() throws IllegalAccessException, InvocationTargetException{		//用Map封装		Map map=new HashMap();		map.put("name", "aaa");		map.put("password", "123");		map.put("age", "23");		map.put("birthday", "1995-10-20");		//需要将Map封装到bean上		ConvertUtils.register(new DateLocaleConverter(),Date.class);//有bug,如果传入一个空的,如上面的birthday,没有检测这种情况				PersonJavaBean bean=new PersonJavaBean();		BeanUtils.populate(bean, map);//用Map集合中的值填充bean的属性				System.out.println(bean.getAge()+bean.getName()+bean.getPassword()+bean.getBirthday());			}}

十八  泛型

泛型(Generic)的作用,在JDK5以前,对象保存到集合中就会失去其特性(任何类型传入,都会变成Object),取出时通常要程序员手工进行类型的强制转换,这样不可避免就会引起程序的一些安全性问题,例如:

ArrayList list =new ArrayList();list.add("abc");Integer num=(Integer)list.get[0];//运行时会出错,但编码时发现不了JDK5中的泛型允许程序员在编写集合代码时,就限制集合的处理类型,从而把原来程序运行时可能发生问题,转变为编译时的问题,以此提高程序的可读性和稳定性(尤其在大型程序中更为突出)

示例:

package cn.generic;import java.util.ArrayList;import java.util.List;public class GenericTest {	public static void main(String[]args){		//声明了一个变量,变量指向某一个集合处理类型为String		List<String> list=new ArrayList<String>();		list.add("aaaaa");		String s=list.get(0);	}}掌握泛型的基本应用

掌握泛型集合的存取:

package cn.generic;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import org.junit.Test;public class Test2 {	@Test	// 带泛型的集合的存取	public void test1() {		List<String> list = new ArrayList<String>();		list.add("aa");		list.add("bb");		list.add("cc");		// 传统		Iterator<String> it = list.iterator();		while (it.hasNext()) {			String value = it.next();			System.out.println(value);		}		// 增强for		for (String s : list) {			System.out.println(s);		}	}	@Test	public void test2() {		Map<Integer, String> map = new HashMap<Integer, String>();// Map变量指向的具体的类型必须是对象类型		map.put(1, "aa");		map.put(2, "bb");		map.put(3, "cc");		// 传统keyset , entryset用的多		Set<Map.Entry<Integer, String>> set = map.entrySet();		Iterator<Map.Entry<Integer, String>> it = set.iterator();		while (it.hasNext()) {			Map.Entry<Integer, String> entry = it.next();			int key = entry.getKey();// 拆箱			String value = entry.getValue();			System.out.println(key + "=" + value);		}		// 增强for不能对Map迭代,需转成Set		for (Map.Entry<Integer, String> entry : map.entrySet()) {			int key = entry.getKey();			String value = entry.getValue();			System.out.println(key + "=" + value);		}	}}注意:泛型是提供给javac编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译完带有泛型的java程序后,生成的class文件中将不带有泛型信息。以此使程序运行效率不受到影响,这个过程称之为“擦除”。

package cn.generic;import java.util.ArrayList;public class Test3 {	ArrayList<String> list=new ArrayList<String>();}
package cn.generic;import java.util.ArrayList;public class Test4 {	ArrayList<String> list=new ArrayList();}执行后的class文件内容是一样的

用泛型时,如果两边都使用泛型,两边必须都一样

但是ArrayList<String> list=new ArrayList();可以,为了兼容性
ArrayList list=new ArrayList<String>();//也是可以的,否则,现在的程序员调用不了原来的方法
public void bb(){aa(new ArrayList());//如果上述ArrayList<String> list=new ArrayList();不可以,就无法调用}public void aa(ArrayList<String>list){}

十九  自定义泛型方法和泛型类

java程序中的普通方法,构造方法和静态方法都可以使用泛型,方法是用泛型前,必须对泛型进行声明,语法:<T>,T可以是任意字母,但通常必须大写。<T>通常放在方法的返回值声明之前:

public static <T>void doxx(T t);

注意:

只有对象类型才能作为泛型方法的参数

在泛型中可以同时有多个类型

如:public static <K,V> V getValue(K key){return map.get(key);}

package cn.generic;//自定义带泛型的方法public class Test5 {		public void test1(){		a("aaa");	}	public <T> void a(T t){  //以前使用Object,就需要进行强转,泛型不需要		//传的什么类型,返回的就是什么类型			}	public <T,E> void b(T t,E e){ //使用前需要先声明					}}
package cn.generic;public class Test6<T,E>{//类上面的泛型作用到整个类上,只作用在非静态成员上	//类里面的许多方法都使用同一个泛型	public T a(T t){//在类上声明泛型		return null;	}		public <K>void b(T t,E e,K k){			}	public static <T> void c(T t){//需要自己定义			}}两个例子

package cn.generic;public class Test7 {	// 编写一个泛型方法,实现指定位置上的数组元素的交换	public <T> void swap(T arr[], int post1, int post2) {// 将post1和post2交换		T temp = arr[post1];		arr[post1] = arr[post2];		arr[post2] = temp;	}	// 编写一个泛型方法,接收一个任意数组,并颠倒数组中的所有元素	public <T> void reverse(T arr[]) {		int start = 0;		int end = arr.length - 1;		while (true) {			if (start >= end) {				break;			}			T temp = arr[start];			arr[start] = arr[end];			arr[end] = temp;			start++;			end--;		}	}}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表