Java:Lambda表达式&枚举类
——本文为个人学习Java记录,文章主要内容来自《疯狂java讲义》第3版
Lamdba表达式的几种简单写法:
public interface Identification {
void identification();
}
public interface Name {
void name(String name);
}
public interface Score {
int score(int chineseScore, int mathematicsScore, int englishScore);
}
public class Client {
public void getIdentification(Identification id) {
id.identification();
}
public void getName(Name na) {
na.name("小明");
}
public void getScore(Score sc) {
System.out.println("我的总分是:" + sc.score(40, 50, 60));
}
public static void main(String[] args) {
Client cl = new Client();
cl.getIdentification(()->System.out.println("我是一名学生..."));
cl.getName(name->System.out.println("我的名字是" + name));
cl.getScore((chineseScore, mathematicsScore, englishScore)->chineseScore + mathematicsScore + englishScore);
}
}
输出结果:
我是一名学生...
我的名字是小明
我的总分是:150
第一种:无参数
void identification();
Lambda表达式:
()->System.out.println("我是一名学生...")
由于代码块只有一行代码,所以可以省略{ },如果含有一行以上代码则:
()->{
System.out.println("我是一名学生...")
......
......
}
第二种:一个参数
void name(String name);
Lambda表达式:
name->System.out.println("我的名字是" + name)
由于只有一个形参,则可以省略形参列表的( )。
第三种:多个参数
int score(int chineseScore, int mathematicsScore, int englishScore);
Lambda表达式:
(chineseScore, mathematicsScore, englishScore)->chineseScore + mathematicsScore + englishScore
score()方法需要一个返回值,所以程序将chineseScore + mathematicsScore + englishScore三科成绩的总和作为返回值,这里的return关键字可以省略。
有趣的是:getIdentification(), getName(), getScore()的形参的类型分别为Identification,Name,Score,但实际传入的是Lamdba表达式,说明此处的Lamdba表达式被当成“任意类型”来处理了。
Lamdba表达式的类型:
1. 几个简单的概念:
目标类型:Lamdba表达式的类型。
函数式接口:只包含一个抽象方法的接口,其他方法可以有多个。
说明:这里的抽象方法是指接口自己特有的抽象方法,而不包含该接口从上级继承过 来的抽象方法。
2. 常见的函数式接口:Java 8中一些常用的全新的函数式接口
3. Lamdba表达式进行赋值:
Runnerable r = ()->System.out.println("...");
这里的Runnerable是一个函数式接口,关于Lamdba表达式的两点限制:
—>Lamdba表达式的目标类型必须是明确的函数式接口。
如果不是怎么办?
a. 将Lamdba表达式赋值给函数式接口类型的变量,如上面的一行代码。
b. 将Lamdba表达式作为函数式接口类型的参数传递给方法,如文章最开始的程序。
c. 将Lamdba表达式进行强制类型转换,如下代码:
Object obj = (Runnerable)()->System.out.println("...");
—>Lamdba表达式只能为函数接口类型创建对象。
方法引用与构造器引用:
1. 类方法引用
将数字串转换为数值
public interface TypeConverter {
Integer converter(String str);
}
public class Client {
public static void main(String[] args) {
TypeConverter tc = str->Integer.valueOf(str);
int x = tc.converter("100");
System.out.println(x);
}
}
使用Lamdba创建TypeConverter对象部分,原先的写法:
TypeConverter tc = str->Integer.valueOf(str);
改写之后:
TypeConverter tc = Integer::valueOf;
2. 引用特定对象的实例方法
原先的写法:
TypeConverter tc = str->"123456789".indexOf(str);
改写之后:
TypeConverter tc = "123456789"::indexOf;
3. 引用某类对象的特定方法
public interface TypeConverter {
String converter(String str, int a, int b);
}
public class Client {
public static void main(String[] args) {
TypeConverter tc = (str,a,b)->str.substring(a, b);
String x = tc.converter("Hello World", 2, 6);
System.out.println(x);
}
}
原先的写法:
TypeConverter tc = (str,a,b)->str.substring(a, b);
改写之后:
TypeConverter tc = String::substring;
4. 引用构造器
public class Student{
public Student(String name) {
System.out.println("我是一名学生,名字叫" + name);
}
}
public interface TypeConverter {
Student converter(String str);
}
public class Client {
public static void main(String[] args) {
TypeConverter tc = str->new Student(str);
Student x = tc.converter("Hello World");
System.out.println(x);
}
}
原先的写法:
str->new Student(str);
改写之后:
TypeConverter tc = Student::new;
Lamdba表达式与匿名内部类的异同:
相同点:
1. Lamdba表达式和匿名内部类都可以访问局部变量,且默认用final修饰,无法重新赋值,都可以访问外部类的成员变量(包含实例变量和类变量)。
2. Lamdba表达式创建的对象和匿名内部类生成的对象,都可以调用从接口中继承的默认方法。
不同点:
1. 匿名内部类可以为任意接口创建实例,Lamdba只能为函数式接口创建实例。
2. 匿名内部类可以为抽象类、普通类创建实例,而Lamdba则不能。
3. 匿名内部类实现的抽象方法的方法体允许调用接口中的默认方法,但Lamdba表达式的代码块则不允许调用接口中的默认方法,Lamdba表达式创建的对象可以调用从接口中继承的默任方法。
使用Lamdba表达式调用Arrays中的类方法
待补充……
什么是枚举类?
- 枚举enum是一个关键字,与class、interface类似,所以枚举类可以看成是一种特殊的类。枚举类可以有成员变量、方法,构造器以及实现接口。枚举类的实例是有限的,可被列举的。
- 枚举类可以实现一个或多个接口,但是不能显示继承其他类,枚举类默认继承java.util.Enum类。
- 非抽象枚举类默认用final修饰,因此枚举类不能被继承。
- 枚举类的构造器只能使用private关键字来修饰,可以省略。
- 枚举类的实例,必须显示的列在程序的第一行,否则默认没有实例,且实例默认使用public static final修饰。
- 枚举类默认有一个values()方法,列出枚举类的所有实例,形式很像数组的foreach。
- 访问枚举类中的某个实例格式:EnumClass.InstanceName。
代码部分:
public enum SeasonEnum {
SPRING,SUMMER,AUTUMN,WINTER;
}
public class Client {
public void seasonDescription(SeasonEnum sa) {
switch(sa) {
case SPRING:
System.out.println("不知细叶谁裁出,二月春风似剪刀");
break;
case SUMMER:
System.out.println("荷叶罗裙一色裁,芙蓉向脸两边开");
break;
case AUTUMN:
System.out.println("人生若只如初见,何事秋风悲画扇");
break;
case WINTER:
System.out.println("疏影横斜水清浅,暗香浮动月黄昏");
break;
default:
break;
}
}
public static void main(String[] args) {
for(SeasonEnum s: SeasonEnum.values()) {
System.out.println(s);
}
new Client().seasonDescription(SeasonEnum.SPRING);
}
}
看一下遍历和访问实例部分:
for(SeasonEnum s: SeasonEnum.values()) {
System.out.println(s);
}
new Client().seasonDescription(SeasonEnum.SPRING);
8. 枚举类可以通过valueOf( )来获取指定枚举类的枚举值。
SeasonEnum se = Enum.valueOf(SeasonEnum.class, "SPRING");
9. 当某个枚举类的实现接口的时候,可以使用接口中的抽象方法,且每个实例可以分别实现这个方法,代码如下:
public interface Information {
void Info();
}
public enum SeasonEnum implements Information {
SPRING
{
public void Info() {
System.out.println("不知细叶谁裁出,二月春风似剪刀");
}
},
SUMMER
{
public void Info() {
System.out.println("荷叶罗裙一色裁,芙蓉向脸两边开");
}
},
AUTUMN
{
public void Info() {
System.out.println("人生若只如初见,何事秋风悲画扇");
}
},
WINTER
{
public void Info() {
System.out.println("疏影横斜水清浅,暗香浮动月黄昏");
}
};
}
public class Client {
public static void main(String[] args) {
SeasonEnum se = Enum.valueOf(SeasonEnum.class, "WINTER");
System.out.println(se);
se.Info();
}
}
注意格式,这里的{ }相当于类体部分,属于匿名内部子类,看源文件和class文件可以看出,Java是把它当匿名子类来处理了。
src文件:
class文件:
原文地址: https://zhuanlan.zhihu.com/p/36163515
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
相关文章