码迷,mamicode.com
首页 > 编程语言 > 详细

javaEE学习笔记【02】JDK新特性

时间:2015-10-08 21:24:22      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:

  1. 泛型的使用
    原则“使用泛型的时候左右两边要一致!”
    1
    2
    3
    List  list = new ArrayList<String>();     //add提示的是Object
    List<String>  list = new ArrayList ();    //add提示的是String
    List<String>  list = new ArrayList<String>();  //add提示的是String
    以上的语法全对,但是【推荐使用第三种
  2. 泛型的自定义
    如果在定义一个类的时候成员的类型不明确,那么可以先使用泛型进行代替,直到创建该类的对象的时候可以使用具体的数据类型来替换泛型的类型。
    举例1:定义一个方法返回任意数据类型的数据。
    1
    2
    3
    public static <T> T returnType(T t){
        return t;
    }
    如果一个类中很多地方都使用到了泛型,那么可以将泛型的定义放在类上。
    1
    2
    3
    public class Demo1<T>{
       // 非静态成员都可以直接使用T泛型
    }
    如果是静态成员那么不能使用类上定义好的泛型。如果需要的话需要单独的进行声明。
  3. 泛型的继承和实现
    1
    2
    public interface List<E> extends Collection<E>
    public class Person implements Comparable<Person>
  4. 泛型的通配符
    举例1: 实现一个方法可以打印输出任意集合数据?,通配符?可以接收任意泛型集合
    1
    2
    3
    4
    5
    6
    // Collection<Object> coll = new ArrayList<String>()
    public static void printCollection(Collection<?> coll){
        for(Object temp:coll){
            System.out.println(temp);
        }
    }
  5. 泛型的限定
    在通配符的基础上可以对实际的类型进行基本的限制
    1
    2
    ? extends 父类
    ? super 子类
    举例2:实现数字集合的输出,定义泛型只能够继承Number只能为数字
    1
    2
    3
    4
    5
    public static void printCollection(Collection<? extends Number> coll){
            for(Object temp:coll){
                System.out.println(temp);
            }
        }
    1
    查看List的boolean addAll(Collection<? extends E> c) 方法
    注意:在给泛型传递实际的数据类型的时候必须是对象类型,如果是基本数据类型那么默认会自动的进行装箱操作。
  6. 反射:
    反射即将Class类中的所有的成员映射为相应的对象。
    要学习反射那么需要先了解和掌握以下几个类:
      描述
    Class
      描述所有的Class文件的共性
    Field描述的是Class文件的中的属性的共性
    Constrcutor 描述的是Class文件中的构造函数的共性
    Method    
     描述的是Class文件中的函数的共性

  7. 获取指定类的Class对象
    1
    2
    3
    方式一: 类名.class
    方式二: 对象名.getClass()
    方式三: forName(String className) 该方法是Class类的静态方法   推荐
  8. 举例1: 获取字符串类的Class对象。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public static void main(String[] args)throws Exception {
            // 使用不同的方式会过去Class对象
            Class clazz1 = String.class;
            Class clazz2 = new String("jnb").getClass();
           // 参数必须指定类的全名(类的全限定名)
            Class clazz3 = Class.forName("java.lang.String");
            // class文件时候独一无二的,那么Class对象也应该是单例的
            System.out.println(clazz1 == clazz2);   // true
            System.out.println(clazz2 == clazz3);   // true
        }
    以上的方式都可以获取指定类的Class对象,在实际的开发中到底要使用哪一个?
    一般的情况下我们都需要在不知道类名的情况下获取类的Class对象并进而获取类中包含的成员进行操作。
  9. 将Class对象中的属性进行反射为Filed对象,常用的获取属性字段的方法
    方法描述
    Field[] getDeclaredFields()
      获取所有声明的字段数组对象
    Field[] getFields() 获取所有的声明的共有字段数组对象
    Field getDeclaredField(String name)  获取指定名称的声明的字段对象
    Field getField(String name)   
     获取指定名称的声明的共有字段对象
    URL getResource(String name)  
      获取指定名的资源的URL对象
    InputStream getResourceAsStream(String name)    
    获取指定名的资源的输入流对象

  10. 举例1:获取所有的声明字段数组对象。
        
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public static void main(String[] args)throws Exception {
            // 获取Shape类的Class对象
            Class clazz = Class.forName("cn.itcast.bean.Shape");
            // 获取所有的属性
            Field [] fs = clazz.getDeclaredFields();
            System.out.println(fs.length);   // 2
            // 获取所有共有的属性
            fs = clazz.getFields();
            System.out.println(fs.length);   // 1
            // 获取指定名字的私有的属性
            Field field = clazz.getDeclaredField("x");
            System.out.println(field);
            // 获取指定名字的共有的属性
            field = clazz.getField("y");
            System.out.println(field);
        }
  11. 如果获取到了一个类中声明的属性字段,那么可以使用Field类提供的一些常用方法来操作这些属性。
    方法  描述
    String getName()    
    获取属性的名字
    void set(Object obj, Object value) 给属性设置相应的值
    Object get(Object obj) 获取属性的值

  12. 举例2:调用Field类的方法进行字段对象的操作。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public static void main(String[] args)throws Exception {
            // 获取Shape类的Class对象
            Class clazz = Class.forName("cn.itcast.bean.Shape");
            // 获取所有的属性
            Field [] fs = clazz.getDeclaredFields();
            System.out.println(fs.length);   // 2
            // 获取所有共有的属性
            fs = clazz.getFields();
            System.out.println(fs.length);   // 1
            Shape shape = new Shape();   // 20
            // 获取指定名字的私有的属性
            Field field = clazz.getDeclaredField("x");
            System.out.println(field);
            // 操作私有的属性x
            System.out.println("属性名: "+field.getName());
            // 获取x的属性值,需要暴力的反射
            field.setAccessible(true);
            System.out.println("设置之前的x值:"+field.get(shape));
            // 设置x的属性值
            field.set(shape, 20);
            System.out.println("设置之后的x值:"+field.get(shape));
            // 获取指定名字的共有的属性
            field = clazz.getField("y");
            System.out.println(field);
            // 给属性y进行设置值
            System.out.println("属性名: "+field.getName());
            // 获取设置属性值之前的值
            System.out.println("设置之前的y值:"+field.get(shape));  // 20
            field.set(shape,30);         // 30
            System.out.println("设置之后的y值: "+shape.y);   // 30
    }
    以上的代码可以通过程序进行反射类中的属性字段并操作,但是没有进行静态属性的反射和操作。
  13. 举例3:反射静态的成员属性。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public static void main(String[] args)throws Exception {
            // 获取Shape类的Class对象
            Class clazz = Class.forName("cn.itcast.bean.Shape");
            // 获取共有的静态属性
            Field field = clazz.getField("z");
            System.out.println("设置之前的z值: "+field.get(null));
            field.set(null, 40);
            System.out.println("设置之后的z值: "+field.get(null));
    }
  14. 将Class对象中的方法进行反射为Method对象。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public static void main(String[] args)throws Exception {
            // 获取Shape类的Class对象
            Class clazz = Class.forName("cn.itcast.bean.Shape");
            // 获取所有的声明的方法
            Method [] ths = clazz.getDeclaredMethods();
            System.out.println(ths.length); // 2
            // 获取私有的带参数的sayHello方法
            Method sayHello = clazz.getDeclaredMethod("sayHello", String.class);
            System.out.println(sayHello);
            // 调用私有的方法
            sayHello.setAccessible(true);
            sayHello.invoke(new Shape(), "jnb");
            // 获取所有的共有的方法
            ths = clazz.getMethods();
            System.out.println(ths.length); // 10
            // 获取带参数的共有的 方法
            Method greet = clazz.getDeclaredMethod("greet", String.class);
            System.out.println(greet);
            // 方法的调用
            greet.invoke(new Shape(), "焦宁波");
    }
  15. 将Class对象中的构造函数进行反射为Constructor对象。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public static void main(String[] args)throws Exception {
            // 获取Shape类的Class对象
            Class clazz = Class.forName("cn.itcast.bean.Shape");
            // 获取所有的声明的构造函数
            Constructor [] cons = clazz.getDeclaredConstructors();
            System.out.println(cons.length);  // 3
            // 获取带参数的私有的构造函数对象
            Constructor con =
            clazz.getDeclaredConstructor(int.class,int.class);
            System.out.println(con);
            // 暴力反射私有的构造函数创建对象
            con.setAccessible(true);
            Shape myshape = (Shape) con.newInstance(400,500);
            System.out.println(myshape.getX()+","+myshape.y);
            // 获取所有的共有的构造函数
            cons = clazz.getConstructors();
            System.out.println(cons.length);  // 2
            con = clazz.getConstructor(int.class);
            System.out.println(con);
            // 调用构造函数创建对象
            Shape shape = (Shape) con.newInstance(100);
            System.out.println(shape.getX());
    }
  16. 面试题:请简单的叙述出你所可以创建的对象的几种方式?
    第一种:直接使用new关键字
    第二种:Construnctor.newInstance
    第三种:枚举
    第四种:单例、工厂模式
  17. 内省
    其实在以上的反射技术体验中我们发现其实反射的对象一般是一个具有特定功能的一个类。
    引入一个基本的概念:JavaBean
    如果一个类提供了封装好的属性、构造函数(无参数)、共有的get和set方法以及简单的业务逻辑方法那么将这样的一个类称之为JavaBean类。
    对于一个javaBean的操作无非就是给属性值进行操作或函数的调用。
    使用反射比较繁琐,那么SUN就提供了内省的技术方便大家进行JavaBean类的操作。
  18. 内省主要的类以及方法的描述

      描述
    BeanInfo    
    对JavaBean进行描述的接口
    Introspector 描述所有的JavaBean的成员类
    PropertyDescriptor 描述的是JavaBean的属性类主要的操作方法以及描述

  19. 使用内省技术进行简单的属性的操作。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public static void main(String[] args) throws Exception{
            // 获取一个属性的描述器对象就相当于获取了属性的名、set和get方法
            PropertyDescriptor pd = new PropertyDescriptor("name",Book.class);
            // 获取set方法
            Method set = pd.getWriteMethod();
            // 调用该方法设置属性的值
            Book book = new Book();
            System.out.println("设置前获取name属性值:"+book.getName());
            set.invoke(book, "JavaSE进阶");
            System.out.println("设置后获取name属性值:"+book.getName());
            // 获取get方法
            Method get = pd.getReadMethod();
            System.out.println(get.invoke(book, null));
    }
    以上的代码每次都只能操作一个属性,这样就比较繁琐。可以使用其他的类直接获取所有的属性描述器通过循环来直接操作。
  20. 操作属性方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public static void main(String[] args) throws Exception{
           // 获取指定的BeanInfo对象
           BeanInfo info = Introspector.getBeanInfo(Book.class);
           // 获取Book类中的所有的属性的描述器对象
           PropertyDescriptor[] pds = info.getPropertyDescriptors();
           // 输出长度
           System.out.println(pds.length);
           // 查看数组的第一个属性描述器是谁
           PropertyDescriptor pd = pds[0];
           // 作者
           System.out.println(pd.getName());
           Book book = new Book();
           // 给书设置作者信息
           pd.getWriteMethod().invoke(book, "焦宁波");
           System.out.println(pd.getReadMethod().invoke(book, null));
    }
  21. 面试题:一个JavaBean中为什么必须要提供一个无参数的构造函数?
    原因一:为了可以做父类。
    原因二:为了可以使用反射创建对象。
  22. BeanUtils工具
    在实际的开发中我们经常需要将用户的录入的数据进行封装为对象,那么如果使用反射和内省技术就会变得吃力。因此一个开源的操作JavaBean的一个工具即BeanUtils。
    下载:
    1. http://www.apache.org
    2. beanutils-1.8.0.zip
    3. commons-logging.jar
  23. 包的引入:
    在项目中创建一个文件夹如libs,然后将整个项目需要的第三方的jar包可以直接拷贝带该目录,随后打开该目录
    1. 全选->右键->Build path->add path-> 看到奶瓶子即可
  24. 举例1:使用BeanUtils工具封装用户提交的数据。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public static void main(String[] args)throws Exception {
           // 模拟用户的输入的数据如下
           String name = "XML基础";
           String author = "焦宁波";
           String price = "99.99";
           String date = "2013-01-04";
           Book book = new Book();
           // 任务是将以上的属性设置给指定的Book对象
           BeanUtils.setProperty(book, "name", name);
           BeanUtils.setProperty(book, "author", author);
           BeanUtils.setProperty(book, "price",price );
           // 查看属性是否封装好
           System.out.println(book);
    }
    发现使用上面的代码可以省略基本数据类型的转型的问题。进而提高代码的开发效率。
  25. 举例2:自定义一个类型转换器类。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    public static void main(String[] args)throws Exception {
           // 模拟用户的输入的数据如下
           String name = "XML基础";
           String author = "焦宁波";
           String price = "99.99";
           String date = "2013-01-04";
      
           Book book = new Book();
      
           // 注册一个自己的转换器
           /**
            * converter指定具体的转换器
            * clazz遇到什么类型调用上面的转换器
            */
           ConvertUtils.register(
                   new Converter(){
                    // 回调方法 
                    @Override
                    public Object convert(Class type, Object value) {
                        if(value == null){
                            return null;
                        }
                        // 转换为String
                        String data = (String)value;
                        // 将指定格式的字符串转换为Date
                        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                        Date date  = null;
                        try {
                            date = format.parse(data);
                            return date;
                        } catch (ParseException e) {
                            e.printStackTrace();
                            return null;
                        }
                    }
                   },
                   Date.class);
           // 任务是将以上的属性设置给指定的Book对象
           BeanUtils.setProperty(book, "name", name);
           BeanUtils.setProperty(book, "author", author);
           BeanUtils.setProperty(book, "price",price );
           BeanUtils.setProperty(book, "date",date );
           // 查看属性是否封装好
           System.out.println(book);
    }
    如果每次遇到一个复杂类型都需要自定义转换器,那样的话实在麻烦。大家看在开发的时候可以先查看该接口是否提供了有效的实现类。
    1
    ConvertUtils.register(new DateLocaleConverter(), Date.class);
  26. 其实真正的封装好的数据需要存储在数据库中,那么javabean的数据类型应该和数据库的数据类型保持一致,那么在声明持久化javabean的时候需要全部为数据库的基本数据类型。
    因此大家在JavaBean中需要导入的是java.sql.Date类,这样就直接可以将日期自动转换了。
    举例3:实现封装好的JavaBean对象的属性拷贝。
    // 实现属性封装数据的一个拷贝
    1
    2
    3
    4
    Book copy = new Book();
    System.out.println(copy);
    PropertyUtils.copyProperties(copy, book);
    System.out.println(copy);
    思考:如果使用BeanUtils封装用户的数据,那么也就是一个一个设置啊?岂不是也很麻烦?
    其实在真是的环境中我们可以直接获取用户提交的所有的数据信息,只需要进行遍历即可,但是为了方便快速的设置,那么可以将javabean中的属性名和用户提交的数据名保持一致。
  27. 举例1:读取项目根目录下的数据。
    1
    2
    3
    4
    5
    private static void readRoot() throws FileNotFoundException, IOException {
        BufferedReader br = new BufferedReader(new FileReader(new File("jnb.txt")));      
               String line = br.readLine();
               System.out.println(line);
    }
  28. 举例2:读取和class文件同目录的资源数据。
    1
    2
    3
    4
    5
    6
    7
    8
    private static void readClassPath() throws FileNotFoundException,IOException {
            URL url= SoreceReader.class.getResource("jnb.txt");
            String path = url.getPath();
            System.out.println(path);
            BufferedReader br = new BufferedReader(new FileReader(new File(path)));  
            String line = br.readLine();
            System.out.println(line);
    }
  29. 举例3:读取在src目录的资源数据。
    1
    2
    3
    4
    5
    6
    7
    8
    private static void readBin() throws FileNotFoundException, IOException {
            URL url= SoruceReader.class.getResource("../../../jnb.txt");
            String path = url.getPath();
            System.out.println(path);
            BufferedReader br = new BufferedReader(new FileReader(new File(path)));  
            String line = br.readLine();
            System.out.println(line);
    }
  30. 可以直接返回一个指定资源的输入流对象。
    1
    2
    3
    4
    5
    6
    public static void main(String[] args) throws Exception{
        InputStream in = SoreceReader.class.getResourceAsStream("../../../jnb.txt");  
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String line = br.readLine();
            System.out.println(line);
    }
  31. getResourceAsStream 与 getResource的区别
    1. getResourceAsStream直接返回了流对象因此无法获取资源的信息。
    2. getResource直接返回的是资源的绝对路径,那么封装File可以快速的获取资源的信息。所有在文件下载的时候一般使用该方法





javaEE学习笔记【02】JDK新特性

标签:

原文地址:http://www.cnblogs.com/lindongdong/p/a537bee2e0ebb34439a662d2bb8e7b07.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!