JDK5.0新特性:

 
5.0 新特性:
前提:
1.      JVM 没有变 , 编译器改变
2.      逐渐和 C++ 融合接近(很多开始被遗弃的 C++ 元素又被捡了回来)
3.      程序员开发越发的简单了
 
5 小点:
1 自动封装和自动解封(简单类型和封装类型之间),但只是在必要的时候进行,比如向上就近原则中 public static void method(Byte b){}: 调用这个方法的时候不会像上就近调用 int ,而是直接调用这个方法。
Integer i = 3 // OK 封箱
int i = new Integer(3) // OK 解箱
i++ ; // OK ,i Integer
在方法中的参数也可以自动的封箱解箱,但是如果存在两个方法:
 
方法重载依然存在:
public static void method( Integer I ) { }
public static void method( int I ) { }
这个时候调用 method( 10 ) // 会调用第二个方法,因为封箱和解箱都是在迫不得已的情况下才会被调用。
 
public static void method( Byte b ) { }
public static void method( short s ) { }
这个时候调用 byte b = 1 ; method( byte ) // 会调用第二个方法,因为封箱和解箱都是在迫不得已的情况下才会被调用。
 
   同样存在问题:拿 byte 举例: byte : 256 种( 1 个字节) 然而 Byte : 257 种(多了一个 null   
   所以如果 Integer I = null ; int i = I ; // 会有空指针异常
 
   封装类有个重要的特性:就是封装 0
       自动解箱要注意的:
Byte b = null;
Byte b = 1;
int i = 0; (默认 i=0 ),有二义性,究竟 0 是否是有效数字 0 ,还是没有赋值而使用默认给得值;   所以此时用 Integer 就可以避免这样的二义性。
例如:在 hibernate 中使用 Long 而不是 long 去设定 ID 的类型,则 hibernate 会自动检查类型是否是有效数字
 
2        import
System.out 中的 out System 类得公开静态属性
静态引入:引入一个类里面的静态成员,则访问的时候可以不写类名直接调用静态成员
import static java.lang.System.*; 表示引入 System 中的所有静态属性,则在下面使用的时候 out.println(...);   
insert 可以简化更多 因为可以加入包是静态的方法直接使用
例: import static java.lang.System.*;
public class Test {
       public static void main(String[] args) {
               out.println("sdsd");
              }
       }
3        新的遍历方法而且非常的方便 for/in loop
使用该 loop 得对象必须实现 Interable 接口
例:
String ss[] = { test , text };
For(String s:ss){
        System.out.ptintln(s);
}
 
4        变常参数 public static void m ( String s)  通过编译器的帮忙可以简化很多,比如反射中就不用再把 String.class 先封装在 Class[] 中了 而可以直接的是用。
但是需要注意在一个方法中只能有一个 String s ,其前面可以跟别的类型参数如 int i String s
还有就是如果有两个以上的参数 String s 必须放在最后参数上。
. 先绝对匹配,如果没有匹配的再去调用
. 变参和数组不能同时存在 , 变参即数组
. 不能同时存在多个 ... ,一个方法可以有且只能有一个变参,且该变参只能是参数表中的最后一个
       
5        格式化输出 :
 System.out.printf( %d , 4 ) 完全符合 C 的习惯风格,是很有用的东西。格式在 API 中写的十分的详细。
java.util.Formatter -- 〉格式化输出。
java,util,Scanner -- 〉格式化输入。融合了 BufferedReader+StringTokinizer 的功能
 
四大块 :
1.        枚举 (enum) (一种数据类型) java.lang.Enum
对象要用大写来写
其实 enum 可以用 class 来实现:
Class Season {
       public static final Season SPRINT = new Season() ; // 这就是制定的对象
       private Season() { } // 切记把构造方法写成私有
}
可以很好的控制参数的种类和数量,保证必须按照程序员安排的选择。
提高安全性,避免了无谓的异常抛出。
       同样可以排序:通过 CompareTo() 方法
       直接通过 类名 . 对象 选择所要的对象,而这些对象是程序员写好的,只能是他定义的那几个对象。
       类名 [] c = 类名 .values() 可以得到所有的对象。
      
Enum 中有个很诡异的事情,咱们可以理解 enum ó final c lass 但是 enum 中却可以有抽象方法,而这些抽象方法只能通过定义好的几个对象来实现,而且只能通过匿名的内部类的方法来实现。
      
枚举是一个数据类型 , 是一个 final , 不能有子类
 
类型不安全的枚举类型:
     公开静态常量
 
类型安全的枚举模式:
    将公开静态常量作为 public ,将构造方法私有,实现枚举类型
 
java 5.0 引入的新类: java.lang.Enum
 
实现一个枚举类型,调用该类的 values() 方法,则返回枚举值得数组
final class Season{   // 自己实现的枚举类
       public static final Season SPRING = new Season(" ");
       public static final Season SUMMER = new Season(" ");
}
 
用枚举类 :
enum Season2{
       SPRING(),   // 把参数写在 () 里面
       SUMMER();   // 枚举值和属性之间用 ; 隔开
 
       private String name;
 
       private Season2(String name){   
// 此处不能写 public ,必须是私有的,不写就可以,默认就是 private
              this.name = name;
       }
 
       public String getName(){
              return this.name;
       }
}
. 一个枚举值就是一个枚举对象,构造一个枚举值就是调用相应的构造参数
 
★★ .final 里面不能有枚举类型,枚举本来是 final 但是隐含的可以用匿名内部类去继承,里面却可以有 abstract.
: enum Operation{
       ADD{
              public abstract double caculator(double d1,double d2){
                     return d1+d2;
              }
       },      
// 相当于隐含有一个匿名内部类继承了父类 Operation Operation 类已经成为父类, ADD 其实是匿名内部类的对象
       SUB,
       MUL,
       PROVIDE;
 
       // 抽象方法要求每个枚举值去实现该方法
       public abstract double caculator(double d1,double d2){
             
       }
      
       public static void main(String args[]){
              for(Operation o:)
       }
}
 
2.        泛型:(编译时信息)
很好的解决了集合中对象很难管理其类型的难题。
List<Object> l = new ArrayList<String>() ; // 这是错误的这里不存在多态
List<String> l = new Arraylist<String>() ; // OK
泛型的通配符 <?>
List < ? extends Number > 表示可以是 Number 类和其子类
List < ? super Number > 表示可以使 Number 类和其父类
public static < E > void m( E[] os , List<E> ls ) 这里的 <E> 很像 C++ 中的模版
 
ArrayList 比较数组是类型不安全的,指得是里面的类型强转时有可能转换错误
 
public class TestGenerics1{
       public static void main(String args[]){
              List<String> l = new ArrayList<String>();
              l.add("abc");
              //l.add(123);   // 此处会报错,泛型要求不能放入非字符串
              l.get(0);     // 取得时候也不需要类型转换
 
              for(String s:l){   // for/in loop 打印出 list 里面的东西
                     System.out.println(s);
              }
             
              List<List> l2 = new ArrayList<List>();
              L2.add(new ArrayList());
              L2.add(new LinkedList());
              L2.add(new Vector());
              L2.add(new HashSet());    // 以上都是正确的
 
              Set<Number> s = new HashSet<Number>();
              s.add(1.2);
 
              Map<String,Integer> m = new HashMap<String,Integer>();
              m.put( A ,65);      // 不用强制类型转换了,使用了自动解箱
             
              //List<Object> ll = new ArrayList<String>();
               | 不能这样写,因为对象变量的泛型和对象的泛型必须是一致的,不存在多态
               | 如果这句话对的话, String 泛型就没用了
       }    |
}        |
-------------|--------------------------------------------------------
        /|/ 例:
import static java.lang.System.*;
 
public class TestGenerics2{
       public static void main(String args[]){
              List<String> l1= new ArrayList<String>();
              l1.add("abc");
 
              List<Number> l2 = new ArrayList<Number>();
              l2.add(23);
 
              List<Integer> l3 = new ArrayList<Integer>();
              l3.add(23);  
 
              List<Object> l4 = new ArrayList<Object>();
              l4.add("123");
              l4.add(456);
 
              print(l1);  // 如果下面 print 方法的参数是某一个固定类型的话,或者是 Object, 这块就不能这样写 , 出错          
              print(l2);
 
       }
/
       static void print(List<?> l){   // <?> 是泛型的通配符,表示什么类型都可以,写 Object 的话就写死了,上面的调用就会报错
              for(Object o:l){
                     out.println(o);
              }
       }
/
       // 如果要 l1,l4 不可以调用, l2,l3 可以调用则可以
       static void print(List<? extends Number> l){}  
       //<? extends Number> 带限制范围的泛型通配符 , 表示 ? Number 得子类
/
       // 如果表示都实现了某个接口,依然用 extends
       static void print(List<? extends comparable> l){}  
/
       // 如果要 l2,l4 可以调用, l1,l3 不可以调用则可以
       static void print(List<? super Number> l){} 
       //<? super Number> 表示 ? Number 得父类
      
}
泛型方法,在修饰符和返回值之间写泛型
static void copyArrayToList(Object[] os,List<?> ls){
       for(Object o:os){
              ls.add(o);   // 报错,因为 os 放入 List ,运行的时候 List 不知道究竟是什么类型
       }
}
 
正确的是:
static <E> void copyArrayToList( E [] os,List <E> ls){ 
// 两个参数:一个 E 类型的数组,一个存放 E 对象的 List
 
// 必须要保证数组的类型和泛型的类型时一样的,每个数组是字符串的,每个元素都是字符串,所以每个字符串当然可以放在泛型是字符串的 List , 所以可以使用泛型方法
 
static <E,S extends T> void copyArrayToList( E [] os,List <S> ls){
// 两个参数:一个 E 类型的数组,一个存放 E 或者 E 子类的对象的 List
       for(E o:os){
              ls.add(o); 
       }
}
泛型定义:
<E,T> 表示定义了两个泛型,多个泛型定义用,隔开,那么在后面的方法参数表、集合的类型等处应用这两个泛型
 .E 是什么类型就看调这个方法的时候怎么传参数的
public static void main(String args[]){
              List<String> l1= new ArrayList<String>();
              l1.add("abc");
              Number[] a1 = new Number[10];
 
              List<Number> l2 = new ArrayList<Number>();
              l2.add(23);
              Number[] a1 = new Number[10];
 
              List<Integer> l3 = new ArrayList<Integer>();
              l3.add(23);  
 
              List<Object> l4 = new ArrayList<Object>();
              l4.add("123");
              l4.add(456);
 
 
              copyArrayToList(a1,l1);
...
}
///
// 定义泛型的时候也可以限制范围 , 只能向下不能向上,即只能是 extends ,不能用 super
 
static <E super Numner> void copyArrayToList(ObjectE[] os,List<E> ls){ 
       for(E o:os){
              ls.add(o); 
       }
}
/
      
       // 如果要 E Number 而不是 Integer ,则
       static <E extends Numner&comparator> void copyArrayToList(ObjectE[] os,List<E> ls){ 
       for(E o:os){
              ls.add(o); 
       }
}
<E super Numner&comparator> 类名 & 接口,表示 E 继承 Numner 实现 comparator
 
--------------------------------------------------------------------------
自定义一个泛型类:
public class TestGenerics1{
       public static void main(String args[]){
              MyClass<String> m = new MyClass<String>();
              MyClass<Integer> m2 = new MyClass<Integer>();
              String s = m.get();  
              Integer i = m2.get();
              //System.out.println(m instanseof MyClass<String>);
              // 泛型是编译时概念,到运行的时候什么泛型都没有了, m instanseof MyClass 是到运行时才能确定的,所以这句话是不对的
       }
}
class MyClass <E>{
       public void print(E parameter){
             
       }
 
       public E get(){      // 返回类型是泛型
              return null;
       }
}
    ★注意:
* 不能 new 一个泛型的对象
* 静态方法不能使用类的泛型,
静态变量不能够使用泛型定义
public class MyGenericClass<T> {
 
 public static T value;// 错误的定义
 
}
 
此外,泛型的定义不会被继承,举个例子来说,如果 A B 的子类,而 C 是一个声明了泛型定义的类型的话, C<A> 不是 C<B> 的子类。为了更好的说明,可以看下面的代码,这段代码是
错误的。
 
List<String> strList =new ArrayList<String>();
 
List<Object> objList=strList; // 错误的赋值
 
 
 
不过这样一段代码是正确的:
 
List<Object> strList =new ArrayList<Object>();
 
strList.add("jsdkfjsdl");
 
 
 
 
 
那么,在什么时候我们应该使用统配类型,什么时候我们应该使用泛型函数呢?答案是取决于函数参数之间,函数参数和返回值之间的类型依赖性。
 
如果一个函数的参数类型与函数返回的参数没有必然关联,同时对于该函数其他的参数的类型也没有依赖关系,那么我们就应该使用统配符,否则就应该使用泛型函数。
 
为了更清楚地说明这一点,我们可以看一下 java.util 包中 Collections 类型几个方法的定义:
 
class Collections {
 
        static void swap(List<?> list, int i, int j) {...}
 
        static <T> void copy  (List<? super T> dest, List<? extends T> src)    {...}
 
}
 
其中 swap 函数实际上也可以这样定义:
 
static <T>void swap(List<T> list, int i, int j) {...}
 
但是注意到这里泛型类型参数 T 只在参数中用到了一次,也就是说它和函数其他部分没有依赖性,这可以看作是我们应该使用 ? 的一个标志。
 
copy 方法中,拷贝源 src 中的元素必须是 dest 所能够接受的, src 中的元素必须是 T 的一个子类,但是具体它是哪种子类我们又不必关心,所以方法中使用了泛型作为一个类型参数,
同时也用了统配类型作为第二类型参数
 
 
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炼丹狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值