资讯专栏INFORMATION COLUMN

java5-8新特性的理解

Jinkey / 593人阅读

摘要:引用特定类型的方法特定类普通方法引用构造方法类名称引用构造方法内建函数式接口方法引用操作可能出现的函数式接口有四类有参数有返回值有参数无返回值无参数有返回值判断真假。

可变参数

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

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

[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形式。

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

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

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();
        }
        
    }
}

静态导入可以减少代码量,但是过多的静态导入会降低代码的可读性。

泛型

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

class Point{
    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 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,Message和Message虽然都是Message类的对象,但这两个对象不能够直接进行引用传递操作。通过使用通配符“?”解决参数传递问题。通配符可以接受类对象,但是不能修改对象属性。

class Message{
    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 m1 = new Message<>();
        Message 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{
    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{
    public R change(P p);
}
public class method_reference_static{
    public static void main(String args[]){
        //将String.valueOf()方法变为IMessage接口的change()方法
        //valueOf()方法接收int型数据,返回String型数据
        Imessage msg = String::valueOf;
        String str = msg.change(1000);
        System.out.println(str.replaceAll("0","9"));
    }
}

引用某个对象的方法

实例化对象::普通方法

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

引用特定类型的方法

特定类::普通方法

@FunctionalInterface
interface IMessage

{ public int compare(P p1, P p2); } public class method_reference_special{ public static void main(String args[]){ IMessage msg = String::compareTo; System.out.println(msg.compare("A","B")); } }

引用构造方法

类名称::new

@FunctionalInterface
interface IMessage{
    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 msg = Book::new; //引用构造方法
        Book book = msg.create("JAVA", 100);
        System.out.println(book);
    }
}
内建函数式接口

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

java.util.function

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

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

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

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

3、供给型接口

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

4、断言型接口

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/76937.html

相关文章

  • 读《javaScript高级程序设计-第6章》之理解对象

    摘要:把对象定义为无序属性的集合,其属性可以包含基本值对象或函数。接受两个参数属性所在的对象和要读取其特性的属性名返回的时其特性的对象例如读高级程序设计这本书的第章面向对象的程序设计,我做了篇笔记。这是第一篇,后面还有两篇,分别是封装类和继承。 ECMA-262把对象定义为:无序属性的集合,其属性可以包含基本值、对象或函数。所以,我们可以理解对象就是名值对的集合,名就是对象的每个属性的名字,...

    KoreyLee 评论0 收藏0
  • Javascript面向对象程序设计_理解对象

    摘要:面向对象的程序设计理解对象前言最近在细读高级程序设计,对于我而言,中文版,书中很多地方翻译的差强人意,所以用自己所理解的,尝试解读下。总结如果英语水平足够好的话,建议看英文原版书籍或者国外大师的博客。 JS面向对象的程序设计_理解对象 前言:最近在细读Javascript高级程序设计,对于我而言,中文版,书中很多地方翻译的差强人意,所以用自己所理解的,尝试解读下。 如有纰漏或错误,会非...

    刘厚水 评论0 收藏0
  • 理解Object.defineProperty作用

    摘要:对象是由多个名值对组成的无序的集合。对象中每个属性对应任意类型的值。目标属性所拥有的特性返回值传入函数的对象。给对象的属性添加特性描述,目前提供两种形式数据描述和存取器描述。兼容性在下只能在对象上使用,尝试在原生的对象使用会报错。 对象是由多个名/值对组成的无序的集合。对象中每个属性对应任意类型的值。定义对象可以使用构造函数或字面量的形式: var obj = new Object; ...

    yexiaobai 评论0 收藏0
  • 寻找一种易于理解一致性算法(扩展版)

    摘要:摘要是一种为了管理复制日志的一致性算法。接下来,这篇论文会介绍以下内容复制状态机问题第节,讨论的优点和缺点第节,讨论我们为了可理解性而采取的方法第节,阐述一致性算法第节,评价算法第节,以及一些相关的工作第节。 摘要 Raft 是一种为了管理复制日志的一致性算法。它提供了和 Paxos 算法相同的功能和性能,但是它的算法结构和 Paxos 不同,使得 Raft 算法更加容易理解并且更容易...

    FuisonDesign 评论0 收藏0

发表评论

0条评论

Jinkey

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<