黑马软件工程师_JDK1.5新特性和反射机制

黑马程序员_JDK1.5新特性和反射机制
 

---------------------- android培训 、java培训 、期待与您交流! ----------------------

 

 

 

 

 

 

JDK1.5 新特性 :

静态导入 .

普通的 import 语句可以导入一个类或者某个包中所有的类 .

import static 语句导入

静态导入方法      import static java.lang.Math.*;

 

可变参数 : 一个方法接受的参数个数不固定 .

可变的特点 :

1.       只能出现在参数列表的最后

2.       位于变量类型和变量名之间 , 前后有无空格都可以

3.       调用可变参数和方法时 , 编译器为该可变参数隐含创建一个数组 , 在方法体中以数组的形式访问可变参数 .

 

增强 for 循环

语法 :for(type 变量名 : 集合变量名 ){…}   

注意 :

迭代变量必须在 () 中定义      集合变量可以是数组或实现了 iterable 接口的集合类

 

自动装箱拆箱

Integer iObj=3; 自动把基本数据类型装成一个 Integer 对象在赋给引用变量

syso(iObj+12); 自动拆箱

引入享元数据模式 :flyweight

当对象很小 , 很多个地方要用到这些小的对象 , 可以把这些对象的共性抽取出来封装成一个对象 , 把不同的地方当成方法的参数传递给该对象 . 不同的部分叫做外部状态 , 相同的部分叫做内部状态 .

 

枚举 :

定义的构造方法和其他信息都必须位于元素列表之后 .

枚举中的元素等效于静态的成员变量 . 在调用执行的时候会调用相应的构造方法 .

枚举元素必须位于开始部分 , 元素列表后面用 ; 号与其他元素分隔 ,

枚举相当于一个类 , 其中可以定义构造方法 , 成员变量 , 普通方法和抽象方法 .

带构造方法的枚举 :

1.       构造方法必须私有 ,

2.       如果有多个构造方法 , 看元素类型的参数来选择构造方法 ,MON MON()) 效果一样 , 都是调用默认的构造方法 .

 

带抽象方法的枚举 , 交通灯例子 .

枚举只有一个成员时 , 可以作为一种单例设计模式 . 因为构造方法已经私有化了 , 元素是自然的 new 出来 . 不用 getInstance.

 

public class TestEnum {
    /*最普通的枚举*/
    public enum ColorSelect {
        red, green, yellow, blue;    
    }

    /* 枚举也可以象一般的类一样添加方法和属性,你可以为它添加静态和非静态的属性或方法,这一切都象你在一般的类中做的那样. */
    public enum Season {
        // 枚举列表必须写在最前面,否则编译出错
        winter, spring, summer, fall;

        private final static String location = "Phoenix";        

        public static Season getBest() {
            if (location.equals("Phoenix"))
                return winter;
            else
                return summer;
        }
    }
    /*还可以有构造方法*/
    public enum Temp {
        /*通过括号赋值,而且必须有带参构造器和一属性跟方法,否则编译出错
         * 赋值必须是都赋值或都不赋值,不能一部分赋值一部分不赋值
         * 如果不赋值则不能写构造器,赋值编译也出错*/
        absoluteZero(-459), freezing(32),boiling(212), paperBurns(451);
        
        private final int value;
        public int getValue() {
            return value;
        }
        //构造器默认也只能是private, 从而保证构造函数只能在内部使用
        Temp(int value) {
            this.value = value;
        }
    }

    public static void main(String[] args) {
        /*
         * 枚举类型是一种类型,用于定义变量,以限制变量的赋值 赋值时通过"枚举名.值"来取得相关枚举中的值
         */
        ColorSelect m = ColorSelect.blue;
        switch (m) {
        /*注意:枚举重写了ToString(),说以枚举变量的值是不带前缀的
          *所以为blue而非ColorSelect.blue
          */

   case red:
            System.out.println("color is red");
            break;
        case green:
            System.out.println("color is green");
            break;
        case yellow:
            System.out.println("color is yellow");
            break;
        case blue:
            System.out.println("color is blue");
            break;
        }
        System.out.println("遍历ColorSelect中的值");
        /*通过values()获得枚举值的数组*/
        for (ColorSelect c : ColorSelect.values()) {
            System.out.println(c);
        }  

   System.out.println("枚举ColorSelect中的值有:"+ColorSelect.values().length+"个");

   /*ordinal()返回枚举值在枚举中的索引位置,从0开始*/
  System.out.println(ColorSelect.red.ordinal());//0
  System.out.println(ColorSelect.green.ordinal());//1
  System.out.println(ColorSelect.yellow.ordinal());//2
  System.out.println(ColorSelect.blue.ordinal());//3


  /*枚举默认实现了java.lang.Comparable接口*/ 
  System.out.println(ColorSelect.red.compareTo(ColorSelect.green));


  System.out.println(Season.getBest());
        
        for(Temp t:Temp.values()){
            /*通过getValue()取得相关枚举的值*/
            System.out.println(t+"的值是"+t.getValue());
        }

    }
}
 

 

反射的基石 Class .

Java 类是用于描述一类事物的共性 , 该类事物有什么属性 , 没有什么属性 , 至于这属性的值是什么 , 则是这个类的实例对象来确定的 .Java 程序中的各个 Java 类是同一类事物 , Class 来描述 .

如何得到各个字节码对应的实例对象 (Class 类型 )

1.       类名 .class

2.       对象 .getClass()

3.       Class.rotName(“ 类名 ”)

 

Class.isPrimitive() 是否是原始类型的字节码 .

int.class==Integer.TYPE              //true

TYPE 代表这个类型的基本类型的字节码 .

在源程序中出现的类型 , 都有各自的 Class 实例对象 . 例如 int[],void…

反射 : 就是把 Java 类中的各种成分映射成相应的 java .

为什么要用反射 ?

可以保持最大的灵活度,比如只要根据类名就可以实例化对象,就可以写到配置文件里面,获取这个字符串来实例化对象,如果需要换成别的类,只需要修改配置文件就行了,不然还需要修改源代码再重新编译等等 .

 

构造方法的反射 :

Constructor 类代表某个类的一个构造方法 .

得到某个类所有的构造方法

Constructor [] constructors= Class.forName("java.lang.String").getConstructors();

得到某一个构造方法

Constructor constructor = Class.forName( java.lang.String ).getConstructor(StringBuffer.class);

调用获得的方法时要用到和获得方法相同类型的实例对象 .

创建实例对象 :

通常方式 : String str = new String(new StringBuffer("abc"));

反射方式 : String str = (String)constructor.newInstance(new StringBuffer("abc"));

Class.newInstance() 方法直接用来创建无参的构造方法的实例对象 .

String obj = (String)Class.forName("java.lang.String").newInstance();

 

成员变量的反射 :

Reflectpoint pt1= new ReflectPoint(3,5);

Field fieldY=new ReflectPoint(2,4).getClass.getField(“y”);//fieldY 不是对象身上的变量 , 而是类上的 , 要用它去取某个对象的值要明确他到哪个对象身上去取 .

fieldY.get(pt1);

对于不可见的私有的方法获取     private x;

fieldX.setAccessible(true);

pt1.getClass().getDeclaredField(“x”)

 

成员方法的反射 .

得到类中的某一个方法 :

  Method charAt = Class.forName("java.lang.String").getMethod("charAt", int.class);

调用方法 : 反射方式 : System.out.println(charAt.invoke(str, 1));

用反射得到字节码中的某个方法 , 在用这个方法去作用于某个对象 . 如果调用的第一个参数对象为 null, 代表该 method 对象对应的是一个静态方法 !

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

      Jdk1.5 public Object invoke(Object obj,Object... args)

     Jdk1.4 public Object invoke(Object obj,Object[] args) ,即按 jdk1.4 的语法,需要将一个数组作为参数传递给 invoke 方法时,数组中的每个元素分别对应被调用方法中的一个参数,所以,调用 charAt 方法的代码也可以用 Jdk1.4 改写为 charAt.invoke( str , new Object[]{1}) 形式。

 

 

有相同和元素类型的数组属于同一个类型 , 有相同的 Class.

基本类型的一维数组可以当作 Object 类型使用 , 不能当作 Object[] 类型使用 ;

非基本类型的两种都可以用 .

 

Arrays.asList(); 方法在处理 int[] String[] 时的差异 .

String[] 1.4 的处理 .int[] 1.5 的把整个数组作为一个对象来处理 .

 

ArrayList_HashSet 的比较及 Hashcode 分析 .Hashcode 的作用 ?

Hashcode 作用 : 每一个用到 Hashset 集合的对象 , 在读取和存储的时候都要计算该对象的 Hashcode , 然后存储在 Hashcode 地址段中 . 在我们要操作一个新的对象时 . 我们要判断这个对象是否存在 , 这时计算该对象的 Hashcode , 然后到相应的地址段中去查找该对象是否存在 . 不用从头到尾每个对象查找对比 , 大大的提高了效率 , 两个对象的 equals 方法相等的话他们的 Hashcode 值肯定相同 , 反过来不一定成立了 . 而且当 Hashcode 的值确定以后 , 不要修改参与哈希值计算的数据的值 , 修改后会造成对这个集合操作时找不到原来相对应对象了 . 修改值会导致内存泄露 .

 

反射的作用 . 实现框架功能 .

框架与工具的区别 : 工具类是被用户类调用 , 而框架则是调用用户提供的类 .

框架要解决的核心问题 :

因为在写程序时无法知道要被调用的类名 , 所以在程序中无法直接 new 某个类的实例对象了 , 这就要用到反射的方式来做 . 程序中不要用具体的类的名字 , 而是从一个配置文件中读取 .

配置文件要用一个完整的路径 , 但完整的路径不是硬编码 , 而是通过某种方式运算出来的 .

用类加载器加载 :

ReflectTest.class getClassLoader().getResourceAsStream(“config.properties”);

类加载器加载的是只读的 , 不能保存 .

 

 

 

 

---------------------- android培训 、java培训 、期待与您交流! ----------------------