java5-8新特性的理解

可变参数

在java程序中调用方法时,必须严格按照方法定义的变量进行参数传递。可是在开发过程当中可能会出现一种状况:不肯定要传递的参数个数。解决这个问题的思路是将多个参数封装为数组。这是一个打折扣的方法,由于数组并不表明任意多个数据。java

在JDK1.5中,引入了可变参数的概念。可变参数的语法形式为:express

[public/protected/private] [static/final/abstract] 返回值类型 func(参数类型 ... 变量){
    [return [返回值] ;]
}

参数变量传递到方法中,以指定类型的数组进行保存。数组

public class varargs{
    public static void main(String args[]){
        System.out.println(add(1,2,3));
        System.out.println(add(10,20));
    }
    public static int add(int ... data){
        int sum = 0;
        for(int i = 0; i < data.length; i++){
            sum += data[i];
        }
        return sum;
    }
}

foreach循环

java中的foreach语句是一种增强型for循环操做。for循环的输出方式须要控制索引,过于麻烦。所以,在JDK1.5中引入foreach形式。app

for(数据类型 变量:数组/集合){
    //每一次循环,会将数组内容赋值个变量
}

每次循环自动将数组或集合的内容取出,避免了索引问题。ide

public class foreach{
    public static void main(String args[]){
        int data[] = new int[]{1,2,3,4,5};
        for(int x : data){
            System.out.println(x + " ");
        }
    }

静态导入

若是一个类中的方法所有属于static型方法,其余类在引用此类时,必须先使用import导入所须要的包。而后使用“类名.方法()”进行调用。
若是在调用这些方法时不但愿出现类的名称,JDK1.5引入静态导入功能。函数

import static 包.类.*;
package com.qi.demo;
public class myMath{
    public static int div(int x, int y) throws Exception{
        System.out.println("===start===");
        int result = 0;
        try{
            result = x / y;
        }catch(Exception e){
            throw e;
        }finally{
            System.out.println("===end===");
        }
        return result;
    }
    public static int add(int x, int y){
        return x + y;
    }
}
import static com.qi.demo.myMath.*;
public class static_import{
    public static void main(String args[]){
        System.out.println("Add operation:" + add(10,20));
        try{
            System.out.println("divide operation: " + div(10,2));
        }catch(Exception e){
            e.printStackTrace();
        }
        
    }
}

静态导入能够减小代码量,可是过多的静态导入会下降代码的可读性。this

泛型

JDk5提供泛型技术。类属性或方法的参数在定义数据类型时,能够直接使用一个标记进行占位,再具体使用时才设置其对应的实际数据类型。这样当设置的数据类型出现错误后,就能够在程序编译时检测出来。使用泛型时,可以采用的类型只能是类,也就是说不能是基本类型,只能是引用类型。例如泛型采用整型,应用Integer,而不是int。设计

class Point<T>{
    private T x;
    private T y;
    public void setX(T x){
        this.x = x;
    }
    public void setY(T y){
        this.y = y;
    }
    public T getX(){
        return x;
    }
    public T getY(){
        return y;
    }
}
public class generic{
    public static void main(String args[]){
        Point<Integer> p = new Point<>();
        p.setX(10);
        p.setY(20);
        Integer x = p.getX();
        Integer y = p.getY();
        System.out.println("coordinate x: " + x + " y: " +y);
    }
}

通配符

对于同一类,因为设置泛型类型不一样,其对象表示的含义也不一样,所以不可以直接进行引用操做。例如经过泛型定义Message<T>,Message<String>和Message<Integer>虽然都是Message类的对象,但这两个对象不可以直接进行引用传递操做。经过使用通配符“?”解决参数传递问题。通配符能够接受类对象,可是不能修改对象属性。code

class Message<T>{
    private T msg;
    public void setMsg(T msg){
        this.msg = msg;
    }
    public T getMsg(){
        return msg;
    }
}
public class generic_wildcard{
    public static void main(String args[]){
        Message<Integer> m1 = new Message<>();
        Message<String> m2 = new Message<>();
        m1.setMsg(100);
        m2.setMsg("hello");
        fun(m1);
        fun(m2);
    }
    public static void fun(Message<?> temp){
        System.out.println(temp.getMsg());
    }
}

在“?”通配符的基础上还有两个子通配符。对象

? extends 类

设置泛型上限,在声明和方法中使用。表示能够设置该类或其子类。

? super 类

设置泛型下限,在方法中使用。表示只能设置该类或其父类。

泛型接口

泛型能够定义在接口上。使用接口必须定义相应子类。对于使用泛型的接口,有两种实现方式。一是在子类继续设置泛型标记。二是在子类中为父类接口明肯定义一个泛型类型。

泛型方法

泛型也能够在方法中定义。在方法中定义泛型时,方法不必定要在泛型类中定义,但要在方法返回值类型前明肯定义泛型类型。

Annotation

JDK1.5提出并应用了注解技术。在java SE中,最多见的Annotation是:

@Override

准确覆写操做。保证子类覆写的方法是父类中定义过的方法。当覆写方法出现错误时,能够在编译时检查出来。

@Deprecated

声明过时操做。用于声明过时不建议使用的方法。

@SuppressWarnings

压制警告。开发者明确知道会出现警告信息却执意按照固定方式处理,可使用@SuppressWarnings压制出现的警告信息。

class Book<T>{
    private T title;
    public void setTitle(T title){
        this.title = title;
    }
    public T getTitle(){
        return title;
    }
}
public class annotation_suppresswarnings{
    @SuppressWarnings({"rawtypes", "unchecked"})
    public static void main(String args[]){
        Book book = new Book();
        book.setTitle("hello");
        System.out.println(book.getTitle());
    }
}

接口定义增强

JDK1.8开始,接口中能够定义普通方法与静态方法。java增长这个特性缘由以下。随着接口的子类愈来愈多,若是这个接口功能不足,须要增长新的方法,则须要对全部接口子类覆写新增长的方法。这个设计的工做量是重复的且是巨大的,所以经过放宽接口定义,接口能够定义普通方法和静态方法,接口的方法扩充问题就能获得很好的解决。
在接口中定义普通方法,该方法必须使用default来进行定义。使用default定义的普通方法,须要利用实例化对象明确调用。在接口中定义静态方法,该方法能够由接口名称直接调用。

lambda表达式

JDK1.8中引入lambda表达式。lambda表达式是应用在单一抽象方法接口环境下的一种简化定义形式,解决匿名内部类定义复杂问题。单一抽象方法接口使用@FunctionalInterface注解,表示此为函数式接口,里面只容许定义一个抽象方法。lambda表达式有三种形式。

(params) -> expression
(params) -> statement
(params) -> {statements}
@FunctionalInterface
interface IMessage{
    public int add(int ... args);
    static int sum(int ... args){
        int sum = 0;
        for(int temp:args){
            sum += temp;
        }
        return sum;
    }
}
public class lambda{
    public static void main(String args[]){
        //()内是参数,->后是子类覆写抽象方法的方法体
        fun((int ... param) -> IMessage.sum(param));
    }
    public static void fun(IMessage msg){
        System.out.println(msg.add(10,20,30));
    }
}

方法引用

JDK1.8支持方法的引用操做,至关于为方法定义别名。java8定义了四种方法引用操做形式。

  • 引用静态方法

类名称::static方法名称

interface Imessage<P,R>{
    public R change(P p);
}
public class method_reference_static{
    public static void main(String args[]){
        //将String.valueOf()方法变为IMessage接口的change()方法
        //valueOf()方法接收int型数据,返回String型数据
        Imessage<Integer, String> msg = String::valueOf;
        String str = msg.change(1000);
        System.out.println(str.replaceAll("0","9"));
    }
}
  • 引用某个对象的方法

实例化对象::普通方法

@FunctionalInterface
interface IMessage<R>{
    public R upper();
}
public class method_reference_common{
    public static void main(String args[]){
        //String类的toUpperCase()定义:public String toUpperCase()。
        //该方法没有参数,有返回值。
        IMessage<String> msg = "hello"::toUpperCase;
        String str = msg.upper();
        System.out.println(str);
    }
}
  • 引用特定类型的方法

特定类::普通方法

@FunctionalInterface
interface IMessage<P>{
    public int compare(P p1, P p2);
}
public class method_reference_special{
    public static void main(String args[]){
        IMessage<String> msg = String::compareTo;
        System.out.println(msg.compare("A","B"));
    }
}
  • 引用构造方法

类名称::new

@FunctionalInterface
interface IMessage<C>{
    public C create(String t, double p);
}
class Book{
    private String title;
    private double price;
    public Book(String title, double price){
        this.title = title;
        this.price = price;
    }
    @Override
    public String toString(){
        return "book: " + this.title + ", price: " + this.price;
    }
}
public class metheod_reference_constructor{
    public static void main(String args[]){
        IMessage<Book> msg = Book::new; //引用构造方法
        Book book = msg.create("JAVA", 100);
        System.out.println(book);
    }
}

内建函数式接口

方法引用操做可能出现的函数式接口有四类:有参数有返回值、有参数无返回值、无参数有返回值、判断真假。JDK1.8提供了一个新的开发包:

java.util.function

该开发包提供四个核心函数式接口,简化开发者的定义,实现操做的统一。
一、功能型接口

@FunctionalInterface
public interface Function<T,R>{
    public R apply(T t); //接收**一个**参数,并返回一个处理结果
}
import java.util.function.Function;
public class funcifc_function{
    public static void main(String args[]){
        Function<String, Boolean> fun = "##hello"::startsWith; //利用对象调用startsWith()
        System.out.println(fun.apply("##"));
    }
}

注意引用的方法只能有一个输入和一个返回结果。不然,引用方法不能与apply()匹配。
二、消费型接口

@FunctionalInterface
public interface Comsumer<T>{
    public void accept(T t); //只接收数据,不返回结果
}
import java.util.function.Consumer;
public class funcifc_consumer{
    public static void main(String[] args){
        Consumer<String> cons = System.out::print;
        cons.accept("hello world");
    }
}

三、供给型接口

@FunctionalInterface
public interface Supplier<T>{
    public T get(); //不接收数据,只返回结果   
}
import java.util.function.Supplier;
public class funcifc_supplier{
    public static void main(String args[]){
        Supplier<String> sup = "hello"::toUpperCase;
        System.out.println(sup.get());
    }
}

四、断言型接口

@FunctionalInterface
public intereface Predicate<T>{
    public boolean test(T t); //判断
}
import java.util.function.Predicate;
public class funcifc_predicate{
    public static void main(String args[]){
        Predicate<String> pre = "hello"::equalsIgnoreCase;
        System.out.println(pre.test("HELLO"));
    }
}
相关文章
相关标签/搜索