java基础增强

1. 静态导入和自动装箱拆箱

(1).静态导入: 导入java里面类的静态成员 import static 包名 类名 静态属性/静态方法/*
(2).自动装箱拆箱:
自动装箱:把基本数据类型赋值给对应的包装类(对象)
自动拆箱:把包装类的对象赋值给对应的基本数据类型

 1 package com.study.lgs;
 2 import static java.lang.System.out;
 3 
 4 import java.util.ArrayList;
 5 import java.util.Iterator;
 6 import java.util.List;
 7 public class ZhuangXiangChaiXiang {
 8 
 9     public static void main(String[] args) {
10         // TODO Auto-generated method stub
11         //1、静态导入
12         //out.println("aaa");
13         
14         //2.自动装箱拆箱:
15         Integer i=1;//自动装箱  jdk1.5+才能这样写 否则这样写:Integer i=new Integer(1)
16         int j=i;//自动拆箱
17         
18         //3.自动装箱拆箱的典型应用
19         List l=new ArrayList();
20         l.add(1);//装箱 把对象1装到list对象l里面去
21         l.add(2);
22         l.add(3);
23     
24         //迭代器遍历输出
25         Iterator k=l.iterator();
26         while(k.hasNext()){
27             int j1=(Integer)k.next();
28             out.println(j1);
29             
30             
31         }
32         /*ArrayList<Integer> al=new ArrayList<Integer>();
33         al.add(1);
34         al.add(2);
35         al.add(3);
36         for(Integer k:al){
37             out.println(k);
38         }*/
39     }
40 
41 }

2. 增强for循环

    用途:遍历数组或者遍历实现Iterable泛型接口的集合

  1 package cn.study.lgs;
  2 import static java.lang.System.out;
  3 
  4 import java.util.ArrayList;
  5 import java.util.HashMap;
  6 import java.util.Iterator;
  7 import java.util.List;
  8 import java.util.Map;
  9 import java.util.Map.Entry;
 10 import java.util.Set;
 11 
 12 import org.junit.Test;
 13 
 14 public class StrongFor {
 15     
 16     @Test
 17     public void test1(){
 18         //1、遍历数组
 19         int i[]={1,2,3};
 20         for(int k:i){
 21             out.println(k);
 22         }
 23     }
 24     @Test
 25     public void test2(){
 26         //2、遍历集合
 27         List l=new ArrayList();
 28         l.add(1);
 29         l.add(2);
 30         l.add(3);
 31     //    l.add("aaa");
 32         
 33         for(Object o:l){
 34 //            out.println(o); //不用包装直接以对象的形式输出 也可以
 35             int i=(Integer) o;
 36             out.println(i);
 37         }
 38         }
 39     @Test
 40     public void testMap(){
 41         Map m=new HashMap();
 42         m.put("1", "aaa");
 43         m.put("2", "bbb");
 44         m.put("3", "ccc");
 45         //1、传统方案取出Map里面的值 1
 46         Set s=m.keySet();//通过keyset方法把map里面的每个key存到s里面去
 47         Iterator i=s.iterator();//迭代遍历s里面的key值
 48         while(i.hasNext()){
 49 //            String key=(String) i.next();
 50 //            String value=(String) m.get(key);
 51 //            out.println(key+"对应的值为:"+value);
 52             String st=(String) i.next();
 53             System.out.println(st+ "对应的值为"+m.get(st));
 54             
 55 //            System.out.println(i.next());  //有错 两次的i.next()不一样
 56 //            System.out.println(m.get(i.next()));
 57         
 58             
 59         }
 60         
 61         
 62     }
 63     @Test
 64     public void testMap2(){
 65         Map m=new HashMap();
 66         m.put("1", "aaa");
 67         m.put("2", "bbb");
 68         m.put("3", "ccc");
 69         //1、传统方案取出Map里面的值 2
 70         Set s=m.entrySet();//通过entrySet方法把每组键值存到s中
 71         Iterator i=s.iterator();//迭代遍历输出s中的值
 72         while(i.hasNext()){
 73             Map.Entry me=(Entry) i.next();
 74             System.out.println(me.getKey()+"对应的值为"+me.getValue());
 75         }
 76         
 77         
 78         
 79     }
 80 
 81     @Test
 82     public void testMap3(){
 83         Map m=new HashMap();
 84         m.put("1", "aaa");
 85         m.put("2", "bbb");
 86         m.put("3", "ccc");
 87         //1、增强for循环 1 (keySet实现Iterable泛型接口)
 88         for(Object o:m.keySet()){
 89 //            String s=(String) o;
 90 //            String value=(String) m.get(o);
 91 //            System.out.println(o+" "+value);
 92             out.println(o+" "+m.get(o));
 93         }
 94         
 95         
 96     }
 97     @Test
 98     public void testMap4(){
 99         Map m=new HashMap();
100         m.put("1", "aaa");
101         m.put("2", "bbb");
102         m.put("3", "ccc");
103         //1、增强for循环 2 (entrySet实现Iterable泛型接口)
104         for(Object o:m.entrySet()){
105          Map.Entry me=(Entry) o;
106          System.out.println(me.getKey()+" "+me.getValue());
107         }
108         
109         
110     }
111     
112     @Test //增强for循环应该注意的问题 增强for循环只能取数组或者集合里面的数据 不能更改数据;要改数据的话只能用传统方法
113     public void test3(){
114 //        int []i=new int[]{1,2,3};
115 //        for(int j:i){
116 //            j=10;//j仅仅是指向取出来的值而已 并不能改变数组里面的值
117 //            
118 //        }
119 //        //传统方法改变数组的值
120 //        for(int j=0;j<i.length;j++){
121 //            i[j]=10;
122 //        }
123 //        out.println(i[0]);
124 //        out.println(i[1]);
125 //        out.println(i[2]);
126 //        
127 
128         List l=new ArrayList();
129         l.add("a");
130         l.add("b");
131         l.add("c");
132         for(Object k:l){
133             k="d";//k仅仅是指向取出来的值而已 并不能改变集合里面的值
134             
135         }
136         //传统方案删除集合里面的元素
137         for(int i=0;i<l.size();i++){
138             
139             l.removeAll(l);
140             
141             
142             
143         }
144         l.add("e");
145         l.add("e");
146         l.add("e");
147         System.out.println(l.get(0));
148         System.out.println(l.get(1));
149         System.out.println(l.get(2));
150         
151     
152     }
153 }

3. 可变参数

使用可变参数的精髓:就是看需要什么类型的数据,需要对象就传入对象/对象数组,需要基本数据类型就传基本数据类型/基本数组

 1 package com.study.lgs;
 2 import java.util.Arrays;
 3 import java.util.List;
 4 
 5 import org.junit.Test;
 6 
 7 public class KeBianCanShu {
 8     
 9     @Test
10     public void testSum(){
11         int []i={1,2,3};
12         sum(i);//可变参数里面可以看成一个数组,所以可以向里面传入数组i
13         sum(1,2,3);
14     }
15     //可变参数按数组方式进行处理,只能放在参数列表的最后,一个参数列表中只能有一个可变参数
16     
17     public void sum(int...nums){
18         int sum=0;
19         for(int k:nums){
20             sum+=k;
21         }
22         System.out.println(sum);
23     }
24     @Test
25     public void testArrays(){
26         List l=Arrays.asList("1","2","3");//传入普通字符串对象
27         System.out.println(l);
28         
29         String [] s={"1","2","3","4"};//传入字符数组对象
30         l=Arrays.asList(s);
31         System.out.println(l);
32         
33         //int []i={1,2,3,4,5};
34         Integer []i={1,2,3,4,5};
35         l=Arrays.asList(i);//传入基本数据类型整型数组对象 List的l会吧i数组看作一个对象,所以输出的l为一个地址,必须使用包装类的对象以对象方式传入才可输出实际的值
36         System.out.println(l);
37     }
38 
39 }

4. 枚举

4.1 枚举的作用和特性

  作用:限定某些程序运行时所需要数据的取值范围

  特性:

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

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

      (3) 与java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数,但枚举类的构造函数必须是私有的(因为枚举类的作用就是限定某些程序运行时所需要数据的取值范围,如果构造函数公有,别人就可以随便更改)

      (4) 枚举类也可以实现接口、继承抽象类

      (5) jdk5扩展了switch语句,它除了可以接收int,byte,char,short外,还可以接收一个枚举类型

      (6) 若枚举类只有一个枚举值,则可以单作单态设计模式使用

 1 package enumeration;
 2 
 3 import org.junit.Test;
 4 
 5 //枚举的作用:限定某些程序运行时所需要数据的取值范围
 6 enum Grade{
 7     A,B,C,D
 8 }
 9 public class DefineEnum {
10     @Test
11     public void test(){
12         DefineEnum.printGrade(Grade.A);
13     }
14     public static void printGrade(Grade a){
15         switch(a){
16         case A:
17             System.out.println("90");
18              break;
19         case B:
20             System.out.println("80");
21             break;
22         case C:
23             System.out.println("70");
24             break;
25         case D:
26             System.out.println("60");
27             break;
28         default:
29             System.out.println("传入参数有错");
30             
31         }
32     }
33 }

4.2 定义枚举的字段、构造函数、方法去封装更多的信息

 1 package enumeration;
 2 
 3 import org.junit.Test;
 4 
 5 //枚举的作用:限定某些程序运行时所需要数据的取值范围
 6 //怎样定义枚举的字段、构造函数、方法去封装更多的信息
 7 enum Grade{
 8     A("100-90"),B("89-80"),C("79-70"),D("69-60");//对枚举进行实例化
 9     private String value;//定义每个枚举类型里面存的值
10     private Grade(String value){
11         this.value=value;
12     }
13     public String getValue(){ //外部对象获取每个枚举类型里面存的值
14         return this.value;
15     }
16 }
17 public class DefineEnum {
18     @Test
19     public void test(){
20         printGrade(Grade.B);
21     }
22     public void printGrade(Grade a){
23         System.out.println(a.getValue());
24     }
25 }

4.3 带抽象方法的枚举 实例化时必须实现抽象方法

 1 package enumeration;
 2 
 3 import org.junit.Test;
 4 
 5 //枚举的作用:限定某些程序运行时所需要数据的取值范围
 6 //带抽象方法的枚举 实例化时必须实现抽象方法
 7 enum Grade{
 8     A("100-90") {
 9         @Override
10         public String getLocalValue() {
11             // TODO Auto-generated method stub
12             return "优";
13         }
14     },
15     B("89-80") {
16         @Override
17         public String getLocalValue() {
18             // TODO Auto-generated method stub
19             return "良";
20         }
21     },
22     C("79-70") {
23         @Override
24         public String getLocalValue() {
25             // TODO Auto-generated method stub
26             return "中";
27         }
28     },
29     D("69-60") {
30         @Override
31         public String getLocalValue() {
32             // TODO Auto-generated method stub
33             return "差";
34         }
35     };//对枚举进行实例化 必须实现抽象方法
36     
37     private String value;//定义每个枚举类型里面存的值
38     private Grade(String value){
39         this.value=value;
40     }
41     public String getValue(){ //外部对象获取每个枚举类型里面存的值
42         return this.value;
43     }
44     //带抽象方法的枚举
45     public abstract String getLocalValue();
46 }
47 public class DefineEnum {
48     @Test
49     public void test(){
50         printGrade(Grade.B);
51     }
52     public void printGrade(Grade a){
53         System.out.println(a.getValue());
54         System.out.println(a.getLocalValue());
55         
56     }
57 }

4.4 普通单例设计模式与枚举单例设计模式

 1 package enumeration;
 2 
 3 //定义普通单态设计模式
 4 class Single{
 5     private static Single sin=null;
 6     private Single(){}
 7     private Single(Single sin){
 8         this.sin=sin;
 9     }
10     public static Single createShiLi(){
11         if(sin==null){
12             sin=new Single();
13         }
14         return sin;
15         
16     }
17 }
18 //定义枚举类型单态设计模式 当枚举里面只有一个对象时也属于单态设计模式
19 enum EnumSingle{
20     A;//枚举中声明的每一个枚举值表示枚举类的一个实例化对象
21       //m枚举类的构造函数必须是私有的,因为枚举就是用来限制实例化的对象的,如果构造函数为公有的就可以实例化新的对象,不符合枚举规范    
22 }
23 public class DefineSingle {
24 
25     public static void main(String[] args) {
26         // TODO Auto-generated method stub
27         //普通设计模式的实例化
28         Single s1=Single.createShiLi();
29         Single s2=Single.createShiLi();
30         Single s3=Single.createShiLi();
31         System.out.println(s1);
32         System.out.println(s2);
33         System.out.println(s3);
34         
35         
36 
37     }
38 
39 }

 4.6 测试枚举中的常用方法

 1 package enumeration;
 2 
 3 import org.junit.Test;
 4 
 5 //枚举的作用:限定某些程序运行时所需要数据的取值范围
 6 //带抽象方法的枚举 实例化时必须实现抽象方法
 7 //枚举中声明的每一个枚举值表示枚举类的一个实例化对象
 8 //m枚举类的构造函数必须是私有的,因为枚举就是用来限制实例化的对象的,如果构造函数为公有的就可以实例化新的对象,不符合枚举规范    
 9 
10 enum Grade {
11     A("100-90") {
12         @Override
13         public String getLocalValue() {
14             // TODO Auto-generated method stub
15             return "优";
16         }
17     },
18     B("89-80") {
19         @Override
20         public String getLocalValue() {
21             // TODO Auto-generated method stub
22             return "良";
23         }
24     },
25     C("79-70") {
26         @Override
27         public String getLocalValue() {
28             // TODO Auto-generated method stub
29             return "中";
30         }
31     },
32     D("69-60") {
33         @Override
34         public String getLocalValue() {
35             // TODO Auto-generated method stub
36             return "差";
37         }
38     };// 对枚举进行实例化 必须实现抽象方法
39 
40     private String value;// 定义每个枚举类型里面存的值
41 
42     private Grade(String value) {
43         this.value = value;
44     }
45 
46     public String getValue() { // 外部对象获取每个枚举类型里面存的值
47         return this.value;
48     }
49 
50     // 带抽象方法的枚举
51     public abstract String getLocalValue();
52 }
53 
54 public class DefineEnum {
55     @Test
56     public void test() {
57         printGrade(Grade.B);
58     }
59 
60     public void printGrade(Grade a) {
61         System.out.println(a.getValue());
62         System.out.println(a.getLocalValue());
63 
64     }
65 
66     // 测试枚举的常用方法
67     @Test
68     public void test2() {
69         System.out.println(Grade.A.name());// name()方法返回枚举的名字
70         System.out.println(Grade.A.ordinal());// ordinal()方法返回枚举对象在枚举类中的序号
71         String str = "B";
72         Grade g = Grade.valueOf(Grade.class, str);// valueOf()方法将某个枚举对象对应的字符串转变为枚举对象
73                                                     // 实际开发中用于检测用户提交的字符串是否属于自己定义的枚举类型
74                                                     // Grade
75                                                     // g=Grade.valueOf(str);
76         System.out.println(g);
77         // for(Grade g:Grade.values()){ //values()方法获取枚举中的每个值
78         // System.out.println(g);
79         // }
80 
81     }
82 }

4.7 定义一个星期的枚举设置方法返回对应中文星期

 1 package enumeration;
 2 
 3 import org.junit.Test;
 4 
 5 //定义一个星期的枚举WeekDay
 6 //枚举值:Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
 7 //该枚举有一个方法,调用该方法返回中文格式的日期
 8 enum WeekDay{
 9     Monday {
10         @Override
11         public String getChineseDay() {
12             // TODO Auto-generated method stub
13             return "星期一";
14         }
15     },
16     Tuesday {
17         @Override
18         public String getChineseDay() {
19             // TODO Auto-generated method stub
20             return "星期二";
21         }
22     },
23     Wednesday {
24         @Override
25         public String getChineseDay() {
26             // TODO Auto-generated method stub
27             return "星期三";
28         }
29     },
30     Thursday {
31         @Override
32         public String getChineseDay() {
33             // TODO Auto-generated method stub
34             return "星期四";
35         }
36     },
37     Friday {
38         @Override
39         public String getChineseDay() {
40             // TODO Auto-generated method stub
41             return "星期五";
42         }
43     },
44     Saturday {
45         @Override
46         public String getChineseDay() {
47             // TODO Auto-generated method stub
48             return "星期六";
49         }
50     },
51     Sunday {
52         @Override
53         public String getChineseDay() {
54             // TODO Auto-generated method stub
55             return "星期天";
56         }
57     };
58     public abstract String getChineseDay();
59     
60 }
61 public class HomeWork {
62     
63     @Test
64     public void test(){
65         printDay(WeekDay.Friday);
66     }
67     public void printDay(WeekDay wd){
68         System.out.println(wd.getChineseDay());
69     }
70 
71 }

5. 反射

5.1 反射的概念

反射:加载类(获取类的字节码),获取类里面的各种组成成分
反射的用途:写框架
通过反射获取类里面的各种组成干什么?
                (1) 获取构造函数去实例化对象
                (2) 获取字段去封装数据
                (3) 获取方法去运行

加载类的三种方式:

 1 package refelect;
 2 
 3 public class LoadClass {
 4 
 5     public static void main(String[] args) throws ClassNotFoundException {
 6         // TODO Auto-generated method stub
 7         //加载类的方法
 8         //1、Class类的forName()方法
 9         Class c1=Class.forName("refelect.Person"); //把类的字节码加载到内存中去
10         System.out.println(c1);
11         //2、通过对象的getClass()方法
12         Person p=new Person();
13         Class c2=p.getClass(); //把类的字节码加载到内存中去
14         System.out.println(c2);
15         //3、通过.class
16         Class c3=Person.class; //把类的字节码加载到内存中去
17         System.out.println(c3);
18 
19     }
20 
21 }

5.2  通过反射获取类的构造函数

 1 package refelect;
 2 
 3 import java.io.InputStream;
 4 import java.util.List;
 5 
 6 public class Person {
 7 
 8     public String name = "aaa";
 9 
10     private int password = 123;
11 
12     private static int age = 23;
13 
14     public static int score = 90;
15 
16     public Person() {
17         System.out.println("person");
18     }
19 
20     public Person(String name) {
21         System.out.println("person name");
22     }
23 
24     public Person(String name, int password) {
25         System.out.println("person name password");
26     }
27 
28     private Person(List list) {
29         System.out.println("list");
30     }
31 
32     public void aa() {
33         System.out.println("aa");
34     }
35 
36     public void aa(String name, int password) {
37         System.out.println(name + password);
38     }
39 
40     public Class[] aa(String name, int[] password) {
41         return new Class[] { String.class };
42     }
43 
44     private void aa(InputStream in) {
45         System.out.println(in);
46     }
47 
48     public static void aa(int num) {
49         System.out.println(num);
50     }
51 
52     public static void main(String[] args) {
53         System.out.println("main");
54     }
55 }
 1 package refelect;
 2 
 3 import java.lang.reflect.Constructor;
 4 import java.util.ArrayList;
 5 import java.util.List;
 6 
 7 import org.junit.Test;
 8 
 9 public class GetConstructor {
10     
11     //通过反射获取类里面的无参构造函数 public Person()
12     @Test
13     public void test1() throws  Exception{
14         //1、获取无参构造函数 public Person()
15         Class c1=Class.forName("refelect.Person");//加载类到内存中去
16         Constructor cs1=c1.getConstructor(null);//通过传入的可变参数获取对应的构造函数,此处获取无参构造函数
17         Person p1=(Person) cs1.newInstance(null);//通过无参构造函数实例化对象
18         String s=p1.name;
19         System.out.println(s);
20     }
21     //通过反射获取类里面的有一个参数构造函数  public Person(String name)
22     @Test
23     public void test2() throws  Exception{
24         
25         Class c1=Class.forName("refelect.Person");//加载类到内存中去
26         Constructor cs1=c1.getConstructor(String.class);//记住:必须传入String.class告知参数类型为字符串,不能传入"aaa"之流
27         Person p=(Person) cs1.newInstance("aaa");//通过构造函数实例化对象
28         System.out.println(p.name);
29     }
30     //通过反射获取类里面的有两个参数构造函数 public Person(String name,int passord)
31     @Test
32     public void test3() throws  Exception{
33         
34         Class c1=Class.forName("refelect.Person");//加载类到内存中去
35         Constructor cs1=c1.getConstructor(String.class,int.class);
36         Person p=(Person) cs1.newInstance("aaa",123);
37         System.out.println(p.name);
38     }
39     //通过反射获取类里面的私有带参构造函数  private Person(List l)
40     @Test
41     public void test4() throws  Exception{
42         //getConstructor()方法只能获取public类型的构造函数
43         //getDeclaredConstructor()方法能够获取所有声明的构造函数包括私有的
44         Class c1=Class.forName("refelect.Person");//加载类到内存中去
45         Constructor cs1=c1.getDeclaredConstructor(List.class);
46         cs1.setAccessible(true);//记住:一定要暴力地将私有的构造函数属性设置为可以被外部访问,否则将会报错
47         Person p=(Person) cs1.newInstance(new ArrayList());
48         System.out.println(p.name);
49     }
50     //创建对象的另一种途径 直接通过反射出的类的newInstance()方法 ,自动调用无参构造函数实例化,以下代码等价于test1
51     @Test
52     public void test5() throws  Exception{
53         //getConstructor()方法只能获取public类型的构造函数
54         //getDeclaredConstructor()方法能够获取所有声明的构造函数包括私有的
55         Class c1=Class.forName("refelect.Person");//加载类到内存中去
56         Person p=(Person) c1.newInstance();
57         System.out.println(p.name);
58     }
59 
60 }

5.3 通过反射获取类的方法以及main方法的特殊获取

 1 package refelect;
 2 
 3 import java.io.FileInputStream;
 4 import java.io.InputStream;
 5 import java.lang.reflect.Method;
 6 
 7 import org.junit.Test;
 8 
 9 //通过反射获取类里面的方法
10 public class GetMethods {
11     
12     //获取方法 public void aa()
13     @Test
14     public void test1() throws Exception{
15     Class c1=Class.forName("refelect.Person");//加载类
16     Method m=c1.getMethod("aa", null);//获取类里面的方法 第一个参数指定是哪一个方法,第二个参数指定方法的参数类型
17     m.invoke(c1.newInstance(), null);//执行方法,第一个参数指定执行方法需要实例化的对象,第二个参数为需要传入的参数
18     }
19     
20     //获取方法 public void aa(String name,int password)
21     @Test
22     public void test2() throws Exception{
23         Class c1=Class.forName("refelect.Person");//加载类
24         Method m=c1.getMethod("aa", String.class,int.class);
25         m.invoke(c1.newInstance(), "lgs",21);
26     }
27     
28     //获取方法 public Class[] aa(String name,int[] password)
29     @Test
30     public void test3() throws Exception{
31         Class c1=Class.forName("refelect.Person");//加载类
32         Method m=c1.getMethod("aa", String.class,int[].class);
33         Class [] cls=(Class[]) m.invoke(c1.newInstance(), "lgs",new int[]{1,2,3});
34         System.out.println(cls[0]);
35     }
36     //获取方法 private void aa(InputStream in)
37     @Test
38     public void test4() throws Exception{
39         Class c1=Class.forName("refelect.Person");//加载类
40         Method m=c1.getDeclaredMethod("aa", InputStream.class);//获取私有方法
41         m.setAccessible(true);//暴力解除方法私有属性
42         m.invoke(c1.newInstance(), new FileInputStream("c:\1.txt"));
43         
44     }
45     //获取方法 public static void aa(int num)
46     @Test
47     public void test5() throws Exception{
48         Class c1=Class.forName("refelect.Person");//加载类
49         Method m=c1.getDeclaredMethod("aa", int.class);//获取私有方法
50         
51         m.invoke(c1.newInstance(), 23);//静态方法调用时不需要对象,因此第一个参数可以为空
52         
53     }
54     //获取方法 public static void main(String[] args)
55     @Test
56     public void test6() throws Exception{
57         Class c1=Class.forName("refelect.Person");//加载类
58         Method m=c1.getDeclaredMethod("main", String[].class);//获取私有方法
59         
60         //m.invoke(null, new String[]{"1","2"});//错误的 因为在传数组参数进去给main函数的时候会被自动拆分为String s1和String s2 main函数里面没有这两种参数所以报错参数个数不正确
61         //m.invoke(null, new Object[]{new String[]{"1","2"}});//静态方法调用时不需要对象,因此第一个参数可以为空,此时main函数会被自动拆分为String[]数组,不会报错
62         m.invoke(null, (Object)new String[]{"1","2"});//这哥们不是喜欢把数组拆分为字符串吗,就加Object强制转换骗他我不是数组
63     }
64 }

5.4 通过反射获取类的字段

 1 package refelect;
 2 
 3 import java.lang.reflect.Field;
 4 
 5 import org.junit.Test;
 6 
 7 //通过反射获取字段
 8 public class GetFields {
 9   //获取字段public String name="lgs";
10     @Test
11   public void test1() throws Exception{
12         
13       Class c1=Class.forName("refelect.Person");//加载类
14       Field f=c1.getField("name");//获取字段 参数为要获取的字段的名称
15      // String s= (String) f.get(c1.newInstance());//获取字段的值  参数为对应的对象
16       Object o=f.get(c1.newInstance());//获取字段的值  参数为对应的对象
17       
18       //获取字段的类型
19       Class type=f.getType();
20       if(type.equals(String.class)){
21           String s=(String) o;
22           System.out.println(s);
23       }
24       
25       //设置字段的值
26       Person p=(Person) c1.newInstance();
27       f.set(p, "yc");
28       System.out.println(p.name);
29 
30       
31   }
32     //获取字段private int password=123;
33     @Test
34       public void test2() throws Exception{
35             
36           Class c1=Class.forName("refelect.Person");//加载类
37           Field f= c1.getDeclaredField("password");
38           f.setAccessible(true);//暴力修改字段的可视性为公有
39           Object o=f.get(c1.newInstance());
40           System.out.println(o);
41     }
42     //获取字段private static int  age=23;
43     @Test
44     public void test3() throws Exception{
45         
46         Class c1=Class.forName("refelect.Person");//加载类
47         Field f= c1.getDeclaredField("age");
48         f.setAccessible(true);//暴力修改字段的可视性为公有
49         Object o=f.get(c1.newInstance());
50         System.out.println(o);
51     }
52     //获取字段public static int  score=90;
53     @Test
54     public void test4() throws Exception{
55         
56         Class c1=Class.forName("refelect.Person");//加载类
57         Field f= c1.getField("score");
58 //        Object o=f.get(c1.newInstance());
59         System.out.println(f.get(c1.newInstance()));
60     }
61 }

 6. 内省(Introspector)

6.1 为什么要学习内省

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

6.2 通过内省操作javabean属性

 1 package refelect;
 2 
 3 /**
 4  * Person就是一个javabean 
 5  * 里面的字段有对应的get或者set方法,这个字段就称为一个属性
 6  * 
 7  * @author lgs
 8  *
 9  */
10 public class Person {
11 
12     // 字段
13     public String name;
14 
15     // 字段
16     private int password;
17 
18     // 字段
19     private int age;
20 
21     // 字段
22     private int score;
23 
24     public String getName() {
25         return name;
26     }
27 
28     public void setName(String name) {
29         this.name = name;
30     }
31 
32     public int getPassword() {
33         return password;
34     }
35 
36     public void setPassword(int password) {
37         this.password = password;
38     }
39 
40     public int getAge() {
41         return age;
42     }
43 
44     public void setAge(int age) {
45         this.age = age;
46     }
47 
48     public int getScore() {
49         return score;
50     }
51 
52     public void setScore(int score) {
53         this.score = score;
54     }
55 
56 }
 1 package introspector;
 2 
 3 import java.beans.BeanInfo;
 4 import java.beans.IntrospectionException;
 5 import java.beans.Introspector;
 6 import java.beans.PropertyDescriptor;
 7 import java.lang.reflect.Method;
 8 
 9 import org.junit.Test;
10 
11 //通过内省来操作bean(即Person类)的属性
12 public class TestIntroSpector {
13     
14     //获取bean的所有属性
15     @Test
16     public void test1() throws Exception{
17         //BeanInfo bi=Introspector.getBeanInfo(Person.class);//通过内省Introspector的getBeanInfo(Person.class)方法获取bean的所有属性
18         BeanInfo bi=Introspector.getBeanInfo(Person.class, Object.class);//只获取本身增加的属性,不要从Object类获取的属性 与使用getDisplayName()方法的效果一样
19         PropertyDescriptor [] pd=bi.getPropertyDescriptors();//读取bean的所有属性存到数组pd里面去
20         for(PropertyDescriptor k:pd){
21             System.out.println(k.getName());
22             
23         }
24         
25     }
26     
27     //获取并操作bean指定的属性 age
28     @Test
29     public void test2() throws Exception{
30         Person p=new Person();
31         //使用构造函数 PropertyDescriptor(String 属性名, 对应的bean)操作特定属性
32         PropertyDescriptor pd=new PropertyDescriptor("age", Person.class);
33         
34         //获取属性的写方法,并为属性赋值
35         Method m=pd.getWriteMethod();//获取bean的setAge属性 public void setAge(int age)
36         m.invoke(p, 23);//执行SetAge属性并写入属性值
37         
38         //传统方式获取属性的值
39         System.out.println(p.getAge());
40         
41         //内省获取属性的值
42         Method mt=pd.getReadMethod();//获取getAge()方法 读属性值
43         System.out.println(mt.invoke(p, null));//输出属性值
44         
45     }
46     //获取bean指定的属性的类型 age
47     @Test
48     public void test3() throws Exception{
49         Person p=new Person();
50         //使用构造函数 PropertyDescriptor(String 属性名, 对应的bean)操作特定属性
51         PropertyDescriptor pd=new PropertyDescriptor("age", Person.class);
52         System.out.println(pd.getPropertyType());//获取age属性的类型
53         
54         
55     }
56 
57 }

6.3 使用BeanUtils类操作javabean属性

使用第三方框架beanutils
beanutils的配置过程:
   (1)、新建一个开发库文件夹lib,然后向里面添加commons-beanutils-1.8.0.jar和commons-logging.jar包
   (2)、同时选中上面的两个jar包-右键-build path-add build path
   (3)、当上面的两个jar包在Referenced Libraries(会自动生成这个文件夹)里面变为奶瓶时就可以使用beanutils操作javabean的属性了

 1 package refelect;
 2 
 3 import java.util.Date;
 4 
 5 /**
 6  * Person就是一个javabean 
 7  * 里面的字段有对应的get或者set方法,这个字段就称为一个属性
 8  * 
 9  * @author lgs
10  *
11  */
12 public class Person {
13 
14     // 字段
15     public String name;
16 
17     // 字段
18     private int password;
19 
20     // 字段
21     private int age;
22 
23     // 字段
24     private int score;
25     
26     //生日
27     private Date birthday;
28 
29     public String getName() {
30         return name;
31     }
32 
33     public void setName(String name) {
34         this.name = name;
35     }
36 
37     public int getPassword() {
38         return password;
39     }
40 
41     public void setPassword(int password) {
42         this.password = password;
43     }
44 
45     public int getAge() {
46         return age;
47     }
48 
49     public void setAge(int age) {
50         this.age = age;
51     }
52 
53     public int getScore() {
54         return score;
55     }
56 
57     public void setScore(int score) {
58         this.score = score;
59     }
60 
61     public Date getBirthday() {
62         return birthday;
63     }
64 
65     public void setBirthday(Date birthday) {
66         this.birthday = birthday;
67     }
68 
69 }
  1 package beanutils;
  2 
  3 import java.lang.reflect.InvocationTargetException;
  4 import java.text.ParseException;
  5 import java.text.SimpleDateFormat;
  6 import java.util.Date;
  7 import java.util.HashMap;
  8 import java.util.Map;
  9 
 10 import org.apache.commons.beanutils.BeanUtils;
 11 import org.apache.commons.beanutils.ConversionException;
 12 import org.apache.commons.beanutils.ConvertUtils;
 13 import org.apache.commons.beanutils.Converter;
 14 import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
 15 import org.junit.Test;
 16 
 17 //使用beanutils操作javabean(即Person类)的属性
 18 //使用第三方框架beanutils
 19 //beanutils的配置过程:
 20 //1、新建一个开发库文件夹lib,然后向里面添加commons-beanutils-1.8.0.jar和commons-logging.jar包
 21 //2、同时选中上面的两个jar包-右键-build path-add build path
 22 //3、当上面的两个jar包在Referenced Libraries(会自动生成这个文件夹)里面变为奶瓶时就可以使用beanutils操作javabean的属性了
 23 public class TestBeanUtils {
 24     
 25     //BeanUtils类操作bean属性
 26     @Test
 27     public void test1() throws Exception, Exception{
 28         Person p=new Person();
 29         //通过BeanUtils的setProperty(bean, name, value)方法设置特定的属性的值
 30         //第一个参数代表要设置的bean对象(即Person对象),第二个参数表示要设置的属性名,第三个表示要设置的属性值
 31         BeanUtils.setProperty(p, "name", "fp");//设置bean属性的值
 32         System.out.println(p.getName());
 33         
 34     }
 35     //BeanUtils类操作用户通过表单提交过来的值
 36     @Test
 37     public void test2() throws Exception, Exception{
 38         
 39         //用户通过表单提交过来的值,提交过来的都是字符串
 40         String name="lgs";
 41         String password="123";
 42         String age="23";
 43 
 44         //把用户提交过来的值设置到bean的属性(即Person类的属性)里面去,提交过来的都是字符串
 45         // BeanUtils内部能够把表单提交过来的字符串转变为对应的八种基本数据类型,不能转变为日期这种复杂的数据类型
 46         //如果要转换为日期就必须为BeanUtils注册日期转换器
 47         Person p=new Person();
 48         BeanUtils.setProperty(p, "name", name);//设置bean属性的值
 49         BeanUtils.setProperty(p, "password", password);//设置bean属性的值
 50         BeanUtils.setProperty(p, "age", age);//设置bean属性的值 BeanUtils能够把表单提交过来的字符串转变为对应的八种基本数据类型
 51         System.out.println(p.getName());
 52         System.out.println(p.getPassword());
 53         System.out.println(p.getAge());
 54         
 55         
 56     }
 57     //把用户提交过来的字符串类型的日期 转换为bean里面定义的日期类型(Date类型)的日期 ,自定义转换器
 58     @Test
 59     public void test3() throws Exception, Exception{
 60         
 61         //用户通过表单提交过来的值,提交过来的都是字符串
 62         String name="lgs";
 63         String password="123";
 64         String age="23";
 65         //字符串类型的日期
 66         String birthday="1995-06-06";
 67         
 68         //把用户提交过来的值设置到bean的属性(即Person类的属性)里面去,提交过来的都是字符串
 69         // BeanUtils内部能够把表单提交过来的字符串转变为对应的八种基本数据类型,不能转变为日期这种复杂的数据类型
 70         //如果要转换为日期就必须为BeanUtils注册日期转换器
 71         
 72         //为了让字符串类型的日期赋给bean的birthday(Date类型属性)属性,我们给BeanUtils注册一个日期转换器
 73         //ConvertUtils.register(converter, clazz);
 74         //第一个参数表示要注册的转换器接口,第二个表示要注册的转换器类型
 75         ConvertUtils.register(new Converter(){
 76              public Object convert(Class type, Object value){
 77                 if(value==null){
 78                     return null;
 79                 }
 80                 if(!(value instanceof String)){
 81                     throw new ConversionException("只支持String类型的转换"); 
 82                 }
 83                 String s=(String) value;
 84                 if(s.trim().equals("")){
 85                     return null; 
 86                 }
 87                 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");//指定要转换的日期格式
 88                 try {
 89                     return sdf.parse(s);
 90                 } catch (ParseException e) {
 91                     // TODO Auto-generated catch block
 92                     //e.printStackTrace();
 93                     throw new RuntimeException(e);//异常链e不能断(不能为空),否则不知道抛出的是什么异常
 94                 }
 95                 
 96                  
 97              }
 98         }, Date.class);
 99         Person p=new Person();
100         BeanUtils.setProperty(p, "name", name);//设置bean属性的值
101         BeanUtils.setProperty(p, "password", password);//设置bean属性的值
102         BeanUtils.setProperty(p, "age", age);//设置bean属性的值 BeanUtils能够把表单提交过来的字符串转变为对应的八种基本数据类型
103         BeanUtils.setProperty(p, "birthday", birthday);//只支持八种数据类型的转换,所以在此之前已经为BeanUtils注册了日期转换器
104         System.out.println(p.getName());
105         System.out.println(p.getPassword());
106         System.out.println(p.getAge());
107         System.out.println(p.getBirthday().toLocaleString());
108         
109         
110     }
111     //把用户提交过来的字符串类型的日期 转换为bean里面定义的日期类型(Date类型)的日期 
112     //使用BeanUtils已经写好的转换器
113     @Test
114     public void test4() throws Exception, Exception{
115         
116         //用户通过表单提交过来的值,提交过来的都是字符串
117         String name="lgs";
118         String password="123";
119         String age="23";
120         //字符串类型的日期
121         String birthday="1995-06-06";
122         
123         //注册日期转换器时使用BeanUtils写好的日期转换器
124         //既然已经写好了日期转换器为什么还要自己写呢原因有2个
125         //1、写好的日期转换器DateLocaleConverter有bug,当转入日期为空时,仍会转空日期 此时会报错
126         //2、还有一些转换器没有写,这样就需要自己来写转换器了
127         ConvertUtils.register(new DateLocaleConverter(birthday), Date.class);
128         
129         Person p=new Person();
130         BeanUtils.setProperty(p, "name", name);//设置bean属性的值
131         BeanUtils.setProperty(p, "password", password);//设置bean属性的值
132         BeanUtils.setProperty(p, "age", age);//设置bean属性的值 BeanUtils能够把表单提交过来的字符串转变为对应的八种基本数据类型
133         BeanUtils.setProperty(p, "birthday", birthday);//只支持八种数据类型的转换,所以在此之前已经为BeanUtils注册了日期转换器
134         System.out.println(p.getName());
135         System.out.println(p.getPassword());
136         System.out.println(p.getAge());
137         System.out.println(p.getBirthday());
138         
139         
140     }
141     
142     //定义Map集合存放用户提交的数据
143     @Test
144     public void test5() throws Exception, InvocationTargetException{
145         //定义Map集合封装用户提交的数据   //Map的关键字必须与bean的属性一致,否则不能写入
146         Map m=new HashMap();
147         m.put("name", "yqh");
148         m.put("password", "123456");
149         m.put("age", "20");
150         m.put("birthday", "1995-12-30");
151         
152         //为BeanUtils注册日期转换器转换字符串日期
153         ConvertUtils.register(new DateLocaleConverter(), Date.class);
154         Person bean=new Person();
155         BeanUtils.populate(bean, m);//用Map集合填充bean属性
156         System.out.println(bean.getName());
157         System.out.println(bean.getPassword());
158         System.out.println(bean.getAge());
159         System.out.println(bean.getBirthday());
160     }
161 
162 }

 7. 泛型

7.1 使用泛型(generic)的好处

    使用泛型的好处可以进行类型安全检查,提高了程序的可读性和稳定性

 1 package generic;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 import org.junit.Test;
 7 
 8 public class TestGeneric {
 9 
10     //使用泛型的好处
11     @Test
12     public void test1() {
13         // TODO Auto-generated method stub
14         // 1、最原始的集合
15         List l = new ArrayList();
16         l.add("aaa");
17         // 此时集合中的值明显是一个字符串,但程序员却把字符串转为Integer 编译不会出错但运行会错,相当不安全
18         // Integer i=(Integer) l.get(0);
19 
20         // 使用泛型的好处
21         // 2、定义集合时就利用泛型指定其处理的类型 这样做提高了程序的可读性和稳定性,同时 进行类型安全检查
22         List<String> l1 = new ArrayList<String>();
23         // l1.add(1);//使用泛型的好处可以进行类型安全检查 因为指定的泛型是String,所以传入的值必须为字符串
24         l1.add("1");
25         System.out.println(l1.get(0));
26 
27     }
28 
29 }

7.2 泛型与集合搭配使用及其注意事项

       泛型是给java编译器(javac)使用的;防止在编译阶段向集合插入非法数据,当编译完以后,编译后的class文件不具有泛型信息,所以不影响运行效力,这个过程称之为“擦除”

  1 package generic;
  2 
  3 import java.util.ArrayList;
  4 import java.util.HashMap;
  5 import java.util.Iterator;
  6 import java.util.List;
  7 import java.util.Map;
  8 import java.util.Map.Entry;
  9 import java.util.Set;
 10 
 11 import org.junit.Test;
 12 
 13 public class TestGeneric {
 14 
 15     //使用泛型的好处
 16     @Test
 17     public void test1() {
 18         // TODO Auto-generated method stub
 19         // 1、最原始的集合
 20         List l = new ArrayList();
 21         l.add("aaa");
 22         // 此时集合中的值明显是一个字符串,但程序员却把字符串转为Integer 编译不会出错但运行会错,相当不安全
 23         // Integer i=(Integer) l.get(0);
 24 
 25         // 使用泛型的好处
 26         // 2、定义集合时就利用泛型指定其处理的类型 这样做提高了程序的可读性和稳定性,同时 进行类型安全检查
 27         List<String> l1 = new ArrayList<String>();
 28         // l1.add(1);//使用泛型的好处可以进行类型安全检查 因为指定的泛型是String,所以传入的值必须为字符串
 29         l1.add("1");
 30         System.out.println(l1.get(0));
 31 
 32     }
 33     //集合的存取
 34     @Test
 35     public void test2() {
 36         // TODO Auto-generated method stub
 37         
 38         List<String> l1 = new ArrayList<String>();
 39         // l1.add(1);//使用泛型的好处可以进行类型安全检查 因为指定的泛型是String,所以传入的值必须为字符串
 40         //集合的存
 41         l1.add("1");
 42         l1.add("2");
 43         l1.add("3");
 44         //集合的取
 45         //1、传统方案:使用迭代器
 46         System.out.println("-------1、传统方案:使用迭代器-----");
 47         Iterator<String> it=l1.iterator();
 48         while(it.hasNext()){
 49             System.out.println(it.next());
 50         }
 51         //2、增强for循环
 52         System.out.println("-------2、增强for循环-----");
 53         for(String s:l1){
 54             System.out.println(s);
 55         }
 56         
 57     }
 58     
 59     //Map集合的存取
 60     @Test
 61     public void test3(){
 62         Map<Integer,String> m=new HashMap<Integer,String>();
 63         //Map的存
 64         m.put(1, "aa");
 65         m.put(2, "bb");
 66         m.put(3, "cc");
 67         //Map的取
 68         //传统方式1:keySet;
 69         System.out.println("-------传统方式1:keySet-------");
 70         Set<Integer> s=m.keySet();
 71         Iterator<Integer> it=s.iterator();
 72         while(it.hasNext()){
 73             int i=it.next();
 74             System.out.println(i+" "+m.get(i));
 75         }
 76         
 77         //传统方式2:entrySet 常用
 78         System.out.println("-------传统方式2:entrySet-------");
 79         Set<Entry<Integer, String>> se=m.entrySet();
 80         Iterator<Entry<Integer, String>> ite=se.iterator();
 81         while(ite.hasNext()){
 82             Entry<Integer, String> e=ite.next();
 83             System.out.println(e.getKey()+" "+e.getValue());
 84         }
 85         
 86         //增强for循环 j2ee里面常用的方式(重点)
 87         System.out.println("-------增强for循环-------");
 88         for(Entry<Integer, String> e:m.entrySet()){
 89             System.out.println(e.getKey()+" "+e.getValue());
 90         }
 91     }
 92     //使用泛型时应该注意的问题
 93     @Test
 94     public void test4(){
 95         //注意:当集合两边都使用泛型时,两边的泛型类型必须一致,否则会报错
 96         //但是如果只有一边使用泛型是是可以的
 97         
 98         //两边都使用泛型
 99         ArrayList<String> al=new ArrayList<String>();
100         //ArrayList<String> al=new ArrayList<Object>();
101         //ArrayList<Object> al2=new ArrayList<String>();
102         
103         //只有一边使用泛型
104         ArrayList<String> al3=new ArrayList();
105         ArrayList al4=new ArrayList<String>();
106         
107         //提高阶段:泛型是给java编译器(javac)使用的;防止在编译阶段向集合插入非法数据,
108         //当编译完以后,编译后的class文件不具有泛型信息,所以不影响运行效力,这个过程称之为“擦除”
109         //如l1和l2编译成class文件以后,除了变量名称不一样,其他的是完全一样的
110         List<String> l1 = new ArrayList<String>();
111         List l2 = new ArrayList();
112     }
113 
114 }

7.3 自定义泛型

定义泛型方法:泛型遵循先声明再使用的规则

第一种方式:常规方法

 1 package generic;
 2 
 3 //定义泛型方法
 4 public class DefineGenericMetgod {
 5     
 6     public void testaa(){
 7         aa("aa");//传入的是字符串,就确定了泛型类型为String,就不存在类型强转的情况(这就是泛型的真正意义)
 8     }
 9     //泛型遵循先声明再使用的规则
10     public <T> void aa(T t){
11         
12     }
13     public <E, K, T> void bb(T t,K k,E e){
14         
15     }
16 
17 }

第二种方式:一个泛型作用于多个方法时可以把泛型声明在类上

 1 package generic;
 2 
 3 //定义泛型方法
 4 //当一个泛型作用于多个方法时可以把泛型声明在类上
 5 public class DefineGenericMetgod2<T,K,E> {
 6     
 7     public void testaa(){
 8         //aa("aa");//传入的是字符串,就确定了泛型类型为String,就不存在类型强转的情况(这就是泛型的真正意义)
 9     }
10     //泛型遵循先声明再使用的规则
11     public  T aa(T t){
12         return t;
13         
14     }
15     public  void bb(T t,K k,E e){
16         
17     }
18     //类上的泛型对静态方法不起作用,要重新自定义自己的泛型,注意这个泛型T和类上的泛型T不是同一个
19     public static<T> void cc(T t){
20         
21     }
22 
23 }

7.4 练习

(1) 编写一个泛型方法,交换指定数组元素的位置,记住:一定要使用泛型T定义方法,不能使用诸如String,int子类的类型,那样的话就只能交换一种特定类型的数组

 1 public <T> void swap(T arr[], int pos1, int pos2) {
 2         T temp;
 3         temp = arr[pos1];
 4         arr[pos1] = arr[pos2];
 5         arr[pos2] = temp;
 6     }
 7 
 8     @Test
 9     public void testSwap() {
10         Integer[] i = new Integer[] { 1, 2, 3, 4, 5 };
11         System.out.println("-----交换之前-----");
12         for (Integer k : i) {
13             System.out.println(k);
14         }
15         swap(i, 1, 3);
16         System.out.println("-----交换之后-----");
17         for (Integer k : i) {
18             System.out.println(k);
19         }
20 
21     }

(2) 编写一个泛型方法,接收任意数组,然后颠倒数组里面的元素

     思路:定义两个指针,第一个指针指向数组的第一个元素,第二个指针指向数组的最后一个元素,把两个元素交换,然后把第一个指针加1,第二个指针减1,再交换,如此进行下去知道两个指针的值相同时不在进行交换

 1 public <T> void reverse(T arr[]) {
 2         int first = 0;
 3         int last = arr.length - 1;
 4 
 5         while (true) {
 6             if (first >= last) {
 7                 break;
 8             }
 9             T temp;
10             temp = arr[first];
11             arr[first] = arr[last];
12             arr[last]=temp;
13             first++;
14             last--;
15         }
16     }
17 
18     @Test
19     public void testReverse() {
20         Integer[] i = new Integer[] { 1, 2, 3, 4, 5 };
21         System.out.println("-----颠倒之前-----");
22         for (Integer k : i) {
23             System.out.println(k);
24         }
25         reverse(i);
26         System.out.println("-----颠倒之后-----");
27         for (Integer k : i) {
28             System.out.println(k);
29         }
30     }
原文地址:https://www.cnblogs.com/leeSmall/p/7787075.html