JAVA高新技术学习<一>
(jdk1.5新特性:枚举,注解,泛型)
高新技术知识点:
1.可变参数和增强for循环
/**可变参数的特点:
*...只能出现在参数列表最后面
*位于变量类型和变量名之间,前后无空格都可以
*调用可变参数方法时,编译器为该可变参数创建隐含数组,
*注意:它只为可变参数创建数组,上面的int x不在可变参数中,所以x不在可变参数中
*把int x删掉,则所有参数均纳入数组中
*在方法体中以数组形式访问可变参数。
*/
1: package Itcast.com;
2: //import static java.lang.Math.max;//必须是静态导入
3: //import static java.lang.Math.abs;//要加static
4:
5: public class zhang01
6: {
7: public static void main(String[] args)
8: {
9: add(3,5,6);
10: }
11: public static void add(int... args)//可变参数
12:
13: {
14: //这里sum=0是错的,一开始是第一个值
15: /*
16: for (int i=0;i<args.length;i++)//这里犯过低级错误for条件体之间是用; 隔开
17: {
18: sum+=args[i];
19: }
20: return sum;
21: */
22: //加强for循环(迭代取值)
23: //格式:for(type 变量名:集合变量的名字){}
24: int sum=0;
25: for(int arg:args)//自定义变量arg,用arg去迭代集合agrs,用arg逐一去取args里的元素
26: {
27: System.out.println(arg);
28: sum+=arg;
29: }
30: System.out.println(sum);
31: }
32:
33: }
34: //overload 重载
35: //override 重写
2.自动拆装箱和享元设计模式
/*享元模式(设计模式)
* 有很多个小的对象,他们有很多属性相同,所以把他们变成一个对象,
* 那些不同的属性把他们变成方法的参数。
* 将基本数据类型数字装箱时,如果在其在一个字节之内(-128到127)
* 由于位于常用区域不会改变,所以将其缓存起来,下次可直接拿来用
* 没必要一个数字对应多个对象 公用即可 *
*/
package Itcast.com; public class AutoBox { public static void main(String[] args) { Integer iobj=125; Integer jobj=125; System.out.println(iobj==jobj); /** * */ } }
3.枚举
3.1 用普通类模拟实现枚举功能
1: package Itcast.com;
2: public abstract class WeekDay1
3: {
4: private WeekDay1(){}//私有的构造方法
5:
6:
7: /*定义外部类的抽象方法
8: */
9: public abstract WeekDay1 nextDay();
10:
11: //每个元素分别用一个公有的静态成员表示
12:
13: /*现在想要在这个抽象类WeekDay1里面创建枚举类型的对象,就不能直接用new了,因为是抽象类不可以
14: *只能用这个类的子类来创建对象 ,但这个子类必须要复写父类的所有抽象方法才可以
15: *把本来大量的if else 语句转为了一个个独立的类(内部类)
16: */
17: public final static WeekDay1 SUN=new WeekDay1(){//用匿名内部类去复写抽象方法
18: public WeekDay1 nextDay()
19: {
20: return MON;
21: }
22: };
23: //通过匿名内部类复写父类抽象方法后,成功创建了抽象类的对象
24: public final static WeekDay1 MON=new WeekDay1()
25: {
26: public WeekDay1 nextDay()
27: {
28: return SUN;
29: }
30: };
31: /*public WeekDay nextDay()
32: {
33: if(this==SUN)
34: {
35: return MON;
36: }
37: else
38: {
39: return SUN;
40: }
41: }*/
42:
43:
44: //对象创建完成,把对象的返回值类型转成字符串 ,便于打印结果
45: public String toString()
46: {
47: return this==SUN? "SUN":"MON";
48: }
49:
50: }
3.2 定义一个正规的枚举用enum关键字实现,演示规范的枚举定义
1: package Itcast.com;
2:
3: public class EnumTest//枚举
4: /*定义类型,让这些类型的变量指向的指是指定的值
5: * 演示用普通类实现枚举的方法,如下
6: */
7: {
8: public static void main(String[] args)
9: {
10: //自定义枚举
11: WeekDay1 weekDay = WeekDay1.MON;
12: System.out.println(weekDay.nextDay());
13:
14: //利用专业枚举演示:
15: WeekDay weekDay2= WeekDay.FRI;
16: System.out.println(weekDay2.name());
17: //返回指定对象在枚举元素中的位置,从0开始计数
18: System.out.println(weekDay2.ordinal());
19: //把别人传过来的字符串变成一个实际的星期对象
20: System.out.println(weekDay2.valueOf("SUN"));
21: //返回一个数组,把枚举里面的元素都装进数组,还可以对数组
22: //进行操作
23: System.out.println(weekDay2.values().length);
24: System.out.println(TrafficLamp.GREEN.time);
25: }
26: /*
27: * 定义一个正规的枚举用enum关键字实现
28: */
29: //可以给枚举自定义
30: public enum WeekDay
31: {
32: //静态的成员变量,执行后都会初始化
33: //枚举的元素必须写在所有成员最前面,注意!!
34: SUN(1),MON(),TUE(1),WED,THI,FRI,SAT;
35: /*如下面所示,给出两个构造函数,一个没参数,一个带int类型的参数
36: * 那么初始化的时候到底构造谁呢?
37: * 在上面的元素列表中元素后面加(),如果里面有int值,则调用
38: * 带参数的构造方法传入相应参数来构造对应的元素,没值则调用空参数的那个来构造
39: * 对应的元素
40: * 即实现元素的差别化构造
41: */
42: //构造方法必须是私有的,而且必须位于元素列表之后
43: private WeekDay()
44: {
45: System.out.println("first");
46: }
47: private WeekDay(int day)
48: {
49: System.out.println("second");
50: }
51: }
52: //定义一个交通灯枚举类,他有三个元素:红绿黄
53: public enum TrafficLamp
54: {
55: RED (30)
56: {
57: public TrafficLamp nextLamp()
58: {
59: return GREEN;
60: }
61: },
62: GREEN(45)
63: {
64: public TrafficLamp nextLamp()
65: {
66: return YELLOW;
67: }
68: },
69: YELLOW(5)
70: {
71: public TrafficLamp nextLamp()
72: {
73: return RED;
74: }
75: };
76: //每个元素通过内部类都复写了父类的抽象方法得以建立对象
77: //很重要的一点,枚举元素是写在所有成员(变量、函数)的最前面的。
78: public abstract TrafficLamp nextLamp();
79: //成员变量time,通过构造函数可以给每个元素赋予相应的time值
80: private int time;
81: //这样子类就会调用父类有参的构造方法
82: private TrafficLamp(int time)
83: {
84: this.time=time;
85: }
86:
87:
88: }
89:
90:
91: }
4.反射
/**
* 反射的基石 Class类
* 用于描述java程序中用到的各个java类,他们的共性就是
* 他们都是java中的类,所以可以用Class类来描述
* Class类不能直接用new来创建对象,他是一堆类的字节码
* 定义方法
* Class clas1=Date.class//得到相应类的字节码
* 拥有的方法:
* p1.getClass():得到对象所属的那份字节码
* 类的静态方法forName:
* 返回字节码文件:1.已加载到虚拟机中的,直接返回该字节码
* 2.虚拟机里没有,用类加载器加载并缓存到虚拟机再返回该字节码
* Class.forName("java.lang.String")
* 得到各个字节码对应的实例对象(Class类型)
* 1 类名.class
* 2 对象.class
* 3 Class.forName("类名")
* 八个基本数据类型加void预定义了Class实例对象
* @author shantui
* 反射就是把java类中的各种成分映射成相应的java类
* 反射的constructor类:得到某个类所有的构造方法
*/
先自定义一个反射点
1: package Itcast.com;
2:
3: public class ReflactPoint
4: {
5: /*
6: private int x;
7: public int y;
8: ReflactPoint(int x,int y)
9: {
10: this.x=x;
11: this.y=y;
12: }
13: */
14:
15: public String str1="ball";
16: public String str2="basketball";
17: public String str3="fbbtball";
18: //反射点
19:
20: public String toString()
21: {
22: return str1+";"+str2+";"+str3;
23: }
24:
25:
26: //选中x,然后alt+shif+s:快速产生构造方法
27:
28:
29: }
4.1 对构造方法、自定义方法、数组的反射演示
1: package Itcast.com;
2:
3: //import java.lang.reflect.Constructor;
4: import java.lang.reflect.Array;
5: import java.lang.reflect.Field;
6: import java.lang.reflect.Method;
7: import java.util.Arrays;
8: public class reflect
9: {
10: public static void main(String[] args)throws Exception
11: {
12: String str1="abc";
13: /**
14: Class cls1=str1.getClass();
15: //Class cls2=String.class;
16: //Class cls3=Class.forName("java.lang.String");
17: //System.out.println(cls1==cls2);
18: //System.out.println(cls3==cls2);
19: //验证是不是个基本数据类型的字节码
20: //结果是否,因为他是个类
21: //System.out.println(cls1.isPrimitive());
22: //int是基本数据类型
23: //System.out.println(int.class.isPrimitive());
24: //问:int[]这个类型是不是数组类型
25: //结果:是这样判断的
26: //System.out.println(int[].class.isArray());
27:
28: //constructor构造器类型,方法使用:
29:
30:
31: //得到String类中指定构造方法,哪个呢(有很多个构造方法而且无序)?
32: //我只想得到构造方法中:接受参数为两个,分别是StringBuffer类型,int类型
33: //只想得到这种,如何得到,如下:
34: //Constructor constructor1= String.class.getConstructor(StringBuffer.class,int.class);
35:
36: //用反射实现此效果:new String (new StringBuffer("abc")),就是给String的构造函数传入的是一个abc,这个abc是个StringBuffer类型,以此完成new一个String
37: //重新对StringBuffer进行自定义的构造
38: //编译期不执行等号右边的运算,所以不知道constructor是谁的构造方法,返回的是谁的,所以要指明
39: //不指明编译期通不过的
40: //Constructor constructor2= String.class.getConstructor(StringBuffer.class);
41: //得到构造方法后,怎么用?:有一个newInstanc方法:构造一个实例对象。
42: //String str2=(String)constructor2.newInstance(new StringBuffer("abc"));
43: //System.out.println(str2.charAt(2));
44: //创建一个对象的一般方法class->constructor-->new object
45: //为简化过程,用到了newInstance:创建一个实例对象:Class.newInstance
46:
47: //给反射点传入两个值
48: *
49: */
50: ReflactPoint pt1=new ReflactPoint();
51: /**得到一个类身上的某个字段
52: Fied类代表某个类中的一个成员变量,即 成员变量类
53: filedy的值不是5,因为filedy不是对象身上的变量,而是类上的,要用它 去取x和Y
54: 他把类上的指定的成员变量封装起来,成为类里的一个变量,可用他去取值
55: Field fieldy = pt1.getClass().getField("y");
56: System.out.println(fieldy.get(pt1));
57: 由于 x私有了,要想得到x,需要用getDeclaredField("x")
58: Field fieldx = pt1.getClass().getDeclaredField("x");
59: 把私有的x进行暴力反射
60: fieldx.setAccessible(true);
61: System.out.println(fieldx.get(pt1));
62: */
63: changeStingValue(pt1);
64: System.out.println(pt1);
65: /**
66: 通过反射调用Sting类型的CharAt()方法
67: 得到String类文件中的指定方法,即名字为charat,接受的数据类型为int类型的那个重载形式
68: 这里的名字一定要是系统存在的函数名,而且不要写错,比如首字母是小写的。
69: */
70: Method methodCharAt =String.class.getMethod("charAt",int.class);
71: /**
72: invok:调用,他是方法身上的调用,即方法的开启标志和信号
73: invok格式:invok(要用charAt的变量名称,你要charAt第几个?)
74: 如果出现这样的格式:invok( ,x),说明该Method方法,这是个静态方法
75: */
76: System.out.println(methodCharAt.invoke(str1,1));
77:
78: /**
79: * TestArguments.main(new String[]{"abc","ddd"});
80: 如果要启用的TestArguments这个类是客户输入的,我们不知道,则上面的方法不可行了
81: 为什么要用反射调用main,假如TestArguments中,每个args[i]都是个类名,我们不知道客户想运行哪个类的主函数
82: 这是就要用到反射,给我你想运行的类名,我反射一下就可以执行其主函数
83: */
84:
85: /**
86: * 这里调出软件的run as对话框,把此主函数入口中要传入的(x)=Arguments
87: * 这样这个主函数就会被传入一个类类型的变量,相当于客户输入了一个类,
88: * 让本类来运行他的主函数 *
89: */
90: String startingClassName=args[0];
91: Method mainMethod =Class.forName(startingClassName).getMethod("main", String[].class);
92:
93: mainMethod.invoke(null,(Object)new String[]{"abc","123","sss"});
94: /*
95: * 数组反射演示:
96: */
97: int [] a1=new int[]{1,2,3};
98: int [] a2=new int[4];
99: int [][] a3=new int[1][2];
100: String [] a4=new String[]{"111","2222","3"};
101: System.out.println(a1.getClass()==a2.getClass());
102: System.out.println(a1.getClass().getName());//“[I”代表 :整数 数组
103: System.out.println(a1.getClass().getSuperclass().getName());//数组父类名
104:
105: /*
106: * 基本数据类型都不是Object类型
107: * 所以Object[] aobj1=a1是错的,int不是Object类型,int[]是
108: */
109: Object[] aobj4=a4;//String是Object类型
110: Object[] aobj3=a3;
111: /**
112: object数组内装了一个abject类型的数组,即二维数组。
113: aslist方法可以把字符串数组的元素转成List集合的形式,但它只接受Object类型的数组
114: ,但int类型数组不符合,所以只把a1当成一个单纯Object数处理。
115: */
116: System.out.println(Arrays.asList(a1));
117: System.out.println(Arrays.asList(a4));
118: //数组反射演示:
119: Object obj =null;
120: printObject(a4);
121:
122: }
123:
124: private static void printObject(Object obj)
125: {
126: // TODO Auto-generated method stub
127: Class clasz=obj.getClass();
128: if (clasz.isArray())
129: {
130: int len =Array.getLength(obj);
131: for (int i = 0; i <len; i++)
132: {
133: System.out.print(Array.get(obj, i)+" ");
134: }
135: }
136: else
137: {
138: System.out.println(obj);
139: }
140: }
141:
142:
143:
144:
145:
146: //把指定成员变量的值按照指定的规则替代(把b全换成a)
147: private static void changeStingValue(Object obj) throws Exception
148: {
149: // TODO Auto-generated method stub
150: Field[] fields =obj.getClass().getFields();
151: for(Field field :fields)
152: {
153: //字节码的比较用等号,因为都只有一份
154: //if(field.getType().equals(String.class))
155: if(field.getType()==String.class);
156: {
157: String oldvalue=(String)field.get(obj);
158: String newValue= oldvalue.replace('b', 'a');
159: field.set(obj, newValue);
160:
161: }
162: }
163:
164: }
165: }
166:
167: class TestArguments//等待客户输入此类
168: {
169: public static void main(String[] args)
170: {
171: for(String arg: args)
172: {
173: System.out.println(arg);
174: }
175:
176: }
177: }
4.2 用对类的反射实现客户给我什么类,我就运行什么类的效果
/*获取类的方法2:类加载器
* 配置文件都放在classpath指定的目录下。
* 获取类的方法1:通过配置文件:
* 通过集合框架的形式,传入指定的集合类型,可将下面的
* 集合类定义成用户传入的 类,这里就需要传入一个配置文件“config.properties”
* 在里面预先写入想传入的是哪个集合类
1: package Itcast.com;
2: import java.io.FileInputStream;
3: import java.io.InputStream;
4: import java.util.Collection;
5: import java.util.Properties;
6: public class ReflectTest2
7: {
8: public static void main(String[] args) throws Exception
9: {
10:
11: //获得ReflectTest2类的类加载器后到classpath指定的目录中去加载指定的类,
12: ReflectTest2.class.getClassLoader().getResourceAsStream("E:/lsk/studyTest//config.properties");
13:
14: //读取配置文件
15: InputStream ips =new FileInputStream("config.properties");
16: //利用properties类加载读取的配置文件中的信息
17: Properties props =new Properties();
18: props.load(ips);
19: ips.close();
20: //按照配置文件中的类名,找到其值(类的类型),即由其key找到其value(集合类型),赋给className
21: String className = props.getProperty("className");
22: //按照类名(key=className)找到对应类类型(value)后新构造一个collections
23: Collection collections =(Collection)Class.forName(className).newInstance();
24:
25: //Collection collections =new HashSet();
26: person p1=new person(5,5);
27: person p2=new person(5,5);
28: person p3=new person(3,3);
29: collections.add(p1);
30: collections.add(p2);
31: collections.add(p3);
32: collections.add(p1);
33: System.out.println(collections.size());
34: }
35: }
36: class person
37: {
38: int x=0,y=0;
39: person(int x,int y)
40: {
41: this.x=x;
42: this.y=y;
43: }
44:
45: }
46: