• java基础语法要点<二>(基于1.8)


    注解(元数据)

    从jdk5 开始,java支持在源文件中嵌入补充信息,称为注释(annotation)。注释不会改变程序的动作,也就不会改变程序的语义。但在开发和部署期间,各种工具可以使用这类信息。元数据(metadata)也用于表示这一特性。

    RUNTIME保留策略

    设计注释的主要目的是用于其他的开发和部署工具,但是如果为注释指定为RUNTIME保留策略,那么任何程序在运行时都可以使用反射来查询注释(java.lang.reflect,在运行时获取类相关信息的特性),动态地获取一些信息。

    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.reflect.Method;
    
    //@interface声明一个注解类型,注解类型内部有方法声明,不能使用extends子句
    //所有注解类型都自动扩展了Annotation接口(java.lang.annotation,其中重写了hashCode(),equals(),toString()
    //还指定了annotationType()方法)
    
    //保留策略:SOURCE/*只在源文件保留,编译时会被抛弃*/
    //      CLASS /*在编译时存储到.class文件,但运行时通过JVM不能得到这些注释*/
    //      RUNTIME /*在编译时存储到.class文件,并且运行时可以通过JVM获取这些注释*/
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyAnno{
    	 String str();
    	 int val();
    }
    
    class Meta {
    	
    	// 应用注释时,需要为注释的成员提供值。注释的成员看起来像域变量
    	@MyAnno(str = "Annotation Example",val = 100)
    	public static void myMeth(String str,int i){
    		Meta ob = new Meta();
    		
    		try{
    			// 获取Class对象,之后可以获取与类声明中各个条目相关的信息,包括注释
    			Class<?> c = ob.getClass(); 
    			// getMethod,getField,getConstructor
    			Method m = c.getMethod("myMeth",String.class,int.class);
    			
    			// 对Class,Method,Field,Constructor对象调用getAnnotation,可以获得与对象关联的特定注释。
    			// 如果没有注释或保留策略不是RUNTIME,则返回null
    			// MyAnno.class称为 类字面值,当需要已知类的Class对象时,可以用这个表达式:Class<?> c = Meta.class; 
    			MyAnno anno = m.getAnnotation(MyAnno.class);
    			
    			System.out.println(anno.str() + " : "+ anno.val());
    		}
    		catch(NoSuchMethodException e){
    			System.out.println("NoSuchMethodException");
    		}
    	}
    	
    	public static void main(String args[]){
    		myMeth("test",10);
    	}
    }
    
    import java.lang.annotation.Annotation;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.reflect.Method;
    
    
    
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyAnno{
    	String str();
    	int val();
    }
    
    @Retention(RetentionPolicy.RUNTIME)
    @interface What{
           // 默认值
    	String description() default "Testing";
    }
    
    @What(description = "An annotation test class")
    @MyAnno(str = "Meta2", val = 99)
    class Meta2 {
    	
    	@What(description = "An annotation test method")
    	@MyAnno(str = "Testing", val = 100)
    	public static void myMeth(){
    		Meta2 ob = new Meta2();
    		try{
    			// 获取Class对象,之后可以获取与类声明中各个条目相关的信息,包括注释
    			Annotation[] annos =  ob.getClass().getAnnotations();
    			
    			System.out.println("All annotations for Meta2");
    			for (Annotation a:annos){
    				System.out.println(a);
    			}
    			
    			System.out.println();
    			
    			Method m = ob.getClass().getMethod("myMeth");
    			annos = m.getAnnotations();
    			System.out.println("All annotations for myMeth");
    			for (Annotation a:annos){
    				System.out.println(a);
    			}
    		}
    		catch(NoSuchMethodException e){
    			System.out.println("NoSuchMethodException");
    		}
    	}
    	
    	public static void main(String args[]){
    		myMeth();
    	}
    }
    

    单成员注解或其他成员有默认值时,可以使用缩写形式(成员名称必须为value),

    @Rentetion(RentetionPolicy.RUNTIME)
    @interface MySingle{
         int value();
         int xyz() default 0;
    }
    
    class Single{
        @MySingle(88)
         public static void myMeth(){
         } 
    }
    

      getAnnotation(),getAnnotations()由AnnotatedElement接口(java.lang.reflect)定义,

         该接口支持注解反射,类Method,Field,Constructor,Class,Package都实现了这个接口。

      getDeclaredAnnotations() 返回调用对象中存在的所有非继承注解

      isAnnotationPresent(Class<? extends Annotation> annoType) annoType指定的注解与调用对象是否相关联

      jdk 8新增:getDeclaredAnnotation() ,getAnnotationsByType()和getDeclaredAnnotationsByType(),后两个方法自动使用重复注释。

    标记注解

     标记注解是特殊类型的注解,其中不包含成员,唯一目的是标记声明,

    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.reflect.Method;
    
    
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyMarker{}
    
    class Marker {
    	@MyMarker
    	public static void myMeth(){
    		Marker ob =new Marker();
    		try {
    			Method	m = ob.getClass().getMethod("myMeth");
    			if (m.isAnnotationPresent(MyMarker.class)){
    				System.out.println("MyMarker is present");
    			}
    		} 
    		catch (NoSuchMethodException | SecurityException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    	
    	public static void main(String args[]){
    		myMeth();
    	}
    }
    

     

    内置注解

      java提供了许多内置注解,大部分为专有注解,

        但有9个用于一般目的。

        4个来自 java.lang.annotation, 只能注解其他注解

       @Retention /*指定保留策略*/,

       @Documented /*标记注解,用于通知某个工具——注解将被文档化*/,

       @Target /*用于指定可以应用注解的声明的类型*/,

      @Target(ElementType.FIELD),
    
      @Target({ElementType.FIELD,ElementType.LOCAL_VARIABLE})

       @Inherited /*标记注解,只影响用于类声明的注解,会导致超类的注解被子类继承。*/

       5个来自java.lang:

        @Override  /*标记注解,只能用于方法,带有此注解的方法必须重写超类中的方法,否则会编译报错。用于确保超类方法呗真正地重写,而不是简单地重载。*/

        @Deprecated/*标记注解,用于指示声明是过时的,并且已经被更新的形式取代*/

        @FunctionalInterface/*标记注解,jdk 8 新增,用于接口指出被注释的接口是一个函数式接口*/

        @SafeVarargs /*标记注解,只能用于方法和构造函数,指示没有发生与可变长度参数相关的不安全操作。用于移植“未检查不安全代码”警告。只能用于varargs方法或者 声明为static或final的构造函数*/

        @SuppressWarnings/*用于指定能抑制一个或多个编译器可能会报告的警告,使用字符串形式表示的名称来制定要被抑制的警告*/

    类型注解

    从 jdk 8开始,java增加了可以使用注解的地方,如前面的例子,早期的注解只能用于声明。但丛jdk 8开始在能够使用类型的大部分地方,也可以指定注解。扩展后的这种注解 称为 类型注解。

       类型注解 可以注解 方法的返回类型,方法内this的类型,强制转换,数组级别,被继承的类及throws子句,泛型。

       类型注解很重要,因为它们允许工具对代码执行额外的检查。

       类型注解必须包含ElementType.TYPE_USE作为目标。

       jdk 8 新增 TYPE_PARAMETER, ElementType.TYPE_USE

    import java.lang.annotation.*;
    import java.lang.reflect.*;
    
    // 类型注解
    @Target(ElementType.TYPE_USE)
    @interface TypeAnno{}
    
    // 类型注解
    @Target(ElementType.TYPE_USE)
    @interface NotZeroLen{}
    
    // 类型注解
    @Target(ElementType.TYPE_USE)
    @interface Unique{}
    
    // 类型注解
    @Target(ElementType.TYPE_USE)
    @interface MaxLen{
    	int value();
    }
    
    // 非类型注解,用于注解泛型参数声明
    @Target(ElementType.TYPE_PARAMETER)
    @interface What{
    	String description();
    }
    
    // 标记注解
    @Target(ElementType.FIELD)
    @interface EmptyOK{}
    
    // 标记注解
    @Target(ElementType.METHOD)
    @interface Recommended{}
    
    public class TypeAnnoDemo<@What(description = "Generic data type") T> {
    	// 用于构造函数的类型注解
    	public @Unique  TypeAnnoDemo(){}	
    	// 类型注解 用于注解类型,而不是字段
    	@TypeAnno String str;
    	// 注解字段 test
    	@EmptyOK String test;
    	
    	// 注解 this(接收方),this是所有实例方法的隐式参数,它引用的是调用对象。
    	// 丛jdk 8开始,可以显式地将this声明为方法的第一个参数,在这种声明里,this的类型必须是其类的类型
    	public int f(@TypeAnno TypeAnnoDemo<T> this,int x){
    		return 10;
    	}
    	
    	// 注解返回类型
    	public @TypeAnno Integer f2(int j,int k){
    		// 自动封装
    		return j + k;
    	}
    	
    	// 注释 方法声明
    	public @Recommended Integer f3(String str){
    		return str.length();
    	}
    	
    	// 注解 throws 子句
    	public void f4() throws @TypeAnno NullPointerException{
    		// ...
    	}
    	
    	// 注解数组级别
    	String @MaxLen(10) [] @NotZeroLen [] w;
    	
    	// 注解数组元素类型
    	@TypeAnno Integer[] vec;
    	
    	// 注释 extends 子句
    	class SomeClass extends @TypeAnno TypeAnnoDemo<Boolean>{}
    	
    	public static void myMeth(int i){
    		// 注解类型参数
    		TypeAnnoDemo<@TypeAnno Integer> ob = 
    				new TypeAnnoDemo<@TypeAnno Integer>();
    		// 注解 
    		@Unique TypeAnnoDemo<Integer> ob2 = new @Unique TypeAnnoDemo<Integer>();
    		
    		
    		Object x = new Integer(10);
    		Integer y;
    		// 注解 类型转换
    		y = (@TypeAnno Integer) x;
    	}
    	
    	public static void main(String args[]){
    		myMeth(10);
    	}
    }
    

    重复注释

    jdk 8 新增的另一个注解特性 是允许在相同元素上重复应用注释。

    可重复的注释 必须用@Repeatable 进行注解。

    import java.lang.annotation.*;
    import java.lang.reflect.*;
    
    @Retention(RetentionPolicy.RUNTIME)
    // 指定重复注解的容器类型
    @Repeatable(MyRepeatedAnnos.class)
    @interface MyAnno{
    	String str() default "Testing";
    	int val() default 9000;
    }
    
    // 容器
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyRepeatedAnnos{
    	// value是重复注解类型的数组
    	MyAnno[] value();
    }
    
    public class RepeatAnno {
    	
    	@MyAnno(str = "First annotation", val = -1)
    	@MyAnno(str = "Second annotation", val = 100)
    	public static void myMeth(String str,int i){
    		RepeatAnno ob = new RepeatAnno();
    		
    		Class<?> c = ob.getClass();
    		try {
    			Method m = c.getMethod("myMeth", String.class,int.class);
    			
    			// 使用getAnnotation
    			Annotation anno = m.getAnnotation(MyRepeatedAnnos.class);
    			System.out.println(anno);
    			
    			// 使用jdk 8 新增的方法
    			Annotation[] annos = m.getAnnotationsByType(MyAnno.class);
    			for(Annotation a : annos){
    				System.out.println(a);
    			}
    		} 
    		catch (NoSuchMethodException | SecurityException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    	
    	public static void main(String args[]){
    		myMeth("test",100);
    	}
    }
    

     注解的限制:

      一个注解不能继承另一个注解。

      注解声明的方法都不带参数。

      注解不能泛型化。

      注解方法不能指定throws子句。

    类型注解被用来支持在Java的程序中做强类型检查。配合插件式的check framework,可以在编译的时候检测出runtime error,以提高代码质量。

    check framework是第三方工具,配合Java的类型注解效果就是1+1>2。它可以嵌入到javac编译器里面,可以配合ant和maven使用,也可以作为eclipse插件。地址是http://types.cs.washington.edu/checker-framework/。
    check framework可以找到类型注解出现的地方并检查,举个简单的例子:

    import checkers.nullness.quals.*;
    public class GetStarted {
    void sample() {
    @NonNull Object ref = new Object();
    }
    }

    使用javac编译上面的类

    javac -processor checkers.nullness.NullnessChecker GetStarted.java

    编译是通过,但如果修改成:

    @NonNull Object ref = null;

    如果你不想使用类型注解检测出来错误,则不需要processor,直接javac GetStarted.java是可以编译通过的,这是在java 8 with Type Annotation Support版本里面可以,但java 5,6,7版本都不行,因为javac编译器不知道@NonNull是什么东西,但check framework 有个向下兼容的解决方案,就是将类型注解nonnull用/**/注释起来
    ,比如上面例子修改为:

    import checkers.nullness.quals.*;
    public class GetStarted {
    void sample() {
    /*@NonNull*/ Object ref = null;
    }
    }

    这样javac编译器就会忽略掉注释块,但用check framework里面的javac编译器同样能够检测出nonnull错误。
    通过类型注解+check framework我们可以看到,现在runtime error可以在编译时候就能找到。

    Java 8的类型注解:工具和机会(转)

    深入理解Java:注解(Annotation)--注解处理器

      

    I/O 

      通过流执行 I/O,流是一种抽象,流通过java的I/O系统链接到物理设备。所有流的行为方式都是相同的。可以将不同的输入设备(磁盘文件,键盘,网络socket抽象为输入流),对应的输出流可以引用控制台,磁盘文件,网络连接。  

       在java.io中定义了基于流的i/o,在java.nio中还定义了基于缓冲和基于通道的i/o

       java定义了两种流:字节流(在最底层,所有i/o仍然是面向字节的)和字符流(使用unicode编码,便于处理字符)

        

    泛型 

      jdk 5引入了泛型,泛型可以只定义算法一次,使其独立于特定的数据类型,然后将算法应用于各种数据类型而不需要任何额外的工作。

      泛型为语言增加的强大功能从根本上改变了代码的编写方式。

      泛型本质上是提供类型的"类型参数",它们也被称为参数化类型(parameterized type)或参量多态(parametric polymorphism)。

      在引入泛型特性之前,java是通过Object类型的引用变量来操作各种类型的对象,但它们不能以类型安全的方式进行工作。因为需要显式地使用强制类型转换

    // .....
    package N;
    
    public interface Iterator{
    	public Object next (); 
    	public boolean hasNext (); 
    }
    
    
    // .....
    package N;
    
    public interface Collection{
    	public void add(Object x);
    	public Iterator iterator();
    }
    
    
    // .....
    package N;
    
    public class NoSuchElementException extends RuntimeException {
    	
    }
    
    
    // .....
    package N;
    
    public class MyLinkedList implements Collection {
    	protected class Node{
    		Object elt;
    		Node next = null; 
    		
    		Node (Object elt) { this.elt = elt; } 
    	}
    
    	protected Node head = null, tail = null; 
    	
    	public MyLinkedList () {} 
    	
    	@Override
    	public void add(Object elt) {
    		// TODO Auto-generated method stub
    		if (head == null) { head = new Node(elt); tail = head; } 
    		else { tail.next = new Node(elt); tail = tail.next; } 
    	}
    
    	@Override
    	public Iterator iterator() {
    		// TODO Auto-generated method stub
    		return new Iterator () { 
    			 protected Node ptr = head; 
    			 public boolean hasNext () { 
    				 return ptr != null; 
    			 }
    			 public Object next () { 
    				 if (ptr != null) { 
    					 Object elt = ptr.elt; 
    					 ptr = ptr.next; 
    					 return elt;
    				 } 
    				 else {
    					 throw new NoSuchElementException (); 
    				 }
    			 } 
    		};
    	}
    }
    
    
    // .....
    import N.*;
    
    public class Test {
    
    	public static void main(String[] args) {
    		MyLinkedList xs = new MyLinkedList(); 
    		xs.add(new Byte((byte) 0));
    		xs.add(new Byte((byte) 1)); 
    		Iterator xi = xs.iterator();
    		while(xi.hasNext()){
    			Byte x = (Byte)xi.next(); 
    			System.out.println("Byte:"+ x);
    		}
    		
    		System.out.println();
    		MyLinkedList ys = new MyLinkedList();
    		ys.add("zero");
    		ys.add("one"); 
    		Iterator yi = ys.iterator();
    		while(yi.hasNext()){
    			String y = (String) yi.next();
    			System.out.println("String:"+ y);
    		}
    
    		System.out.println();
    		MyLinkedList zs = new MyLinkedList();
    		zs.add(ys);
    		zs.add(ys);
    		Iterator zi = zs.iterator();
    		while(zi.hasNext()){
    			MyLinkedList zlist = (MyLinkedList)zi.next();
    			Iterator zzi = zlist.iterator();
    			while(zzi.hasNext()){
    				String y = (String) zzi.next();
    				System.out.println("String:"+ y);
    			}
    		}
    		
    		Byte w = (Byte)ys.iterator().next(); // run-time exception
    		System.out.println("Byte:"+ w);
    	}
    }
    

     上面的例子,编译器不知道Object的实际类型,无法发现强制类型转换的错误,需要到运行时才会抛出。这一缺陷推迟了发现错误的时间。使用泛型实现,则可以在编译时就发现错误。

    package T;
    
    public interface Collection<T> {
    	 public void add(T x); 
    	 public Iterator<T> iterator(); 
    }
    
    
    // ...
    package T;
    
    public interface Iterator<T> {
    	 public T next(); 
    	 public boolean hasNext(); 
    }
    
    
    // ...
    package T;
    
    import N.NoSuchElementException;
    
    public class MyLinkedList<T> implements Collection<T> {
    	protected class Node{
    		Node next = null;
    		T elt;
    		
    		Node(T elt){
    			this.elt =elt;
    		}
    	}
    	
    	protected Node head = null,tail = null;
    	public MyLinkedList () {}
    	
    	@Override
    	public void add(T x) {
    		// TODO Auto-generated method stub
    		if(head == null){
    			head = new Node(x);
    			tail = head;
    		}
    		else{
    			tail.next = new Node(x);
    			tail = tail.next;
    		}
    	}
    	@Override
    	public Iterator<T> iterator() {
    		// TODO Auto-generated method stub
    		return new Iterator<T> (){
    			protected Node ptr = head;
    			
    			@Override
    			public T next() {
    				// TODO Auto-generated method stub
    				if (ptr != null) { 
    					 T elt = ptr.elt; 
    					 ptr = ptr.next; 
    					 return elt;
    				 } 
    				 else {
    					 throw new NoSuchElementException (); 
    				 }
    			}
    
    			@Override
    			public boolean hasNext() {
    				// TODO Auto-generated method stub
    				return ptr != null;
    			}
    		};
    	} 
    }
    
    
    // ...
    import T.*;
    
    public class Test {
    
    	public static void main(String[] args) {
    		MyLinkedList<Byte> xs = new MyLinkedList<Byte>(); 
    		xs.add(new Byte((byte) 0));
    		xs.add(new Byte((byte) 1)); 
    		Iterator<Byte> xi = xs.iterator();
    		while(xi.hasNext()){
    			Byte x = xi.next(); 
    			System.out.println("Byte:"+ x);
    		}
    		
    		System.out.println();
    		MyLinkedList<String> ys = new MyLinkedList<String>();
    		ys.add("zero");
    		ys.add("one"); 
    		Iterator<String> yi = ys.iterator();
    		while(yi.hasNext()){
    			String y = yi.next();
    			System.out.println("String:"+ y);
    		}
    
    		System.out.println();
    		MyLinkedList<MyLinkedList<String>> zs = new MyLinkedList<MyLinkedList<String>>();
    		zs.add(ys);
    		zs.add(ys);
    		Iterator<MyLinkedList<String>> zi = zs.iterator();
    		while(zi.hasNext()){
    			MyLinkedList<String> zlist = zi.next();
    			Iterator<String> zzi = zlist.iterator();
    			while(zzi.hasNext()){
    				String y = zzi.next();
    				System.out.println("String:"+ y);
    			}
    		}
    	}
    }
    

    String 是 Object 的子类型,因此,我们可以将 String 类型的变量赋值给 Object 类型的变量,甚至可以将 String [ ] 类型的变量(数组)赋值给 Object [ ] 类型的变量,即 String [ ] 是 Object [ ] 的子类型。 但这一特性不适用于泛型。

     List<String> ls = new ArrayList<String>(); 
     List<Object> lo = ls; // 报错,破坏了泛型 的类型安全
    lo.add(new Integer()); 
    String s = ls.get(0);
    

     受限的类型参数(有界类型)

    // 在指定参数类型时,可以声明超类的上界,默认上界是Object
    // 要调用doubleValue(),需要声明 类型参数T必须派生自Number
    // 当需要指定具有一个类和多个接口的边界时,使用 & 运算符连接 它们
    // class Gen(T extends MyClass & MyInterface & MyInterface2 {}
    public class Stats<T extends Number> {
    	T[] nums;
    	
    	Stats(T[] o){
    		nums = o;
    	}
    	
    	double average(){
    		double sum = 0.0;
    		for(int i =0;i<nums.length;i++){
    			sum += nums[i].doubleValue();
    		}
    		return sum / nums.length;
    	}
    	
    	boolean sameAvg(Stats<T> ob){
    		if(average() == ob.average()){
    			return true;
    		}
    		return false;
    	}
    }

    通配符参数

      上例的sameAvg()只有比较双方的类型相同时才能工作,不能比对 Stats<Double>与Stats<Integer>

    // 使用通配符参数 ?
    boolean sameAvg(Stats<?> ob){
    	if(average() == ob.average()){
    		return true;
    	}
    	return false;
    }
    

     上例通配符只是简单地匹配所有有效的Stats对象,范围由Stats声明中的extends子句控制。

      而如同有界参数一样,通配符也可以增加限制,不同在于有界通配符不仅可以有上界<? extends superclass>,也可以有下界<? super subclass>

    class TwoD{
    	int x,y;
    	TwoD(int a,int b){
    		x = a;
    		y =b;
    	}
    }
    class ThreeD extends TwoD{
    	int z;
    	ThreeD(int a,int b, int c){
    		super(a, b);
    		z = c;
    	}
    }
    class FourD extends ThreeD{
    	int t;
    	FourD(int a, int b, int c,int d) {
    		super(a, b, c);
    		t = d;
    	}
    }
    
    class Coords<T extends TwoD>{
    	T[] coords;
    	Coords(T[] o){
    		coords = o;
    	}
    }
    
    public class BoundedWildcards {
    	static void showXY(Coords<?> c){
    		System.out.println("X Y Coordinates:");
    		for (int i = 0; i < c.coords.length; i++) {
    			System.out.println(c.coords[i].x + " " + c.coords[i].y);
    		}
    		System.out.println();
    	}
    	
    	static void showXYZ(Coords<? extends ThreeD> c){
    		System.out.println("X Y Z Coordinates:");
    		for (int i = 0; i < c.coords.length; i++) {
    			System.out.println(c.coords[i].x + " " + c.coords[i].y+ " " + c.coords[i].z);
    		}
    		System.out.println();
    	}
    	
    	static void showAll(Coords<? extends FourD> c){
    		System.out.println("X Y Z T Coordinates:");
    		for (int i = 0; i < c.coords.length; i++) {
    			System.out.println(c.coords[i].x + " " + c.coords[i].y+ " " + c.coords[i].z+ " " + c.coords[i].t);
    		}
    		System.out.println();
    	}
    	
    	public static void main(String[] args) {
    		TwoD td[] = {
    				new TwoD(0, 0),
    				new TwoD(7, 9),
    				new TwoD(18, 4),
    				new TwoD(-1, -23),
    				new TwoD(22, 44)
    		};
    		Coords<TwoD> tdlos = new Coords<>(td);
    		System.out.println("Contens of tdlos:");
    		showXY(tdlos);
    		// 编译报错
    		//showXYZ(tdlos);
    		//showAll(tdlos);
    		
    		FourD fd[] = {
    				new FourD(1, 2, 3, 4),
    				new FourD(6, 8, 9, 14),
    				new FourD(22, 9, 23, 4),
    				new FourD(3, -2, 53, -4),
    		};
    		
    		Coords<FourD> fdlos = new Coords<>(fd);
    		System.out.println("Contens of fdlos:");
    		showXY(fdlos);
    		showXYZ(fdlos);
    		showAll(fdlos);
    	}
    }
    
    public interface Stream<T> extends BaseStream<T, Stream<T>> {
    
        Stream<T> filter(Predicate<? super T> predicate);
    
        <R> Stream<R> map(Function<? super T, ? extends R> mapper);
    
        IntStream mapToInt(ToIntFunction<? super T> mapper);
    
        LongStream mapToLong(ToLongFunction<? super T> mapper);
    
        DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
    
        <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
        // ...
    }
    

      

     前面的是泛型类,泛型参数

    泛型方法的格式 public <T extends Comparable<T>, V extends T> boolean isIn(T x, V[] y){}

    public class GenMethDemo {
    	
    	static <T extends Comparable<T>,V extends T> boolean isIn(T x, V[] y){
    		for (int i = 0; i < y.length; i++) {
    			if(x.equals(y[i])){
    				return true;
    			}
    		}
    		return false;
    	}
    	
    	public static void main(String[] args) {
    		Integer nums[] ={
    				1,2,3,4,5
    		};
    		
    		// 完整形式 GenMethDemo.<Integer,Integer>isIn(2,nums),但对大多数泛型方法,类型推断就足够了
    		if(isIn(2,nums)){
    			System.out.println("2 is in nums");
    		}
    		
    		System.out.println();
    		
    		String strs[] ={
    				"one","two","three","four","five"
    		};
    		
    		if(isIn("two",strs)){
    			System.out.println("two is in strs");
    		}
    	}
    }
    

    泛型构造函数, 可以将构造函数泛型化,即使它们的类不是泛型类

    class GenericConstructor {
    	private double val;
    	
    	<T extends Number> GenericConstructor(T arg){
    		val = arg.doubleValue();
    	}
    	
    	void showVal(){
    		System.out.println("val: "+ val);
    	}
    }
    
    class GenConDemo{
    	public static void main(String[] args) {
    		GenericConstructor test1 = new GenericConstructor(100);
    		GenericConstructor test2 = new GenericConstructor(123.5F);
    		
    		test1.showVal();
    		test2.showVal();
    	}
    }
    

    泛型接口

    使用接口作为泛型的上界时,也用extends, 具体形式与泛型类相同

    package T;
    
    public interface Comparable<T> {
    	int compareTo(T that);
    }
    
    
    // ...
    package T;
    
    public class MyByte implements Comparable<MyByte> {
    	private byte value; 
    	public MyByte(byte value) {this.value = value;} 
    	public byte byteValue() {return value;} 
    	@Override
    	public int compareTo(MyByte that) {
    		return this.value - that.value; 
    	}
    	public String toString(){
    		return "" + value;
    	}
    }
    
    
    // ...
    package T;
    
    public class Collections {
      public static <A extends Comparable<A>> A max (Collection<A> xs){
    		Iterator<A> xi = xs.iterator(); 
    		A w = xi.next(); 
    		while (xi.hasNext()) { 
    		 	A x = xi.next(); 
    			if (w.compareTo(x) < 0) w = x; 
    		} 
    		return w;
    	}
    }
    
    
    // ...
    import T.*;
    
    public class Test {
    
    	public static void main(String[] args) {
    		MyLinkedList<MyByte> xxs = new MyLinkedList<MyByte>(); 
    		xxs.add(new MyByte((byte) 3));
    		xxs.add(new MyByte((byte) 4)); 
    		Iterator<MyByte> xxi = xxs.iterator();
    		while(xxi.hasNext()){
    			MyByte x = xxi.next(); 
    			System.out.println("MyByte:"+ x);
    		}
    		
    		MyByte xx = Collections.max(xxs);
    		System.out.println("max MyByte:"+ xx);
                    System.out.println("type of xx is: "+ xx.getClass().getName());
    	}
    }
    
    // public interface Comparable<T> {}
    interface MinMax<T extends Comparable<T>>{
    	T min();
    	T max();
    }
    
    class MyClass<T extends Comparable<T>> implements MinMax<T>{
    	T[] vals;
    	MyClass(T[] o){
    		vals = o;
    	}
    	@Override
    	public T min() {
    		if (vals.length == 0)return null;
    		T v = vals[0];
    		for (int i = 0; i < vals.length; i++) {
    			if(vals[i].compareTo(v)< 0) {
    				v= vals[i];
    			}
    		}
    		return v;		
    	}
    
    	@Override
    	public T max() {
    		if (vals.length == 0)return null;
    		T v = vals[0];
    		for (int i = 0; i < vals.length; i++) {
    			if(vals[i].compareTo(v)> 0) {
    				v= vals[i];
    			}
    		}
    		return v;	
    	}	
    }
    
    public class GenericInterface {
    	public static void main(String[] args) {
    		Integer inums[]={
    				3,6,2,8,6
    		};
    		Character chs[] ={
    			'b','r','p','w'	
    		};
    		
    		MyClass<Integer> iob = new MyClass<>(inums);
    		MyClass<Character> cob = new MyClass<>(chs);
    		
    		System.out.println("Max value in inums is :" + iob.max());
    		System.out.println("Min value in inums is :" + iob.min());
    		
    		System.out.println("Max value in chs is :" + cob.max());
    		System.out.println("Min value in chs is :" + cob.min());
    	}
    }
    

    因为java的泛型只支持引用类型,不支持基本数据类型。所以jdk 5提供的自动装箱与自动拆箱,可以极大地简化代码,

     而从jdk 7 开始,可以进一步缩短创建泛型实例的语法。

     MyClass<Integer,String> mcOb = new  MyClass<Integer,String>(new Integer(88),"A String");
     MyClass<Integer,String> mcOb = new  MyClass<Integer,String>(88,"A String"); 
     MyClass<Integer,String> mcOb = new  MyClass<>(88,"A String");
    

    泛型层次中的运行时类型比较及强制转换

    泛型类作为超类和子类时,在泛型层次中,所有子类都必须向上传递超累所需的所有类型参数。与沿类层次向上传递构造函数的参数类似。

    class Gen<T>{
    	T ob;
    	Gen(T o){
    		ob = o;
    	}
    }
    class Gen2<T> extends Gen<T>{
    	Gen2(T o){
    		super(o);
    	}
    }
    
    class GenInstanceof {
    	public static void main(String[] args) {
    		Gen<Integer> iOb = new Gen<>(88);
    		Gen2<Integer> iOb2 = new Gen2<>(99);		
    		Gen2<String> strOb2 = new Gen2<>("Generics Test");
    		
    		if(iOb2 instanceof Gen2<?>){
    			System.out.println("iobs is instance of Gen2");
    		}
    		
    		if(iOb2 instanceof Gen<?>){
    			// 强制类型转换,因为iOb2是Gen<Integer>的实例
    			Gen<Integer> iObcast = (Gen<Integer>) iOb2;
    			
    			System.out.println("iobs is instance of Gen");
    		}
    		
    		if(strOb2 instanceof Gen2<?>){
    			System.out.println("strOb2 is instance of Gen2");
    		}
    		
    		if(strOb2 instanceof Gen<?>){
    			System.out.println("strOb2 is instance of Gen");
    		}
    		
    		System.out.println();
    		
    		if(iOb instanceof Gen2<?>){
    			System.out.println("iOb is instance of Gen2");
    		}
    		else{
    			System.out.println("iOb is not instance of Gen2");
    		}
    		
    		if(iOb instanceof Gen<?>){
    			System.out.println("iOb is instance of Gen");
    		}
    
    		//不能编译通过,因为在运行时不能使用泛型类型信息。
    //		if(iOb2 instanceof Gen<Integer>){
    //			System.out.println("iOb2 is instance of Gen<Integer>");
    //		}
    	}
    }
    

    java泛型的实现原理  

    泛型 与 c++ 中的模板很类似,但二者处理泛型类型的方式有本质区别

       在 C++ 模板中,编译器使用提供的类型参数来扩充模板,类似字符替换的过程。

       而在java中,影响泛型实现方式的一个重要约束就是需要与以前的JAVA版本兼容。为此JAVA才用"擦除"实现泛型。java虚拟机是不支持泛型的,java的泛型会在编译过程中,首先转化为不带泛型的普通java程序。所以在运行时没有类型参数,它们只是一种源代码机制。转化过程中包含几个部分:

    • 将参数化类型中的类型参数"擦除"(erasure)掉
    • 将类型变量用"上限(upper bound)"取代,通常情况下这些上限是 Object。增加适当的类型转换,以保持与类型参数所指定类型的兼容性。
      /*
      class Gen<T>{
      	T ob;
      	Gen(T o){
      		ob = o;
      	}
      	T getOb(){
      		return ob;
      	}
      } 
       */
      class Gen{
      	Object ob;
      	Gen(Object o){
      		ob =o;
      	}
      	Object getOb(){
      		return ob;
      	}
      }
      /*
      class Gen2 extends Gen<String>{
      	Gen2(String o) {
      		super(o);
      	}
      } 
       */
      class Gen2 extends Gen{
      	Gen2(String o) {
      		super(o);
      	}
      }
      
      
      class GenericBridgeDemo {
      	public static void main(String[] args) {
      		/*
      		Gen2 strOb2 = new Gen2("Generics Test");
      		String ob = strOb2.getOb();
      		System.out.println(ob); 
      		 */
      		Gen2 strOb2 = new Gen2("Generics Test");
      		String ob = (String) strOb2.getOb();
      		System.out.println(ob);
      	}
      }
      
    • 添加类型转换并插入"桥方法"(bridge method),以便覆盖(overridden)可以正常的工作。
      /*
      interface Comparable<T extends Number> {
      	int compareTo(T that);
      }
       */
      interface Comparable {
      	int compareTo(Number that);
      }
      
      /*
      class MyByte extends Number implements Comparable<MyByte> {
      	private static final long serialVersionUID = 2L;
      	
      	private byte value; 
      	public MyByte(byte value) {this.value = value;} 
      	public byte byteValue() {return value;} 
      	public int intValue() {return value;} 
      	public long longValue() {return value;} 
      	public float floatValue() {return value;} 
      	public double doubleValue() {return value;} 
      	
      	public int compareTo(MyByte that) {
      		return this.value - that.value; 
      	}
      	public String toString(){
      		return "" + value;
      	}
      }
       */
      class MyByte extends Number implements Comparable {
      	private static final long serialVersionUID = 2L;
      	
      	private byte value; 
      	public MyByte(byte value) {this.value = value;} 
      	public byte byteValue() {return value;} 
      	public int intValue() {return value;} 
      	public long longValue() {return value;} 
      	public float floatValue() {return value;} 
      	public double doubleValue() {return value;} 
      	
      	public int compareTo(MyByte that) {
      		return this.value - that.value; 
      	}
      	public String toString(){
      		return "" + value;
      	}
      	
      	// 为了可以正常覆盖超类和接口的方法,引入了桥方法
      	public int compareTo(Number that) {
      		return this.compareTo((MyByte)that);
      	}
      }
      
      
      class GenericBridgeDemo{
      	public static void main(String[] args) {
      		MyByte a = new MyByte((byte)88);
      		MyByte b = new MyByte((byte)77);
      		MyByte c = new MyByte((byte)77);
      		MyByte d = new MyByte((byte)99);
      		
      		System.out.println(a.intValue());
      		System.out.println(a.doubleValue());
      		if (a.compareTo(b) > 0){
      			System.out.println("a > b");
      		}
      		if (a.compareTo(d) < 0){
      			System.out.println("a < d");
      		}
      		if (b.compareTo(c) == 0){
      			System.out.println("b == c");
      		}
      	}
      }
      
    /*
    class Gen2 extends Gen<String>{
    	Gen2(String o) {
    		super(o);
    	}
    	String getOb(){
    		System.out.println("调取 gen2.getOb()");
    		return ob;
    	}
    } 
     */
    class Gen2 extends Gen{
    	Gen2(String o) {
    		super(o);
    	}
    	String getOb(){
    		System.out.println("调取 gen2.getOb()");
    		return (String) ob;
    	}
    	//在 JVM 中,方法定义时所使用的方法签名包括方法的返回类型,所以覆盖需要一个桥方法
    	Object getOb(){
    		return this.getOb();
    	}
    }
    

    java泛型的优点

    • 类型安全。 泛型的一个主要目标就是提高 Java 程序的类型安全。使用泛型可以使编译器知道变量的类型限制,进而可以在更高程度上验证类型假设。如果没有泛型,那么类型的安全性主要由程序员来把握,这显然不如带有泛型的程序安全性高。
    • 消除强制类型转换。泛型可以消除源代码中的许多强制类型转换,这样可以使代码更加可读,并减少出错的机会。
    • 向后兼容。支持泛型的 Java 编译器(例如 JDK5.0 中的 Javac)可以用来编译经过泛型扩充的 Java 程序(GJ 程序),但是现有的没有使用泛型扩充的 Java 程序仍然可以用这些编译器来编译。
    • 层次清晰,恪守规范。无论被编译的源程序是否使用泛型扩充,编译生成的字节码均可被虚拟机接受并执行。也就是说不管编译器的输入是 GJ 程序,还是一般的 Java 程序,经过编译后的字节码都严格遵循《 Java 虚拟机规范》中对字节码的要求。可见,泛型主要是在编译器层面实现的,它对于 Java 虚拟机是透明的。
    • 性能收益。目前来讲,用 GJ 编写的代码和一般的 Java 代码在效率上是非常接近的。 但是由于泛型会给 Java 编译器和虚拟机带来更多的类型信息,因此利用这些信息对 Java 程序做进一步优化将成为可能。
    区别: 
    • Java 语言中的泛型不能接受基本类型作为类型参数――它只能接受引用类型。这意味着可以定义 List<Integer>,但是不可以定义 List<int>。
    • 在 C++ 模板中,编译器使用提供的类型参数来扩充模板,因此,为 List<A> 生成的 C++ 代码不同于为 List<B> 生成的代码,List<A> 和 List<B> 实际上是两个不同的类。
      // 这个可以编译。不过使用这个函数的时候,T必须是包含bar函数的类
      template <typename T>
      void foo(T t) {
       t.bar();
      }
      
      // java 则不行,因为编译器只知道T是一种Object,不知道T的具体类型
      static <T> void foo(T t) {
        t.bar();
      }
    • 而 Java 中的泛型则以不同的方式实现,编译器仅仅对这些类型参数进行擦除和替换。类型 ArrayList<Integer> 和 ArrayList<String> 的对象共享相同的类,并且只存在一个 ArrayList 类。因此在c++中存在为每个模板的实例化产生不同的类型,这一现象被称为“模板代码膨胀”,而java则不存在这个问题的困扰。java中虚拟机中没有泛型,只有基本类型和类类型,泛型会被擦除,一般会修改为Object,如果有限制,例如 T extends Comparable,则会被修改为Comparable。而在C++中不能对模板参数的类型加以限制,如果程序员用一个不适当的类型实例化一个模板,将会在模板代码中报告一个错误信息。

    模糊性错误

    class MyGenClass<T,V extends Number>{
    	T ob1;
    	V ob2;
    	
    	MyGenClass(T o1,V o2){
    		ob1 = o1;
    		ob2 = o2;
    	}
    	
    	void set(T o){
    		ob1 = o;
    	}
    	
    	// 通过编译但存在模糊性错误,这里最好使用不同的方法名
    	void set(V o){
    		ob2 = o;
    	}
    	public String toString(){
    		return ob1+","+ ob2;
    	}
    }
    public class GenericsError {
    	public static void main(String[] args) {
    		MyGenClass<Integer,Integer> iob = new MyGenClass<>(1,2);
    		iob.set(12);
    		System.out.println(iob);
    	}
    }
    

     限制:

    1. 不能创建类型 为参数类型 的实例方法  ob = new T(); T vals[] = new T[10];

    2. 静态成员不能使用在类中声明的类型参数 static T ob;  Static T getOb();

    3. 不能创建特定类型的泛型引用数组

         Gen<Integer> gens[] = new Gen<Integer>[10]; // wrong

         Gen<?> gens[] = new Gen<?>[10] //ok

    4.  同上 运行时比较:

        if( iob instanceof Gen<Integer>){} // wrong

        if(iob instanceof Gen<?>){}

    5. 泛型不能扩展Throwable,即不能创建泛型异常类

    lambda表达式

      java发展过程中从根本上改变代码编写方式的两次变更:jdk 5增加的泛型 和 jdk 8增加的 lambda表达式

     lambda显著增强java,原因有两点:

    1. 它增加了语法元素,使java的表达能力得以提升,并流线化了一些常用结构的实现方式。

    2. 导致api库中增加了新功能,包括利用多核环境的并行处理功能(尤其是处理for-each风格的操作时)变得更加容易。以及支持对数据执行管道操作的新的流api。也催生了其他新的java功能,包括方法引用和接口的默认方法。

     ------------------------------------------------------

    “lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包

     闭包是一个代码块,它可以捕获其上下文中任意的变量和常量,延长其的生存周期以供自己使用,把函数以及这些变量包起来,而可以独立完成一个完整的功能。同时它如同普通数据类型的数据一样可以做参数,可以做返回值,参与了其他代码模块的构建。

    ——————

    java的匿名内部类(没有类型名,因而只会有一个实例,也无法扩展,实例化后立即执行)使用内联的方式使代码出现在使用它的位置。也 基本实现了闭包的功能,一直被称作JAVA的闭包。

    匿名内部类的 捕获策略: 局部变量 必须是final,原因:

    用函数实现闭包,需要提高函数的地位,JAVA坚持了它的面向对象的纯粹性,依然是只有class 为 first class, 使用简单类代替函数。

    用函数实现,捕获的变量会加入参数列表,而函数的参数可以传递指针。类中变量的传入则是依靠构造函数,在匿名类内部建立同名的field,而为了保持内外的一致性,只好全部声明为final。

    匿名内部类实现的闭包,使用起来似乎没有C#,SWIFT那样灵活了,不过考虑到java中基本全是类实现,所以这一限制其实也不算什么问题,不便的是基本数据类型,如果要使用的话,需要借助数组等形式,封装器值的变更实际是在构造新的实例,所以不适用。

    匿名内部类传递的是一个类,不像函数式闭包只能传一个函数,它可以传任意个。虽然可能牺牲了可读性,但在匿名内部类中不光可以实现接口中定义的任意个方法,甚至可以自行添加字段,方法等元素。

    import java.util.ArrayList;
    import java.util.List;
    
    public class Nest {
    	List<Runnable> getList2(int n){
    		List<Runnable> actions = new ArrayList<Runnable>();
    		final int x[] = new int[1];
    		x[0] = 0;
    		for (; x[0] < n; x[0]++)
    	       {
    	             actions.add(
    	        		new Runnable(){
    	        			public void run()
    	    	                       {
    	    	                             System.out.println(x[0]);
    	    	                       }
    	        		}
    	        );
    	    }
    		return actions;
    	}
    	List<Runnable> getList(int n){
    		List<Runnable> actions = new ArrayList<Runnable>();
    		for (int counter=0; counter < n; counter++)
    	      {
    	        final int copy = counter;
    	        actions.add(
    	        		new Runnable(){
    	        			public void run()
    	    	                         {
    	    	                                 System.out.println(copy);
    	    	                        }
    	        		}
    	        );
    	        // Local variable copy defined in an enclosing scope must be final or effectively final
    	        // copy = 10;
    	    }
    		return actions;
    	}
    	public static void main(String[] args)
    	{
    		Nest ccc = new Nest();
    		List<Runnable> actions = ccc.getList(15);
    		print(actions);
    		System.out.println();
    		actions = ccc.getList2(15);
    		print(actions);
    	}
    	
    	static void print(List<Runnable> actions){
    		for (Runnable action : actions)
    	    {
    	        action.run();
    	    }
    	}
    }  

     实现机制

    import java.util.ArrayList;
    import java.util.List;
    
    public class Nest {
    	List<Runnable> getList(int n){
    		List<Runnable> actions = new ArrayList<Runnable>();
    		for (int counter=0; counter < n; counter++)
    	    {
    	        final int copy = counter;
    	        class temp implements Runnable{
    	        	final int copy;
    	        	temp(int copy){
    	        		this.copy = copy;
    	        	}
    	        	
    	        	public void run()
    	            {
    	                System.out.println(copy);
    	            }
    	        }
    	        actions.add(new temp(copy));
    	    }
    		return actions;
    	}
    	public static void main(String[] args)
    	{
    		Nest ccc = new Nest();
    		List<Runnable> actions = ccc.getList(15);
    		print(actions);
    	}
    	
    	static void print(List<Runnable> actions){
    		for (Runnable action : actions)
    	    {
    	        action.run();
    	    }
    	}
    }
    

    扩展:匿名内部类不只可以通过接口实现,也可以通过普通类或抽象类

    public class NormalClass {
    	int x =1;
    	int y =2;
    	public void fun1(){
    		System.out.println(x);
    	}
    	public void fun2(){
    		System.out.println(y);
    	}
    }
    public abstract class AbstractClass {
    	int x =1;
    	int y =2;
    	public void fun1(){
    		System.out.println(x);
    	}
    	public void fun2(){
    		System.out.println(y);
    	}
    }
    
    
    
    public class test {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		AbstractClass a = new AbstractClass(){
    			public void fun1(){
    				System.out.println("w2");
    				
    			}
    			
    		};
    		System.out.println(AbstractClass.class.getSimpleName()+":");
    		a.fun1();
    		a.fun2();
    		
    		NormalClass b = new NormalClass(){
    			public void fun1(){
    				System.out.println("w2");
    				
    			}
    			
    		};
    		System.out.println(NormalClass.class.getSimpleName()+":");
    		b.fun1();
    		b.fun2();
    	}
    }
    //    AbstractClass:
    //    w2
    //    2
    //    NormalClass:
    //    w2
    //    2
    

      

    java的 lambda表达式 就是一个实现单一方法的匿名内部类的简化版。使用lambda表达式 代码变得简洁,可读性提高,代码量也大大减少。

    // 匿名内部类
    button.addActionListener(
        new ActionListener(){
            public void actionPerformed(ActionEventae){
                System.out.println("Actiondetected");
            }
        }
    );
    使用Lambda:
    button.addActionListener(
        ()->{
        System.out.println("Actiondetected");
        }
    );    
    

    不便:

    1 . 用函数实现闭包,函数自身的参数列表和返回值类型本身就自解释了自身的类型。而JAVA的lambda表达式是一个类,它无法独立存在, 需要一个函数式接口来定义一个方法(规定函数的类型),使得代码依然比函数实现要复杂。 jdk 8 同时增加了java.util.funciton包,定义了许多常用的函数式接口。

    2.  局部变量只能捕获 final 修饰符修饰的变量。。

     

    函数式接口是仅包含一个抽象方法(有默认行为的方法不算抽象方法)的接口。即通常仅表示单个动作。此外函数式接口定义了lambda表达式的目标类型。同时Object的公有方法也是函数式接口的隐式成员。

    java中的 lambda表达式 格式:

    ()-> 123.45   // double f(){return 123.45}

    ()-> Math.random()*100 // double f(){ return Math.random()*100;}

    (n)->(n%2)==0 // boolean f(Int n){ return (n%2)==0} 

    (n)->n*2 // 参数类型和返回类型各是什么呢?需要函数式接口的定义

    可以显式指定n的类型: (int n) -> n * 2

    public class Lambda {
    	interface MyNumber{
    		double getValue();
    		default int getNum(){
    			return 10;
    		}
    	}
    	public static void main(String[] args) {
    		MyNumber mynum = ()-> 123;
    		System.out.println(mynum.getValue());
    		System.out.println(mynum.getNum());
    		System.out.println();
    		final MyNumber mynum2 = ()-> Math.random() * 100 ;
    		System.out.println(mynum2.getValue());
    		System.out.println(mynum2.getValue());
    		System.out.println();
    		MyNumber mynum3 = ()->{
    			int result =1;
    			int n = (int)(mynum2.getValue());
    			System.out.println(n);
    			for(int i = 1; i<n;i++){
    				result = (int)(Math.sqrt(result * i)) ;
    			}
    			return result;
    		};
    		System.out.println(mynum3.getValue());
    	}
    }
    
    public class Lambda {
    	interface MyNumber<T extends Number>{
    		void getValue(T o);
    	}
    	public static void main(String[] args) {
    		Lambda l = new Lambda();
    		l.forI().getValue(12); 
    		System.out.println();
    		l.print().getValue(0b1001);
    	}
    	
    	<T extends Number> MyNumber<T> print(){
    		return (n)->{
    			System.out.println(n);
    		};
    	}
    	
    	MyNumber<Integer> forI(){
    		return (n)->{
    			for (int i = 0; i < n; i++) {
    				System.out.println(i);
    			}
    		};
    	}
    }
    

    c#中的闭包:

    namespace Lambda
    {
        class Program
        {
            static  void Main()
            {
                Program aa = new Program();
                List<Action> actions = aa.get();
                //执行动作  
                foreach (Action action in actions)
                {
                    // 是一个函数
                    action();
                }
                Console.ReadKey();
            }
            List<Action> get()
            {
                //定义动作组  
                List<Action> actions = new List<Action>();
                for (int counter = 0; counter < 10; counter++)
                {
                    actions.Add(() => { Console.WriteLine(counter); });
                }
                return actions;
            }
        }
    }

     c#中函数可以作为返回值,作为参数,可以柯里化,但函数不能嵌套函数

    namespace Lambda
    {
        class Program
        {
            static  void Main()
            {
                Program aa = new Program();
    
                Console.WriteLine(aa.get2()(1)(2));
                Console.WriteLine(aa.calculate(1, 2, aa.get2()));
                Console.WriteLine(
                    aa.get3()(
                        () =>
                        {
                            Random r = new Random();
                            return r.Next(100);
                        }
                    )()
                );
                Console.ReadKey();
            }
    
            // 函数可以作为返回值,作为参数,可以柯里化
            Func<int, Func<int, int>> get2()
            {
                return x => y => x + y;
            }
    
            int calculate(int a,int b,Func<int, Func<int, int>> f){
                return f(a)(b);
            }
    
            Func<Func<int>, Func<bool>> get3()
            {
                return (x) =>
                {
                    return () => x() > 50;
                };
            }
        }
    }
    

     lambda表达式可以抛出异常

    interface DoubleNumericArrayFunc{
    	double func(double[] n) throws EmptyArrayException;
    }
    
    class EmptyArrayException extends Exception{
    	EmptyArrayException(){
    		super("Array empty");
    	}
    }
    
    public class LambdaException {
    	public static void main(String[] args) throws EmptyArrayException {
    		double values[] = {1,2,3,4};
    		
    		DoubleNumericArrayFunc average = (n)->{
    			double sum =0;
    			if(n.length == 0){
    				throw new EmptyArrayException();
    			}
    			for (int i = 0; i < n.length; i++) {
    				sum += n[i];
    			}
    			return sum / n.length;
    		};
    		
    		System.out.println("The avarage is : "+ average.func(values));
    		System.out.println("The avarage is : "+ average.func(new double[0]));
    	}
    }
    

    方法引用:

    interface StringFunc{
    	String func(String n);
    }
    class MyStringOps{
    	static String strReverse(String str){
    		String result ="";
    		int i;
    		for (i = str.length() - 1; i >= 0; i--) {
    			result += str.charAt(i);
    		}
    		return result;
    	}
    }
    
    class LambdaRefMethod {
    	static String stringOp(StringFunc sf,String s){
    		return sf.func(s);
    	}
    	public static void main(String[] args) {
    		String inStr = "Lambda add power to java";
    		String outStr;
    		
    		/*
    		 * 可将 对 MyStringOps中声明的静态方法 strReverse 的引用 传递给 stringOp的第一个参数
    		 * 因为strReverse 与 函数式接口 StringFunc 兼容(二者的函数类型一致),用strReverse提供
    		 * 了StringFunc的方法实现。
    		 */
    		outStr = stringOp(MyStringOps::strReverse,inStr);
    		System.out.println("Orginal String : " + inStr);
    		System.out.println("String Reversed : " + outStr);
    	}
    }
    

     上面是静态方法的引用传递,实例方法的引用传递,用实例对象引用方法

    interface StringFunc{
    	String func(String n);
    }
    class MyStringOps{
    	String strReverse(String str){
    		String result ="";
    		int i;
    		for (i = str.length() - 1; i >= 0; i--) {
    			result += str.charAt(i);
    		}
    		return result;
    	}
    }
    
    class LambdaRefMethod {
    	static String stringOp(StringFunc sf,String s){
    		return sf.func(s);
    	}
    	public static void main(String[] args) {
    		String inStr = "Lambda add power to java";
    		String outStr;
    		
    		MyStringOps ops = new MyStringOps();
    		outStr = stringOp(ops::strReverse,inStr);
    		System.out.println("Orginal String : " + inStr);
    		System.out.println("String Reversed : " + outStr);
    	}
    }
    

    对于实例引用,也可以使用类名引用方法。 还可以 用super 引用 方法的 超类版本。  

    interface MyFunc<T>{
    	boolean func(T v1,T v2);
    }
    
    class HighTemp{
    	private int hTemp;
    	HighTemp(int ht) {
    		hTemp = ht;
    	}
    	
    	boolean sameTemp(HighTemp ht2){
    		return hTemp == ht2.hTemp;
    	}
    	
    	boolean lessThenTemp(HighTemp ht2){
    		return hTemp < ht2.hTemp;
    	}
    }
    
    class LambdaRefMethod{
    	static <T> int counter(T[] vals,MyFunc<T> f,T v){
    		int count =0;
    		for (int i = 0; i < vals.length; i++) {
    			if(f.func(vals[i], v)){
    				count ++;
    			}
    		}
    		return count;
    	}
    	
    	public static void main(String[] args) {
    		int count;
    		
    		HighTemp[] weekDayHighs ={
    				new HighTemp(89),new HighTemp(82),
    				new HighTemp(90),new HighTemp(89),
    				new HighTemp(89),new HighTemp(91),
    				new HighTemp(84),new HighTemp(83)
    		};
    		
    		count = counter(weekDayHighs,HighTemp::sameTemp,new HighTemp(89));
    		System.out.println(count + " days had a high of 89");
    		
    		HighTemp[] weekDayHighs2 ={
    				new HighTemp(32),new HighTemp(12),
    				new HighTemp(24),new HighTemp(19),
    				new HighTemp(18),new HighTemp(12),
    				new HighTemp(-1),new HighTemp(13)
    		};
    		count = counter(weekDayHighs2,HighTemp::sameTemp,new HighTemp(12));
    		System.out.println(count + " days had a high of 12");
    		
    		count = counter(weekDayHighs,HighTemp::lessThenTemp,new HighTemp(89));
    		System.out.println(count + " days had a high less than 89");
    		
    		count = counter(weekDayHighs2,HighTemp::lessThenTemp,new HighTemp(19));
    		System.out.println(count + " days had a high less than 19");
    	}
    }
    

    泛型方法的引用

    interface MyFunc<T>{
    	int func(T[] vals,T v);
    }
    
    class MyArrayOps{
    	static <T> int countMatching(T[] vals,T v){
    		int count =0;
    		for (int i = 0; i < vals.length; i++) {
    			if(vals[i] == v)count++;
    		}
    		return count;
    	}
    }
    
    class LambdaRefMethod{
    	static <T> int myOp(MyFunc<T> f, T[] vals,T v){
    		return f.func(vals, v);
    	}
    	
    	public static void main(String[] args) {
    		Integer[] vals = {
    				1,2,3,4,2,3,4,4,5
    		};
    		String[] strs ={
    				"one","two","three","two"
    		};
    		
    		int count;
    		count = myOp(MyArrayOps::<Integer>countMatching,vals,4);
    		System.out.println("vals contains " + count + " 4s");
    		
    		count = myOp(MyArrayOps::<String>countMatching,strs,"two");
    		System.out.println("vals contains " + count + " 4s");
    	}
    }
    
    import java.util.*;
    
    class MyClass{
    	private int val;
    	MyClass(int v){ val = v;}
    	int getVal(){ return val;}
    }
    
    class LambdaRefMethod{
    	static int compareMC(MyClass a,MyClass b){
    		return a.getVal() - b.getVal();
    	}
    	
    	public static void main(String[] args) {
    		ArrayList<MyClass> al = new ArrayList<>();
    		
    		al.add(new MyClass(1));
    		al.add(new MyClass(4));
    		al.add(new MyClass(2));
    		al.add(new MyClass(9));
    		al.add(new MyClass(3));
    		al.add(new MyClass(7));
    		
    		// MyClass 既没有定义自己的比较方法,也没有实现Comparator接口,通过方法引用
    		// 简化了代码
    		MyClass maxValObj = Collections.max(al,LambdaRefMethod::compareMC);
    		System.out.println("Maximum value is : "+maxValObj.getVal() );
    	}
    }
    

     构造函数的引用

    interface MyFunc<R,T>{
    	R func(T n);
    }
    
    class MyClass<T>{
    	private T val;
    	MyClass(T v){ val = v;}
        MyClass(){val = null;}
    	T getVal(){return val;}
    }
    
    class MyClass2{
    	String str;
    	MyClass2(String s){str =s;}
    	MyClass2(){str ="";}
    	String getVal(){return str;}
    }
    
    interface MyArrayCreator<T>{
    	T func (int n);
    }
    
    public class LambdaConstRef {
    	static <R,T> R myClassFactory(MyFunc<R,T> cons,T v){
    		return cons.func(v);
    	}
    	
    	public static void main(String[] args) {
    		MyFunc<MyClass<Double>,Double> myClassCons = MyClass<Double>::new;
    		MyClass<Double> mc = myClassFactory(myClassCons, 100.1);
    		System.out.println("val in mc is " + mc.getVal());
    		
    		MyFunc<MyClass2,String> myClassCons2 = MyClass2::new;
    		MyClass2 mc2 = myClassFactory(myClassCons2, "lambda");
    		System.out.println("str in mc2 is " + mc2.getVal());
    		
    		// 数组
    		MyArrayCreator<MyClass2[]> mcArrayCons = MyClass2[]::new;
    		MyClass2[] aa = mcArrayCons.func(2);
    		aa[0] = new MyClass2("22");
    		aa[1] = new MyClass2("122");
    		System.out.println("aa[1] : " +aa[1].getVal());
    				
    		MyArrayCreator<MyClass<?>[]> mcArrayCons2 = MyClass<?>[]::new;
    		MyClass<?>[] bb = mcArrayCons2.func(2);
    		bb[0] = new MyClass<String>("22");
    		bb[1] = new MyClass<String>("122");
    		System.out.println("bb[1] : " +bb[1].getVal());
    	}
    }
    

    java.util.function.* 中提供了 一些预定义的函数式接口。

    UnaryOperator<T> : 对类型为T的对象应用一元运算,并返回类型为T的结果。包含的方法为apply()

    BinaryOperator<T> :对类型为T的两个对象应用操作,并返回类型为T的结果,包含的方法为apply()

    Consumer<T> :对类型为T的对象应用操作,包含的方法为accept()

    Supplier<T> :返回类型为T的对象,包含的方法为get()

    Function<T,R>:对类型为T的对象应用操作,返回类型为R的结果,包含的方法为apply()

    Predicate<T> :确定类型为T的对象是否满足某种约束,并返回指出结果的布尔值,包含的方法为test()

    import java.util.function.Function;
    public class LambdaFunction {
    	public static void main(String[] args) {
    		Function<Integer,Integer> factorial = (n)->{
    			int result = 1;
    			for(int i =1;i<= n;i++){
    				result =i * result;
    			}
    			return result;
    		};
    		
    		System.out.println("the factorial of 3 : "+factorial.apply(3));
    		System.out.println("the factorial of 5 : "+factorial.apply(5));
    	}
    }

    import java.util.stream.*  在更高的抽象层次上对集合进行操作。

    惰性求值,返回加工后的流。

    及早求值返回另一个值。

    import java.util.Comparator;
    import java.util.List;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    class FunctionalProgramming {
    	public static void main(String[] args) {
    		// map
    		List<String> s = Stream.of('a','b','c').map(c->(char)(c+4)+"").collect(Collectors.toList());
    		// filter
    		List<String> s2 = Stream.of("a","b","c","d").filter(str->str!="d").collect(Collectors.toList());
    		// flatMap
    		List<String> s3 = Stream.of(s,s2).flatMap(numbers->numbers.stream()).collect(Collectors.toList());
    		System.out.println(s3);
    		
    		// reduce
    		String all = s3.stream().reduce("all: ",(o,str)->o+str);
    		System.out.println(all);		
    		
    		// min
    		String min = s3.stream().min(Comparator.comparing(str->str.charAt(0))).get();
    		System.out.println(min);
    		
    		// max
    		String max = s3.stream().max(Comparator.comparing(str->str.charAt(0))).get();
    		System.out.println(max);
    	}
    }
    
    flatMap的实现与swift中差别很大

      

     总结:

    缺点

    1。两个不方便

    2。没有语言层面的惰性求值

    优点

    1。lambda的加入 简化了代码,易读的代码可以更多地表达业务逻辑的意图,而不是它的实现机制。也更易于维护,更可靠,更不容易出错。

    2。面向对象是对数据抽象,函数式编程则抽象了行为。让代码在多核CPU上高效运行。

    其他主题

      类型修饰符: transient, volatile

      class T{

         transient int a;

         int b;

      }

      如果将T的对象写入永久存储区域时,不会保存a的内容,但会保存b的内容。

      volatile 告诉编译器,必须总是精确读取变量的最新值。

     instanceof:

     strictfp: 在java2 时,浮点计算模型扫尾宽松了一些, 这个修饰符告诉java定义内的所有浮点数都采用原始的计算模型。

     native: 声明本地代码方法。

         偶尔可能需要调用非JAVA语言编写的子例程,这类子例程作为可执行代码(对于正在使用的CPU和环境而言是可执行代码,即本地代码)而存在。一旦方法使用native声明,就可以从JAVA程序内部调用这些方法。

    public class NativeDemo {
    	int i;
    	
    	public static void main(String args[]){
    		NativeDemo ob = new NativeDemo();
    		
    		ob.i = 10;
    		System.out.println("This is ob.i before the native method :" + ob.i);
    		ob.test();
    		System.out.println("This is ob.i after the native method :"+ ob.i);
    	}
    	
    	// declare native method
    	public native void test();
    	
    	// load DLL that contains static method
    	static{
    		// 动态链接库,从JDK 8开始可以创建静态链接库
    		System.loadLibrary("NativeDemo");
    	}
    }
    

     assert:

    public class AssertDemo {
    	static int val = 3;
    	
    	static int getNum(){
    		return val--;
    	}
    	
    	public static void main(String args[]){
    		int n = 0;
    		
    		for(int i = 0; i<10;i++){
    			n = getNum();
    			assert n > 0 :"n is negative";
    			System.out.println("n is "+ n);
    		}
    	}
    }
    

    Run -> Run Configurations -> Arguments页签 -> VM arguments文本框中加上断言开启的标志:-enableassertions 或者-ea 就可以了  

    静态导入: 导入接口或类的静态成员

    import static java.lang.Math.sqrt;
    import static java.lang.Math.pow;
    //import static java.lang.Math.*;
    
    public class StaticImport {
    	public static void main(String[] args) {
    		double side1,side2;
    		double hypot;
    		
    		side1 = 3.0;
    		side2 = 4.0;
    		hypot = sqrt(pow(side1,2) +pow(side2,2));
    		
    		System.out.println("Given sides of lengths " + side1 + " and " + side2 + " the hypotenuse is " + hypot);	
    	}
    }
    

     优点:简化并缩短了使用静态成员的代码

       缺点: 1,可读性变差(该静态成员来自哪里)

                2,可能的命名空间冲突

       仅针对重复使用某静态成员时设计,如执行一系列数学计算。但不能滥用这一特性。

    通过this()调用重载的构造函数

    class ThisConstructor {
    	int a;
    	int b;
    	
    	ThisConstructor(int i,int j){
    		a = i; 
    		b = j;
    	}
    	
    	ThisConstructor(int i){
    		a = i;
    		b = i;
    	}
    	
    	ThisConstructor(){
    		a = 0;
    		b = 0;
    	}
    }
    
    class ThisConstructor2 {
    	int a;
    	int b;
    	
    	ThisConstructor2(int i,int j){
    		a = i; 
    		b = j;
    	}
    	
    	ThisConstructor2(int i){
    		this(i,i);
    	}
    	
    	ThisConstructor2(){
    		this(0);
    	}
    }
    

     this() 节省了代码,却会增加构造对象的开销

      适用于 包含大量初始化代码的构造函数,适用于创建少量对象的类,却不适合于那些只简单设置少量变量值的构造函数,不适合要大量创建对象的类。

      因super() 和 this() 都必须是构造函数的第一条语句,所有二者不能同时使用。

    紧凑API配置文件

     JDK 8 新增功能,

    内存管理

    swift中的引用计数管理内存,会造成环形引用无法回收内存。用JAVA测试了一下,正常回收了

    class Employee{
    	Manager m;
    	Employee(Manager m){
    		this.m = m;
    		System.out.println("init Employee");
    	}
    	protected void finalize(){
    		System.out.println("deinit Employee");
    	}
    }
    class Manager{
    	Employee e = null;
    	Manager(){
    		System.out.println("init Manager");
    	}
    	void setEmployee(Employee e){
    		this.e =e;
    	}
    	protected void finalize(){
    		System.out.println("deinit Manager");
    	}
    }
    public class GCTest {
    	static void f(){
    		Manager m = new Manager();
    		Employee e = new Employee(m);
    		m.setEmployee(e);
    	}
    	public static void main(String[] args) {
    		f();
    		System.gc();
    	}
    }
    

      

      

      

  • 相关阅读:
    在小程序中实现 Mixins 方案
    watch监听(数组或者对象)
    --socket---网络通信---
    requests实战之破解百度翻译
    nmap命令
    selenium模块的基本使用
    谷歌无头浏览器+反检测
    模拟登录QQ空间
    动作链和iframe的处理
    selenium其他自动化操作
  • 原文地址:https://www.cnblogs.com/wj033/p/4687895.html
Copyright © 2020-2023  润新知