java基础增强

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

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

package com.study.lgs;
import static java.lang.System.out;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ZhuangXiangChaiXiang {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //1、静态导入
        //out.println("aaa");
        
        //2.自动装箱拆箱:
        Integer i=1;//自动装箱  jdk1.5+才能这样写 否则这样写:Integer i=new Integer(1)
        int j=i;//自动拆箱
        
        //3.自动装箱拆箱的典型应用
        List l=new ArrayList();
        l.add(1);//装箱 把对象1装到list对象l里面去
        l.add(2);
        l.add(3);
    
        //迭代器遍历输出
        Iterator k=l.iterator();
        while(k.hasNext()){
            int j1=(Integer)k.next();
            out.println(j1);
            
            
        }
        /*ArrayList<Integer> al=new ArrayList<Integer>();
        al.add(1);
        al.add(2);
        al.add(3);
        for(Integer k:al){
            out.println(k);
        }*/
    }

}

2. 增强for循环

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

package cn.study.lgs;
import static java.lang.System.out;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.junit.Test;

public class StrongFor {
    
    @Test
    public void test1(){
        //1、遍历数组
        int i[]={1,2,3};
        for(int k:i){
            out.println(k);
        }
    }
    @Test
    public void test2(){
        //2、遍历集合
        List l=new ArrayList();
        l.add(1);
        l.add(2);
        l.add(3);
    //    l.add("aaa");
        
        for(Object o:l){
//            out.println(o); //不用包装直接以对象的形式输出 也可以
            int i=(Integer) o;
            out.println(i);
        }
        }
    @Test
    public void testMap(){
        Map m=new HashMap();
        m.put("1", "aaa");
        m.put("2", "bbb");
        m.put("3", "ccc");
        //1、传统方案取出Map里面的值 1
        Set s=m.keySet();//通过keyset方法把map里面的每个key存到s里面去
        Iterator i=s.iterator();//迭代遍历s里面的key值
        while(i.hasNext()){
//            String key=(String) i.next();
//            String value=(String) m.get(key);
//            out.println(key+"对应的值为:"+value);
            String st=(String) i.next();
            System.out.println(st+ "对应的值为"+m.get(st));
            
//            System.out.println(i.next());  //有错 两次的i.next()不一样
//            System.out.println(m.get(i.next()));
        
            
        }
        
        
    }
    @Test
    public void testMap2(){
        Map m=new HashMap();
        m.put("1", "aaa");
        m.put("2", "bbb");
        m.put("3", "ccc");
        //1、传统方案取出Map里面的值 2
        Set s=m.entrySet();//通过entrySet方法把每组键值存到s中
        Iterator i=s.iterator();//迭代遍历输出s中的值
        while(i.hasNext()){
            Map.Entry me=(Entry) i.next();
            System.out.println(me.getKey()+"对应的值为"+me.getValue());
        }
        
        
        
    }

    @Test
    public void testMap3(){
        Map m=new HashMap();
        m.put("1", "aaa");
        m.put("2", "bbb");
        m.put("3", "ccc");
        //1、增强for循环 1 (keySet实现Iterable泛型接口)
        for(Object o:m.keySet()){
//            String s=(String) o;
//            String value=(String) m.get(o);
//            System.out.println(o+" "+value);
            out.println(o+" "+m.get(o));
        }
        
        
    }
    @Test
    public void testMap4(){
        Map m=new HashMap();
        m.put("1", "aaa");
        m.put("2", "bbb");
        m.put("3", "ccc");
        //1、增强for循环 2 (entrySet实现Iterable泛型接口)
        for(Object o:m.entrySet()){
         Map.Entry me=(Entry) o;
         System.out.println(me.getKey()+" "+me.getValue());
        }
        
        
    }
    
    @Test //增强for循环应该注意的问题 增强for循环只能取数组或者集合里面的数据 不能更改数据;要改数据的话只能用传统方法
    public void test3(){
//        int []i=new int[]{1,2,3};
//        for(int j:i){
//            j=10;//j仅仅是指向取出来的值而已 并不能改变数组里面的值
//            
//        }
//        //传统方法改变数组的值
//        for(int j=0;j<i.length;j++){
//            i[j]=10;
//        }
//        out.println(i[0]);
//        out.println(i[1]);
//        out.println(i[2]);
//        

        List l=new ArrayList();
        l.add("a");
        l.add("b");
        l.add("c");
        for(Object k:l){
            k="d";//k仅仅是指向取出来的值而已 并不能改变集合里面的值
            
        }
        //传统方案删除集合里面的元素
        for(int i=0;i<l.size();i++){
            
            l.removeAll(l);
            
            
            
        }
        l.add("e");
        l.add("e");
        l.add("e");
        System.out.println(l.get(0));
        System.out.println(l.get(1));
        System.out.println(l.get(2));
        
    
    }
}

3. 可变参数

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

package com.study.lgs;
import java.util.Arrays;
import java.util.List;

import org.junit.Test;

public class KeBianCanShu {
    
    @Test
    public void testSum(){
        int []i={1,2,3};
        sum(i);//可变参数里面可以看成一个数组,所以可以向里面传入数组i
        sum(1,2,3);
    }
    //可变参数按数组方式进行处理,只能放在参数列表的最后,一个参数列表中只能有一个可变参数
    
    public void sum(int...nums){
        int sum=0;
        for(int k:nums){
            sum+=k;
        }
        System.out.println(sum);
    }
    @Test
    public void testArrays(){
        List l=Arrays.asList("1","2","3");//传入普通字符串对象
        System.out.println(l);
        
        String [] s={"1","2","3","4"};//传入字符数组对象
        l=Arrays.asList(s);
        System.out.println(l);
        
        //int []i={1,2,3,4,5};
        Integer []i={1,2,3,4,5};
        l=Arrays.asList(i);//传入基本数据类型整型数组对象 List的l会吧i数组看作一个对象,所以输出的l为一个地址,必须使用包装类的对象以对象方式传入才可输出实际的值
        System.out.println(l);
    }

}
package enumeration;

import org.junit.Test;

//枚举的作用:限定某些程序运行时所需要数据的取值范围
enum Grade{
    A,B,C,D
}
public class DefineEnum {
    @Test
    public void test(){
        DefineEnum.printGrade(Grade.A);
    }
    public static void printGrade(Grade a){
        switch(a){
        case A:
            System.out.println("90");
             break;
        case B:
            System.out.println("80");
            break;
        case C:
            System.out.println("70");
            break;
        case D:
            System.out.println("60");
            break;
        default:
            System.out.println("传入参数有错");
            
        }
    }
}

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

package enumeration;

import org.junit.Test;

//枚举的作用:限定某些程序运行时所需要数据的取值范围
//怎样定义枚举的字段、构造函数、方法去封装更多的信息
enum Grade{
    A("100-90"),B("89-80"),C("79-70"),D("69-60");//对枚举进行实例化
    private String value;//定义每个枚举类型里面存的值
    private Grade(String value){
        this.value=value;
    }
    public String getValue(){ //外部对象获取每个枚举类型里面存的值
        return this.value;
    }
}
public class DefineEnum {
    @Test
    public void test(){
        printGrade(Grade.B);
    }
    public void printGrade(Grade a){
        System.out.println(a.getValue());
    }
}

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

package enumeration;

import org.junit.Test;

//枚举的作用:限定某些程序运行时所需要数据的取值范围
//带抽象方法的枚举 实例化时必须实现抽象方法
enum Grade{
    A("100-90") {
        @Override
        public String getLocalValue() {
            // TODO Auto-generated method stub
            return "优";
        }
    },
    B("89-80") {
        @Override
        public String getLocalValue() {
            // TODO Auto-generated method stub
            return "良";
        }
    },
    C("79-70") {
        @Override
        public String getLocalValue() {
            // TODO Auto-generated method stub
            return "中";
        }
    },
    D("69-60") {
        @Override
        public String getLocalValue() {
            // TODO Auto-generated method stub
            return "差";
        }
    };//对枚举进行实例化 必须实现抽象方法
    
    private String value;//定义每个枚举类型里面存的值
    private Grade(String value){
        this.value=value;
    }
    public String getValue(){ //外部对象获取每个枚举类型里面存的值
        return this.value;
    }
    //带抽象方法的枚举
    public abstract String getLocalValue();
}
public class DefineEnum {
    @Test
    public void test(){
        printGrade(Grade.B);
    }
    public void printGrade(Grade a){
        System.out.println(a.getValue());
        System.out.println(a.getLocalValue());
        
    }
}

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

package enumeration;

//定义普通单态设计模式
class Single{
    private static Single sin=null;
    private Single(){}
    private Single(Single sin){
        this.sin=sin;
    }
    public static Single createShiLi(){
        if(sin==null){
            sin=new Single();
        }
        return sin;
        
    }
}
//定义枚举类型单态设计模式 当枚举里面只有一个对象时也属于单态设计模式
enum EnumSingle{
    A;//枚举中声明的每一个枚举值表示枚举类的一个实例化对象
      //m枚举类的构造函数必须是私有的,因为枚举就是用来限制实例化的对象的,如果构造函数为公有的就可以实例化新的对象,不符合枚举规范    
}
public class DefineSingle {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //普通设计模式的实例化
        Single s1=Single.createShiLi();
        Single s2=Single.createShiLi();
        Single s3=Single.createShiLi();
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
        
        

    }

}

 4.6 测试枚举中的常用方法

package enumeration;

import org.junit.Test;

//枚举的作用:限定某些程序运行时所需要数据的取值范围
//带抽象方法的枚举 实例化时必须实现抽象方法
//枚举中声明的每一个枚举值表示枚举类的一个实例化对象
//m枚举类的构造函数必须是私有的,因为枚举就是用来限制实例化的对象的,如果构造函数为公有的就可以实例化新的对象,不符合枚举规范    

enum Grade {
    A("100-90") {
        @Override
        public String getLocalValue() {
            // TODO Auto-generated method stub
            return "优";
        }
    },
    B("89-80") {
        @Override
        public String getLocalValue() {
            // TODO Auto-generated method stub
            return "良";
        }
    },
    C("79-70") {
        @Override
        public String getLocalValue() {
            // TODO Auto-generated method stub
            return "中";
        }
    },
    D("69-60") {
        @Override
        public String getLocalValue() {
            // TODO Auto-generated method stub
            return "差";
        }
    };// 对枚举进行实例化 必须实现抽象方法

    private String value;// 定义每个枚举类型里面存的值

    private Grade(String value) {
        this.value = value;
    }

    public String getValue() { // 外部对象获取每个枚举类型里面存的值
        return this.value;
    }

    // 带抽象方法的枚举
    public abstract String getLocalValue();
}

public class DefineEnum {
    @Test
    public void test() {
        printGrade(Grade.B);
    }

    public void printGrade(Grade a) {
        System.out.println(a.getValue());
        System.out.println(a.getLocalValue());

    }

    // 测试枚举的常用方法
    @Test
    public void test2() {
        System.out.println(Grade.A.name());// name()方法返回枚举的名字
        System.out.println(Grade.A.ordinal());// ordinal()方法返回枚举对象在枚举类中的序号
        String str = "B";
        Grade g = Grade.valueOf(Grade.class, str);// valueOf()方法将某个枚举对象对应的字符串转变为枚举对象
                                                    // 实际开发中用于检测用户提交的字符串是否属于自己定义的枚举类型
                                                    // Grade
                                                    // g=Grade.valueOf(str);
        System.out.println(g);
        // for(Grade g:Grade.values()){ //values()方法获取枚举中的每个值
        // System.out.println(g);
        // }

    }
}

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

package enumeration;

import org.junit.Test;

//定义一个星期的枚举WeekDay
//枚举值:Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
//该枚举有一个方法,调用该方法返回中文格式的日期
enum WeekDay{
    Monday {
        @Override
        public String getChineseDay() {
            // TODO Auto-generated method stub
            return "星期一";
        }
    },
    Tuesday {
        @Override
        public String getChineseDay() {
            // TODO Auto-generated method stub
            return "星期二";
        }
    },
    Wednesday {
        @Override
        public String getChineseDay() {
            // TODO Auto-generated method stub
            return "星期三";
        }
    },
    Thursday {
        @Override
        public String getChineseDay() {
            // TODO Auto-generated method stub
            return "星期四";
        }
    },
    Friday {
        @Override
        public String getChineseDay() {
            // TODO Auto-generated method stub
            return "星期五";
        }
    },
    Saturday {
        @Override
        public String getChineseDay() {
            // TODO Auto-generated method stub
            return "星期六";
        }
    },
    Sunday {
        @Override
        public String getChineseDay() {
            // TODO Auto-generated method stub
            return "星期天";
        }
    };
    public abstract String getChineseDay();
    
}
public class HomeWork {
    
    @Test
    public void test(){
        printDay(WeekDay.Friday);
    }
    public void printDay(WeekDay wd){
        System.out.println(wd.getChineseDay());
    }

}

5. 反射

5.1 反射的概念

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

加载类的三种方式:

package refelect;

public class LoadClass {

    public static void main(String[] args) throws ClassNotFoundException {
        // TODO Auto-generated method stub
        //加载类的方法
        //1、Class类的forName()方法
        Class c1=Class.forName("refelect.Person"); //把类的字节码加载到内存中去
        System.out.println(c1);
        //2、通过对象的getClass()方法
        Person p=new Person();
        Class c2=p.getClass(); //把类的字节码加载到内存中去
        System.out.println(c2);
        //3、通过.class
        Class c3=Person.class; //把类的字节码加载到内存中去
        System.out.println(c3);

    }

}

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

package refelect;

import java.io.InputStream;
import java.util.List;

public class Person {

    public String name = "aaa";

    private int password = 123;

    private static int age = 23;

    public static int score = 90;

    public Person() {
        System.out.println("person");
    }

    public Person(String name) {
        System.out.println("person name");
    }

    public Person(String name, int password) {
        System.out.println("person name password");
    }

    private Person(List list) {
        System.out.println("list");
    }

    public void aa() {
        System.out.println("aa");
    }

    public void aa(String name, int password) {
        System.out.println(name + password);
    }

    public Class[] aa(String name, int[] password) {
        return new Class[] { String.class };
    }

    private void aa(InputStream in) {
        System.out.println(in);
    }

    public static void aa(int num) {
        System.out.println(num);
    }

    public static void main(String[] args) {
        System.out.println("main");
    }
}
package refelect;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

public class GetConstructor {
    
    //通过反射获取类里面的无参构造函数 public Person()
    @Test
    public void test1() throws  Exception{
        //1、获取无参构造函数 public Person()
        Class c1=Class.forName("refelect.Person");//加载类到内存中去
        Constructor cs1=c1.getConstructor(null);//通过传入的可变参数获取对应的构造函数,此处获取无参构造函数
        Person p1=(Person) cs1.newInstance(null);//通过无参构造函数实例化对象
        String s=p1.name;
        System.out.println(s);
    }
    //通过反射获取类里面的有一个参数构造函数  public Person(String name)
    @Test
    public void test2() throws  Exception{
        
        Class c1=Class.forName("refelect.Person");//加载类到内存中去
        Constructor cs1=c1.getConstructor(String.class);//记住:必须传入String.class告知参数类型为字符串,不能传入"aaa"之流
        Person p=(Person) cs1.newInstance("aaa");//通过构造函数实例化对象
        System.out.println(p.name);
    }
    //通过反射获取类里面的有两个参数构造函数 public Person(String name,int passord)
    @Test
    public void test3() throws  Exception{
        
        Class c1=Class.forName("refelect.Person");//加载类到内存中去
        Constructor cs1=c1.getConstructor(String.class,int.class);
        Person p=(Person) cs1.newInstance("aaa",123);
        System.out.println(p.name);
    }
    //通过反射获取类里面的私有带参构造函数  private Person(List l)
    @Test
    public void test4() throws  Exception{
        //getConstructor()方法只能获取public类型的构造函数
        //getDeclaredConstructor()方法能够获取所有声明的构造函数包括私有的
        Class c1=Class.forName("refelect.Person");//加载类到内存中去
        Constructor cs1=c1.getDeclaredConstructor(List.class);
        cs1.setAccessible(true);//记住:一定要暴力地将私有的构造函数属性设置为可以被外部访问,否则将会报错
        Person p=(Person) cs1.newInstance(new ArrayList());
        System.out.println(p.name);
    }
    //创建对象的另一种途径 直接通过反射出的类的newInstance()方法 ,自动调用无参构造函数实例化,以下代码等价于test1
    @Test
    public void test5() throws  Exception{
        //getConstructor()方法只能获取public类型的构造函数
        //getDeclaredConstructor()方法能够获取所有声明的构造函数包括私有的
        Class c1=Class.forName("refelect.Person");//加载类到内存中去
        Person p=(Person) c1.newInstance();
        System.out.println(p.name);
    }

}

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

package refelect;

import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;

import org.junit.Test;

//通过反射获取类里面的方法
public class GetMethods {
    
    //获取方法 public void aa()
    @Test
    public void test1() throws Exception{
    Class c1=Class.forName("refelect.Person");//加载类
    Method m=c1.getMethod("aa", null);//获取类里面的方法 第一个参数指定是哪一个方法,第二个参数指定方法的参数类型
    m.invoke(c1.newInstance(), null);//执行方法,第一个参数指定执行方法需要实例化的对象,第二个参数为需要传入的参数
    }
    
    //获取方法 public void aa(String name,int password)
    @Test
    public void test2() throws Exception{
        Class c1=Class.forName("refelect.Person");//加载类
        Method m=c1.getMethod("aa", String.class,int.class);
        m.invoke(c1.newInstance(), "lgs",21);
    }
    
    //获取方法 public Class[] aa(String name,int[] password)
    @Test
    public void test3() throws Exception{
        Class c1=Class.forName("refelect.Person");//加载类
        Method m=c1.getMethod("aa", String.class,int[].class);
        Class [] cls=(Class[]) m.invoke(c1.newInstance(), "lgs",new int[]{1,2,3});
        System.out.println(cls[0]);
    }
    //获取方法 private void aa(InputStream in)
    @Test
    public void test4() throws Exception{
        Class c1=Class.forName("refelect.Person");//加载类
        Method m=c1.getDeclaredMethod("aa", InputStream.class);//获取私有方法
        m.setAccessible(true);//暴力解除方法私有属性
        m.invoke(c1.newInstance(), new FileInputStream("c:\\1.txt"));
        
    }
    //获取方法 public static void aa(int num)
    @Test
    public void test5() throws Exception{
        Class c1=Class.forName("refelect.Person");//加载类
        Method m=c1.getDeclaredMethod("aa", int.class);//获取私有方法
        
        m.invoke(c1.newInstance(), 23);//静态方法调用时不需要对象,因此第一个参数可以为空
        
    }
    //获取方法 public static void main(String[] args)
    @Test
    public void test6() throws Exception{
        Class c1=Class.forName("refelect.Person");//加载类
        Method m=c1.getDeclaredMethod("main", String[].class);//获取私有方法
        
        //m.invoke(null, new String[]{"1","2"});//错误的 因为在传数组参数进去给main函数的时候会被自动拆分为String s1和String s2 main函数里面没有这两种参数所以报错参数个数不正确
        //m.invoke(null, new Object[]{new String[]{"1","2"}});//静态方法调用时不需要对象,因此第一个参数可以为空,此时main函数会被自动拆分为String[]数组,不会报错
        m.invoke(null, (Object)new String[]{"1","2"});//这哥们不是喜欢把数组拆分为字符串吗,就加Object强制转换骗他我不是数组
    }
}

5.4 通过反射获取类的字段

package refelect;

import java.lang.reflect.Field;

import org.junit.Test;

//通过反射获取字段
public class GetFields {
  //获取字段public String name="lgs";
    @Test
  public void test1() throws Exception{
        
      Class c1=Class.forName("refelect.Person");//加载类
      Field f=c1.getField("name");//获取字段 参数为要获取的字段的名称
     // String s= (String) f.get(c1.newInstance());//获取字段的值  参数为对应的对象
      Object o=f.get(c1.newInstance());//获取字段的值  参数为对应的对象
      
      //获取字段的类型
      Class type=f.getType();
      if(type.equals(String.class)){
          String s=(String) o;
          System.out.println(s);
      }
      
      //设置字段的值
      Person p=(Person) c1.newInstance();
      f.set(p, "yc");
      System.out.println(p.name);

      
  }
    //获取字段private int password=123;
    @Test
      public void test2() throws Exception{
            
          Class c1=Class.forName("refelect.Person");//加载类
          Field f= c1.getDeclaredField("password");
          f.setAccessible(true);//暴力修改字段的可视性为公有
          Object o=f.get(c1.newInstance());
          System.out.println(o);
    }
    //获取字段private static int  age=23;
    @Test
    public void test3() throws Exception{
        
        Class c1=Class.forName("refelect.Person");//加载类
        Field f= c1.getDeclaredField("age");
        f.setAccessible(true);//暴力修改字段的可视性为公有
        Object o=f.get(c1.newInstance());
        System.out.println(o);
    }
    //获取字段public static int  score=90;
    @Test
    public void test4() throws Exception{
        
        Class c1=Class.forName("refelect.Person");//加载类
        Field f= c1.getField("score");
//        Object o=f.get(c1.newInstance());
        System.out.println(f.get(c1.newInstance()));
    }
}

 

 6. 内省(Introspector)

6.1 为什么要学习内省

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

6.2 通过内省操作javabean属性

package refelect;

/**
 * Person就是一个javabean 
 * 里面的字段有对应的get或者set方法,这个字段就称为一个属性
 * 
 * @author lgs
 *
 */
public class Person {

    // 字段
    public String name;

    // 字段
    private int password;

    // 字段
    private int age;

    // 字段
    private int score;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPassword() {
        return password;
    }

    public void setPassword(int password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

}

 

package introspector;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

import org.junit.Test;

//通过内省来操作bean(即Person类)的属性
public class TestIntroSpector {
    
    //获取bean的所有属性
    @Test
    public void test1() throws Exception{
        //BeanInfo bi=Introspector.getBeanInfo(Person.class);//通过内省Introspector的getBeanInfo(Person.class)方法获取bean的所有属性
        BeanInfo bi=Introspector.getBeanInfo(Person.class, Object.class);//只获取本身增加的属性,不要从Object类获取的属性 与使用getDisplayName()方法的效果一样
        PropertyDescriptor [] pd=bi.getPropertyDescriptors();//读取bean的所有属性存到数组pd里面去
        for(PropertyDescriptor k:pd){
            System.out.println(k.getName());
            
        }
        
    }
    
    //获取并操作bean指定的属性 age
    @Test
    public void test2() throws Exception{
        Person p=new Person();
        //使用构造函数 PropertyDescriptor(String 属性名, 对应的bean)操作特定属性
        PropertyDescriptor pd=new PropertyDescriptor("age", Person.class);
        
        //获取属性的写方法,并为属性赋值
        Method m=pd.getWriteMethod();//获取bean的setAge属性 public void setAge(int age)
        m.invoke(p, 23);//执行SetAge属性并写入属性值
        
        //传统方式获取属性的值
        System.out.println(p.getAge());
        
        //内省获取属性的值
        Method mt=pd.getReadMethod();//获取getAge()方法 读属性值
        System.out.println(mt.invoke(p, null));//输出属性值
        
    }
    //获取bean指定的属性的类型 age
    @Test
    public void test3() throws Exception{
        Person p=new Person();
        //使用构造函数 PropertyDescriptor(String 属性名, 对应的bean)操作特定属性
        PropertyDescriptor pd=new PropertyDescriptor("age", Person.class);
        System.out.println(pd.getPropertyType());//获取age属性的类型
        
        
    }

}

 7. 泛型

7.1 使用泛型(generic)的好处

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

package generic;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

public class TestGeneric {

    //使用泛型的好处
    @Test
    public void test1() {
        // TODO Auto-generated method stub
        // 1、最原始的集合
        List l = new ArrayList();
        l.add("aaa");
        // 此时集合中的值明显是一个字符串,但程序员却把字符串转为Integer 编译不会出错但运行会错,相当不安全
        // Integer i=(Integer) l.get(0);

        // 使用泛型的好处
        // 2、定义集合时就利用泛型指定其处理的类型 这样做提高了程序的可读性和稳定性,同时 进行类型安全检查
        List<String> l1 = new ArrayList<String>();
        // l1.add(1);//使用泛型的好处可以进行类型安全检查 因为指定的泛型是String,所以传入的值必须为字符串
        l1.add("1");
        System.out.println(l1.get(0));

    }

}

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

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

package generic;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.junit.Test;

public class TestGeneric {

    //使用泛型的好处
    @Test
    public void test1() {
        // TODO Auto-generated method stub
        // 1、最原始的集合
        List l = new ArrayList();
        l.add("aaa");
        // 此时集合中的值明显是一个字符串,但程序员却把字符串转为Integer 编译不会出错但运行会错,相当不安全
        // Integer i=(Integer) l.get(0);

        // 使用泛型的好处
        // 2、定义集合时就利用泛型指定其处理的类型 这样做提高了程序的可读性和稳定性,同时 进行类型安全检查
        List<String> l1 = new ArrayList<String>();
        // l1.add(1);//使用泛型的好处可以进行类型安全检查 因为指定的泛型是String,所以传入的值必须为字符串
        l1.add("1");
        System.out.println(l1.get(0));

    }
    //集合的存取
    @Test
    public void test2() {
        // TODO Auto-generated method stub
        
        List<String> l1 = new ArrayList<String>();
        // l1.add(1);//使用泛型的好处可以进行类型安全检查 因为指定的泛型是String,所以传入的值必须为字符串
        //集合的存
        l1.add("1");
        l1.add("2");
        l1.add("3");
        //集合的取
        //1、传统方案:使用迭代器
        System.out.println("-------1、传统方案:使用迭代器-----");
        Iterator<String> it=l1.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        //2、增强for循环
        System.out.println("-------2、增强for循环-----");
        for(String s:l1){
            System.out.println(s);
        }
        
    }
    
    //Map集合的存取
    @Test
    public void test3(){
        Map<Integer,String> m=new HashMap<Integer,String>();
        //Map的存
        m.put(1, "aa");
        m.put(2, "bb");
        m.put(3, "cc");
        //Map的取
        //传统方式1:keySet;
        System.out.println("-------传统方式1:keySet-------");
        Set<Integer> s=m.keySet();
        Iterator<Integer> it=s.iterator();
        while(it.hasNext()){
            int i=it.next();
            System.out.println(i+" "+m.get(i));
        }
        
        //传统方式2:entrySet 常用
        System.out.println("-------传统方式2:entrySet-------");
        Set<Entry<Integer, String>> se=m.entrySet();
        Iterator<Entry<Integer, String>> ite=se.iterator();
        while(ite.hasNext()){
            Entry<Integer, String> e=ite.next();
            System.out.println(e.getKey()+" "+e.getValue());
        }
        
        //增强for循环 j2ee里面常用的方式(重点)
        System.out.println("-------增强for循环-------");
        for(Entry<Integer, String> e:m.entrySet()){
            System.out.println(e.getKey()+" "+e.getValue());
        }
    }
    //使用泛型时应该注意的问题
    @Test
    public void test4(){
        //注意:当集合两边都使用泛型时,两边的泛型类型必须一致,否则会报错
        //但是如果只有一边使用泛型是是可以的
        
        //两边都使用泛型
        ArrayList<String> al=new ArrayList<String>();
        //ArrayList<String> al=new ArrayList<Object>();
        //ArrayList<Object> al2=new ArrayList<String>();
        
        //只有一边使用泛型
        ArrayList<String> al3=new ArrayList();
        ArrayList al4=new ArrayList<String>();
        
        //提高阶段:泛型是给java编译器(javac)使用的;防止在编译阶段向集合插入非法数据,
        //当编译完以后,编译后的class文件不具有泛型信息,所以不影响运行效力,这个过程称之为“擦除”
        //如l1和l2编译成class文件以后,除了变量名称不一样,其他的是完全一样的
        List<String> l1 = new ArrayList<String>();
        List l2 = new ArrayList();
    }

}

7.3 自定义泛型

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

第一种方式:常规方法

package generic;

//定义泛型方法
public class DefineGenericMetgod {
    
    public void testaa(){
        aa("aa");//传入的是字符串,就确定了泛型类型为String,就不存在类型强转的情况(这就是泛型的真正意义)
    }
    //泛型遵循先声明再使用的规则
    public <T> void aa(T t){
        
    }
    public <E, K, T> void bb(T t,K k,E e){
        
    }

}

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

package generic;

//定义泛型方法
//当一个泛型作用于多个方法时可以把泛型声明在类上
public class DefineGenericMetgod2<T,K,E> {
    
    public void testaa(){
        //aa("aa");//传入的是字符串,就确定了泛型类型为String,就不存在类型强转的情况(这就是泛型的真正意义)
    }
    //泛型遵循先声明再使用的规则
    public  T aa(T t){
        return t;
        
    }
    public  void bb(T t,K k,E e){
        
    }
    //类上的泛型对静态方法不起作用,要重新自定义自己的泛型,注意这个泛型T和类上的泛型T不是同一个
    public static<T> void cc(T t){
        
    }

}

7.4 练习

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

public <T> void swap(T arr[], int pos1, int pos2) {
        T temp;
        temp = arr[pos1];
        arr[pos1] = arr[pos2];
        arr[pos2] = temp;
    }

    @Test
    public void testSwap() {
        Integer[] i = new Integer[] { 1, 2, 3, 4, 5 };
        System.out.println("-----交换之前-----");
        for (Integer k : i) {
            System.out.println(k);
        }
        swap(i, 1, 3);
        System.out.println("-----交换之后-----");
        for (Integer k : i) {
            System.out.println(k);
        }

    }

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

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

public <T> void reverse(T arr[]) {
        int first = 0;
        int last = arr.length - 1;

        while (true) {
            if (first >= last) {
                break;
            }
            T temp;
            temp = arr[first];
            arr[first] = arr[last];
            arr[last]=temp;
            first++;
            last--;
        }
    }

    @Test
    public void testReverse() {
        Integer[] i = new Integer[] { 1, 2, 3, 4, 5 };
        System.out.println("-----颠倒之前-----");
        for (Integer k : i) {
            System.out.println(k);
        }
        reverse(i);
        System.out.println("-----颠倒之后-----");
        for (Integer k : i) {
            System.out.println(k);
        }
    }

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值