Java8函数式接口/Lambda表达式/接口默认方法/接口静态方法/接口冲突方法重写/lambda表达式指定泛型类型等

一:函数式接口

1.函数式接口的概念就是此接口必须有且只能有一个抽象方法,可以通过@FunctionalInterface来显示规定(类似@Override),但是没有此注解的但是只有一个抽象方法的接口也是函数式接口;(接口也和类一样有包访问权限,但是内部的方法则默认是public)

@FunctionalInterface
public interface IFoo{
    void print();
}  // 就是一个最简单的函数式接口,但是如果再有个如void print2()抽象方法则这个接口不是函数式接口会在编译时便报错(因为有@FunctionalInterface)

2.接口里可以有静态方法(JDK8的新特性)

@FunctionalInterface
public interface IFoo{
    void print();
    static void sTest(){
      System.out.println("msg");
    }
}

注意,接口里的静态方法默认且只能是public的,就像接口里的字段默认且只能是public static的;调用时可以直接IFoo.sTest();

3.接口里也可以有default方法(JDK8新特性)

@FunctionalInterface
public interface IFoo{
    void print();
    default void sTest(){
      System.out.println("msg");
    }
}

与静态方法不同的是default方法本质上是实例方法,因此仍然需要创建IFoo的实现类对象才能调用此方法,如(new IFoo(){...}).sTest();是可以的但是IFoo.sTest()则错误

4.当一个接口成为了函数式接口后且也是以函数式接口来使用,它就类似C#里的委托,即接口和其里面的抽象方法是一一对应的,故泛型的声明要在接口名里而非抽象方法里

@FunctionalInterface
public interface IFoo<T extends Serializable>{
    T print(T arg);  // 写成<T> T print(T);对于将IFoo看成委托而言是错误的写法;注意<T extends B> T print。。在普通接口里也是可以的;
    static void sTest(){
      System.out.println("msg");
    }
}

5.函数式接口对象和其Lambda表达式的关系

lambda表达式不会产生里面类的.class文件,而如new Predicate(){...}是会产生的,因此如果需要将lambda表达式转换为接口对象是需要强制转换的,如:((Predicate) o -> false).and(o -> false)

上面的(o -> false)是一个”函数对象“,它和new Predicate(){@Override test...}是不一样的,前者并没有产生Predicate的实现类,因此需要做一个强制类型转换将lambda表达式产生的结果转换为接口实现类对象;

6.将函数式接口当成委托使用

public interface Println<T>{
    void println(T msg);
}

可以Println<String> println = System.out::println;来赋值;

7.实现多个接口但是又同名的default方法时必须重写/重定义该方法(如果是抽象方法则无所谓,当子类实现IC时实现print那么实际上即是实现IA的也是IB的不存在要重写两次的说法)

public interface IA{
    default void print(){}
}
public interface IB{
    default void print(){}
}
public interface IC extends IA, IB{
    @Override
    default void print(){IA.super.print();}  // TODO 用于明确指定用IA的print,注意在JDK8以前由于没有default且只能继承一个类,因此只需要super.print()即可
}

8.lambda表达式的类型推导

如果是非泛型自然不需要,但是如果参数是泛型,但又无法隐式推导出时可以通过(String s) ->{..}来指定泛型的类型;

9.接口里可以都是default方法,此时这个接口可以直接new ITest{}就可以产生对象,但也可以重写default方法

10.可以在子接口里重写父接口的default方法令其在子接口里成为抽象方法;

11.lambda表达式和匿名内部类的区别

lambda表达式是很特殊的存在,它不会生成.class文件,而且它也不是接口的实现类的对象,应该这么理解IFoo foo = ()->true;是IFoo能够匹配右边的lambda表达式,而不是说这个正则表达式是一个IFoo的匿名实现类的对象;

注意上面存在一个隐式的转换即IFoo foo = (IFoo) ()->true;

12.将方法存储到“委托”里

ITest del = System::getenv;  // 此时通过System.getenv方法实现了ITest的抽象方法;

del.method("string");注意,这里有几个重点,1)是ITest必须是函数式接口;2)ITest中的抽象方法名字任意且可以有泛型,但是必须能匹配System.getenv(..)这个方法的返回值和参数列表;3)del和C#的委托变量还是有些不一样的不能直接del(..)来调用,而是要del.method(..)来调用System.getenv方法;

n)还可以用ITest t = String::new;表示String的构造方法;那么t.func(..)方法的就是new String(..)而产生的对象;(构造方法某种程度上可以理解为类的静态方法)

n)IFoo2<String> ss = sbs::concat;,sbs是一个对象,因此ss.func(..)实际是是调用sbs.concat(..)方法

n)对于如果方法test是类A的实例方法,则ITest del = A::test;是错误的,IDE提示没有static的test方法,因为当del.func(..)调用时将不知道要调用哪个对象的test方法,因为test的调用必须依赖某个A对象;

原文地址:https://www.cnblogs.com/silentdoer/p/8966868.html

时间: 2024-10-09 18:47:53

Java8函数式接口/Lambda表达式/接口默认方法/接口静态方法/接口冲突方法重写/lambda表达式指定泛型类型等的相关文章

类方法,实例方法,对象方法,静态方法,动态方法

类方法,也称静态方法,指的是用static关键字修饰的方法. 调用方式有三种:可直接调用.类名.方法名.对象名.方法名. 实例方法指的是不用static关键字修饰的方法. 调用方式只能是对象名.方法名. 需要访问某个实例的成员变量时,那么就将该方法定义成实例方法 一.静态方法常驻内存,实例方法不是,所以静态方法效率高但占内存. 事实上,方法都是一样的,在加载时机和占用内存上,静态方法和实例方法是一样的,在类型第一次被使用时加载.调用的速度基本上没有差别. 二.静态方法在堆上分配内存,实例方法在堆

类的各种自带方法,静态方法,属性方法,类方法等

#coding=utf-8 class Dog(object): ''' 类的描述 ''' def __init__(self,name): self.name = name self.__food = None @staticmethod #实际上跟类没什么关系,单纯的函数,但是必须通过类名来调用 def eat(food): print ('%s is eating %s'%('xiaohuang',food)) @classmethod #类方法,只能访问类变量,不能访问实例变量 def

Java8 之 lambda 表达式、方法引用、函数式接口、默认方式、静态方法

今天我来聊聊 Java8 的一些新的特性,确实 Java8 的新特性的出现,给开发者带来了非常大的便利,可能刚刚开始的时候会有点不习惯的这种写法,但是,当你真正的熟悉了之后,你一定会爱上这些新的特性的,这篇文章就来聊聊这些新特性. lambda 表达式 lambda 表达式在项目中也是用到了,这种新的语法的加入,对于使用 Java 多年的我,我觉得是如虎添翼的感觉哈,这种新的语法,大大的改善了以前的 Java 的代码,变得更加的简洁,我觉得这也是为什么 Java8 能够很快的流行起来的原因吧.

[二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口

函数式接口详细定义 package java.lang; import java.lang.annotation.*; /** * An informative annotation type used to indicate that an interface * type declaration is intended to be a <i>functional interface</i> as * defined by the Java Language Specificat

java8之lambda表达式(默认方法)

许多开发语言都将函数表达式集成到了其集合库中.这样比循环方式所需的代码更少,并且更加容易理解.以下面的循环为例: for(int i = 0; i < list.size(); i++)      System.out.println(list.get(i)); 事实上有一种更好的方式.API开发人员可以提供一个forEach方法,用来将一个函数应用到集合的每个元素上.下面是使用这种方式编写的一个简单调用: package java8test; import java.util.Arrays;

java代码之美(14)---Java8 函数式接口

Java8 函数式接口 之前写了有关JDK8的Lambda表达式:java代码之美(1)---Java8 Lambda 函数式接口可以理解就是为Lambda服务的,它们组合在一起可以让你的代码看去更加简洁. 一.概念 1.什么是函数式接口 概念 所谓的函数式接口, 当然首先是一个接口, 然后就是在这个接口里面 只能有一个抽象方法. 有关函数式接口,有个专门的注解叫:@FunctionalInterface.该注解主要特点有: 1.该注解只能标记在"有且仅有一个抽象方法"的接口上,表示函

Java8函数式编程 (一) 数据流和lambda表达式

JDK 1.8中引入了函数式编程(functional programming,FP),如果您已习惯OOP,一定会感到困惑:什么是函数式编程?这样的编程模式有什么好处? 本文将通过简单的实例令读者对函数式编程有一个大体的了解. 我们知道OOP是以类为基础的,程序中必须首先抽象和定义class.那么FP创建的基础是什么?或者说在Java 8中,至少需要了解什么知识点才能实现基本的函数式编程呢? 本文将首先介绍在Java 8中使用FP所需的基本知识点: Lambda表达式 数据流 基本实例 Map<

Java 8——接口中个的默认方法和静态方法

在Java SE 8之前,interface只是事物的抽象,用来定义统一的抽象事物和描述事物的抽象行为和属性. 但是在Java SE 8中,增加了可以在interface中增加默认实现的行为和事物的静态行为. 一.为什么? java迭代了如此多的版本且主要采用的都是演化的思想而非重构(为了保证与历史的兼容性). 这样就容易出现很多比较难以处理的问题,接口在发布之后就已经被定型,除非我们能够一次性更新所有该接口的实现.比如某个历史接口有很多实现,需要在历史接口中增加一个行为,那么久需要在它的所有实

java8-新特性--(接口的默认方法与静态方法)

Java 8用默认方法与静态方法这两个新概念来扩展接口的声明. public interface Inte{ void method(); default void defaultMethod(){ System.out.println("default"); } static void staticMehod(){ System.out.println("static"); } }   public static void main(String[]args){