基础语法
1、使用long、float这种数据类型时需要在数字后面加'l'、'f'后缀,因为你写个整数默认是Int类型,小数默认是double类型
2、方法重载:只要传入的参数不同就允许存在重复方法名
3、类型转换:范围小的可以转成范围大的,反之则不能,否则会发生强制截断导致数据错误
4、表达式的自动类型转换:都会向精度高的靠拢,比如小数和整数的运算会自动转化成小数类型
数组
1、动态初始化数组:先确定类型和容量但是不赋值,二维数组也相同
Stirng[] array = new String[8]
面向对象
类、对象、方法与jvm虚拟机内存中方法区、栈内存、堆内存之间的关系
1、类(Class)
比喻:你可以把类看作是建筑设计图纸。它详细描述了要建造的建筑物的各种特性,比如尺寸、材料等。
内存对应:在JVM中,类的信息(包括类名、方法信息、静态变量等)存储在方法区。方法区就像是存放所有建筑设计图纸的地方。
2、对象(Object)
比喻:对象则是根据建筑设计图纸实际建造出来的房子。每个对象都是类的一个实例,就像每栋建筑都是按照特定的设计图建造的一样。
内存对应:对象被创建后,会被分配到堆内存中。堆内存就像是放置所有实际建造出来的建筑的地方。在这里,每个对象都有自己的空间来存储其状态(即成员变量的值)。
3、方法(Method)
比喻:方法就像是施工过程中执行的具体操作指南,比如如何打地基、如何砌墙等。不同的方法指导着完成不同的任务。
内存对应:当一个方法被调用时,会在栈内存中为这个方法创建一个栈帧(Stack Frame),用来存储该方法执行期间的局部变量、操作数栈等信息。栈内存就像是记录每个施工步骤的临时笔记本,每次执行方法就像是记录下当前步骤的操作。
4、JVM内存概述
方法区:存储类的信息,包括类的结构(字段和方法数据)、运行时常量池、静态变量等。
堆内存:用于存储对象实例及数组,是垃圾回收器主要管理的区域。
栈内存:每个线程都有自己的栈,用于存储方法调用的栈帧。栈帧包含局部变量表、操作数栈、动态链接、方法出口等信息。
构造器
1、分为有参构造器和无参构造器,如果自定义了有参构造器则会将默认的无参构造器覆盖(除非你专门写了一个无参构造器)
2、子类构造器使用父类构造器:
public class Main {
public static void main(String[] args) {
Student student = new Student("kaka", 20, "龙岩学院");
}
}
class People{
String name;
int age;
public People(String name, int age) {
this.name = name;
this.age = age;
}
}
class Student extends People{
String school;
public Student(String name, int age, String school) {
super(name, age); // 调用父类的有参构造器
this.school = school;
}
}
3、调用兄弟构造器(设置默认值):
class Student {
String name;
int age;
String school;
public Student(String name, int age, String school) {
this.name = name;
this.age = age;
this.school = school;
}
public Student(String name, int age) {
this(name, age, "清华大学");
}
}
引用关键字this
1、访问类的成员变量
当你在一个方法或构造器中需要区分局部变量和成员变量时,可以使用this关键字来指代当前对象的成员变量。例如:
public class Person {
String name;
public Person(String name) {
this.name = name; // 使用this区分成员变量name和参数name
}
}
这里,this.name指的是类的成员变量,而name是构造函数的参数。
2、调用另一个构造器(构造器链)
public class Car {
private String brand;
private String color;
private int year;
public Car(String brand, String color, int year) {
this.brand = brand;
this.color = color;
this.year = year;
}
public Car(String brand, String color) {
this(brand, color, 2025); // 默认年份为2025
}
}
使用场景:设置默认值
3、返回当前对象
有时候你可能希望方法返回当前对象的引用,以便于链式调用(method chaining)。这时可以使用this返回当前对象:
public class Person {
private String name;
public Person setName(String name) {
this.name = name;
return this; // 返回当前对象
}
}
这样,你就可以链式调用方法,如person.setName("John").setAge(30)(假设还有setAge方法并且也返回this)。
面向对象三大特征:封装、继承、多态
1、封装:合理隐藏、合理暴露
就像创建实体类时你需要将属性全部设为私有(不允许外部变量直接访问并赋值)进行合理隐藏,然后设置get/set方法对其进行合理暴露。
实体类是专门用来存放数据的,如果要对数据进行操作要在专门的实体操作类中操作。例如:
/*
* 实体类
* */
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/*
* 实体操作类
* */
public class StudentOperator {
private final Student student;
public StudentOperator(Student student) {
this.student = student;
}
public void printStudentName(){
System.out.println(student.getName());
}
}
/*
* 调用处
* */
Student student = new Student("lisi", 29);
new StudentOperator(student).printStudentName();
static静态变量:类和对象共享的变量,不管是用类还是用对象引用该变量都会使其发生改变。这里推荐直接用类引用该变量。
static静态变量实际上也是跟对象一样存在堆内存中的,但是对象在新建时一直会在堆内存不断开辟空间,而静态变量不会随着对象数量的增加而增加,它只有一个
static静态方法:如果一个方法不需要访问对象中的数据,则可以将其定义为实例方法,可以直接使用类来进行调用了(常用于写工具类中的方法)
使用工具类时因为没有必要创建对象,所以可以直接将工具类对象的无参构造器进行私有化。
静态方法和实例方法访问的相关注意事项:
静态方法中可以直接访问静态成员,不可以直接访问实例成员。
实例方法中既可以直接访问静态成员,也可以直接访问实例成员。
实例方法中可以出现this关键字,静态方法中不可以出现this关键字的。
2、继承:使用了extends关键字,能让一个类与另一个类建立起父子关系。子类能继承父类的非私有成员(变量、方法)。
继承的特点:不支持多继承(因为继承对象如果存在相同的方法将无法执行),但是可以多层继承。java中所有的类都是继承Object类。
访问父类属性或方法可以使用super关键字,super关键字就是访问父类对象。子类不能访问父类的父类对象,除非将子类对象向上转型或者父类的父类定义相应的get/set方法。
方法重写:1️⃣子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限 (public>protected>缺省)
2️⃣重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。
3️⃣私有方法、静态方法不能被重写,如果重写会报错的。
简单来说方法重写就八个大字:声明不变,重新实现
方法重写应用场景:如输出对象时默认会调用 对象名.toString ,而这个输出的是对象的地址,若在对象内将toString方法重写,则可以自定义输出的内容
3、权限修饰符:

4、多态(对象多态、行为多态、属性不多态):
简单来说多态就是一个对象的多种形态
多态的前提:
1️⃣有继承、实现关系
class Animal {
String name = "Animal";
public void eat() {
System.out.println("动物吃东西了");
}
}
class Cat extends Animal {
String name = "Cat";
@Override
public void eat() {
System.out.println("猫吃东西了");
}
}
class Dog extends Animal {
String name = "Dog";
@Override
public void eat() {
System.out.println("狗吃东西了");
}
}
2️⃣存在父类引用子类对象
Animal cat = new Cat(); //父类引用子类对象
cat.eat(); //行为多态,编译看左边,运行看右边(优先从子类查找是否有重写方法)
System.out.println(cat.name); //属性不多态,编译、运行都看左边(优先从父类找属性)
Animal dog = new Dog(); //父类引用子类对象
dog.eat();//行为多态,编译看左边,运行看右边
System.out.println(dog.name); //属性不多态,编译、运行都看左边(优先从父类找属性)
3️⃣子类存在方法重写(1️⃣中子类的eat方法)
多态的好处(具有解耦性):
public class Main {
public static void main(String[] args) {
Animal cat = new Cat();
cat.eat(cat); //将cat对象传入
Animal dog = new Dog();
dog.eat(dog); //将dog对象传入
}
}
class Animal {
String name = "Animal";
public void eat() {
System.out.println("动物吃东西了");
}
public void eat(Animal animal) {
System.out.println("动物们开始吃东西了...");
animal.eat(); //分别调用了cat和dog类中的eat方法
}
}
class Cat extends Animal {
String name = "Cat";
@Override
public void eat() {
System.out.println("猫吃东西了");
}
}
class Dog extends Animal {
String name = "Dog";
@Override
public void eat() {
System.out.println("狗吃东西了");
}
}
这里使用animal.eat()能够分别调用子类中重写的eat方法其实是多态中的动态方法调度
缺点:不能调用子类中自己的方法,因为是之前通过animal.eat()调用了子类重写父类的方法,因此如果子类中具有自己的方法,如cat类中:
class Cat extends Animal {
String name = "Cat";
@Override
public void eat() {
System.out.println("猫吃东西了");
}
public void eatFish() {
System.out.println("猫吃鱼了");
}
}
这时候我们就不能通过animal.eatFish()调用了,需要向下转型:
Animal cat = new Cat();
cat.eat(cat); //将cat对象传入
Cat cat1 = (Cat) cat; //强制类型转换可以调用子类的非重写方法
cat1.eatFish();
强转时需要注意先判断对象的真实类型,再进行转换,否则会报类型转换异常:ClassCastException错误。在父类的公共方法中需判断参数对象的真实类型然后向下转型:
public class Main {
public static void main(String[] args) {
Animal cat = new Cat();
cat.eat(cat); //将cat对象传入
Animal dog = new Dog();
dog.eat(dog); //将dog对象传入
}
}
class Animal {
String name = "Animal";
public void eat() {
System.out.println("动物吃东西了");
}
public void eat(Animal animal) {
System.out.println("动物们开始吃东西了...");
animal.eat(); //分别调用了cat和dog类中的eat方法
//判断类型并向下转型,调用子类非重写方法
if(animal instanceof Dog){
Dog dog = (Dog) animal;
dog.eatBone();
}else if(animal instanceof Cat){
Cat cat = (Cat) animal;
cat.eatFish();
}
}
}
class Cat extends Animal {
String name = "Cat";
@Override
public void eat() {
System.out.println("猫吃东西了");
}
public void eatFish() {
System.out.println("猫吃鱼了");
}
}
class Dog extends Animal {
String name = "Dog";
@Override
public void eat() {
System.out.println("狗吃东西了");
}
public void eatBone() {
System.out.println("狗吃骨头了");
}
}
final关键字
1、修饰类:该类被称为最终类,特点是不能被继承了。
修饰方法:该方法被称为最终方法,特点是不能被重写了。
修饰变量:该变量有且仅能被赋值一次。
2、final修饰基本类型的变量,变量存储的数据不能被改变。
final修饰引用类型的变量(如数组、对象),变量存储的地址不能被改变,但地址所指向对象的内容是可以被改变的
3、使用场景:用于声明配置文件的属性(属性名一般由大写字母和下划线组成)
单例设计模式
1、饿汉式单例(直接在属性中new)
class A {
public static final A a = new A(); //直接在属性中new对象
private A() {
} //必须将构造器私有保证外部无法创建
public static A getObject() { //外部只能通过这个方法获得对象
return a;
}
}
2、懒汉式单例(在需要时才new)
class A {
public static A a;
private A() {
} //必须将构造器私有保证外部无法创建
public static A getObject() { //外部只能通过这个方法获得对象
if (a == null) { //需要时才new
a = new A();
}
return a;
}
}
枚举类
1、代码示例:
public class Main {
public static void main(String[] args) {
System.out.println(A.X); //输出X,因为父类的Enum重写了Object的toString方法,所以可以直接输出对象名
System.out.println(A.Y);
System.out.println(A.Z);
System.out.println(A.X.ordinal());//输出对象的位置索引
}
}
enum A {
X,Y,Z
}
2、反编译完之后的样子:
final class A extends java.lang.Enum<A> {
public static final A X;
public static final A Y;
public static final A Z;
public static A[] values();
public static A valueOf(java.lang.String);
static {};
}
枚举类底层就是不可修改的常量,但是它属于多例模式,因为它每定义一个属性都会新建一个对象
3、应用场景:跟定义常量的应用场景类似,但是比常量更加规范
public class Main {
public static void main(String[] args) {
move(3);
move2(A.DOWN);
}
//使用定义常量的方法
public static void move(int d) { //此处的参数值没有受约束,也就是你传0、1以外的整数值都行
switch (d) {
case B.UP:
System.out.println("向上");
break;
case B.DOWN:
System.out.println("向下");
break;
default:
System.out.println("输入有误");
}
}
//使用枚举定义的方法
public static void move2(A a) { //此处的参数值受约束,你只能传枚举类型A的参数
switch (a) {
case UP:
System.out.println("向上");
break;
case DOWN:
System.out.println("向下");
}
}
}
enum A {
UP, DOWN
}
class B {
public static final int UP = 0;
public static final int DOWN = 1;
}
抽象类
1、抽象类示例:
public class Main {
public static void main(String[] args) {
//抽象类不能被创建,会报错
//A a = new A();
new B().show();
}
}
abstract class A { //可以定义为就是为了"生孩子"的类
public void show2() {
System.out.println("该方法不用重写");
}
public abstract void show();//抽象方法只有方法体没有方法声明
}
class B extends A { //只能通过继承的方式,并且还要重写抽象类中所有抽象方法
@Override
public void show() {
System.out.println("重写了抽象类的show方法");
}
}
2、抽象类的好处:
父类知道每个子类都要做某个行为,但每个子类要做的情况不一样,父类就定义成抽象方法,交给子类去重写实现,我们抽出这样的抽象类,就是为了更好的支持多态
3、抽象类的模版方法设定
public class Main {
public static void main(String[] args) {
B b = new B();
b.template();
C c = new C();
c.template();
}
}
abstract class A {
public final void template() {
System.out.println("这是模版开头");
customize(); //相当于父类调用子类的方法
System.out.println("这是模版结尾");
}
public abstract void customize();
}
class B extends A {
@Override
public void customize() {
System.out.println("这是B的自定义内容");
}
}
class C extends A {
@Override
public void customize() {
System.out.println("这是C的自定义内容");
}
}
注意:模版方法是给子类直接使用的,不能被子类重写(一旦被重写了模版的意义就失效了),所以最好要加个final修饰
接口
1、概念:
(1)实现类可以实现多个接口,必须重写完全部接口的全部抽象方法,否则实现类需要定义成抽象类
(2)接口中的属性会默认加上一系列修饰关键字:public static final;方法前面会默认加上:public abstract。
2、示例:
// 定义接口
interface Animal {
void makeSound(); // 动物发出声音的方法
}
// 实现接口的第一个类
class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("汪汪!");
}
}
// 实现接口的第二个类
class Cat implements Animal {
@Override
public void makeSound() {
System.out.println("喵~");
}
}
// 测试类
public class Main {
public static void main(String[] args) {
// 声明接口类型的变量,指向不同的实现类对象,体现多态
Animal animal1 = new Dog();
Animal animal2 = new Cat();
// 调用方法,根据实际对象执行不同的行为
animal1.makeSound(); // 输出:汪汪!
animal2.makeSound(); // 输出:喵~
}
}
3、JDK8以后新增的接口特性:
(1)默认方法:
interface Animal {
default void breathe() {
System.out.println("Animal is breathing.");
}
}
实现类可以继承默认实现,也可以重写它。
(2)静态方法:
interface Animal {
static void info() {
System.out.println("This is an animal interface.");
}
}
常用于工具方法或辅助方法,调用时直接使用:"接口名.方法名"
(2)私有方法(JDK9+):
interface Animal {
default void method1() {
System.out.println("Method 1");
helper();
}
private void helper() {
System.out.println("Helper method");
}
}
只能在接口内部调用
4、接口的注意事项:
(1)接口与接口可以实现多继承,一个接口可以同时继承多个接口
类与类:单继承一个类只能继承一个直接父类
类与接口:多实现,一个类可以同时实现多个接口。
接口与接口:多继承,一个接口可以同时继承多个接口。
示例:
interface A {
public void a();
}
interface B {
public void b();
}
interface C extends A , B{
public void c();
}
class D implements C {
@Override
public void c() {
}
@Override
public void a() {
}
@Override
public void b() {
}
}
(2)一个接口继承多个接口,如果多个接口中存在方法签名冲突(返回类型不一样但是方法名一样),则此时不支持多继承,也不支持多实现(报错)
(3)一个类维承了父类,又同时实现了接口,如果父类中和接口中有同名的方法,实现类会优先用父类的:
interface A {
default void show(){
System.out.println("A");
}
}
class B {
public void show() {
System.out.println("B");
}
}
class C extends B implements A {
public void go(){
show(); //优先调父类的show方法(就近)
A.super.show(); //调接口A的方法
}
}
使用 .super 可以引用某个特定父类或接口中的成员。当它与接口一起使用时,允许你访问该接口中定义的默认方法
(4)一个类实现了多个接口,如果多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可
interface A {
default void show() {
System.out.println("A");
}
}
interface B {
default void show() {
System.out.println("B");
}
}
class C implements A, B {
@Override
public void show() {
A.super.show(); //只调用A接口的方法
B.super.show(); //只调用B接口的方法
}
}
抽象类和接口的对比
1、相同点:
(1)多是抽象形式,都可以有抽象方法,都不能创建对象
(2)都是派生子类形式:抽象类是被子类继承使用,接口是被实现类实现
(3)一个类继承抽象类,或者实现接口,都必须重写完他们的抽象方法或自己要成为抽象类,否则就报错
(4)都能支持的多态,都能够实现解耦合
2、不同点:
(1)抽象类中可以定义类的全部普通成员,接口只能定义常量,抽象方法(JDK8新增的三种方式)
(2)抽象类只能被类单继承,接口可以被类多实现
(3)一个类继承抽象类就不能再继承其他类,一个类实现了接口(还可以继承其他类或者实现其他接口)
(4)抽象类体现模板思想:更利于做父类,实现代码的复用性(最佳实践)
(5)接口更适合做功能的解耦合:解合性更强更灵活(最佳实践)
综合案例(家电的开关操作)
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
JD[] jds = new JD[3];
jds[0] = new Light("吊灯", false);
jds[1] = new Fridge("冰箱", false);
jds[2] = new Washer("洗衣机", false);
Controller controller = Controller.getInstance();
while (true) {
controller.printAllStatus(jds);
System.out.println("\n请输入你要按要开关的电器");
String command = new Scanner(System.in).nextLine();
switch (command) {
case "1":
controller.operate(jds[0]);
break;
case "2":
controller.operate(jds[1]);
break;
case "3":
controller.operate(jds[2]);
break;
default:
System.out.println("输入有误");
}
}
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class JD implements Switch {
private String name;
private Boolean status;
@Override
public void press() {
this.status = !this.status;
}
public String getStatusName() {
return this.status ? "开" : "关";
}
}
class Light extends JD {
public Light(String name, Boolean status) {
super(name, status);
}
}
class Fridge extends JD {
public Fridge(String name, Boolean status) {
super(name, status);
}
}
class Washer extends JD {
public Washer(String name, Boolean status) {
super(name, status);
}
}
interface Switch {
public void press();
}
//设置成单例模式
class Controller {
private static Controller controller;
private Controller() {
}
public static Controller getInstance() {
if (controller == null) {
controller = new Controller();
}
return controller;
}
public void printAllStatus(JD[] jds) {
System.out.println("\n所有电器状态 ===============");
for (int i = 0; i < jds.length; i++) {
System.out.println(jds[i].getName() + "开关状态为" + jds[i].getStatusName());
}
}
public void operate(JD jd) {
System.out.println("\n正在操作==============");
System.out.println(jd.getName() + "开关原始状态:" + jd.getStatusName());
jd.press();
System.out.println("点击了开关按钮");
System.out.println(jd.getName() + "开关现有状态:" + jd.getStatusName());
}
}
代码块
1、静态代码块:static { },属于类,类加载时它也加载,并且只自动执行一次 。多用于对静态资源的初始化(用static修饰的成员)
2、代码块:{ },属于对象,对象每被创建一次代码块就自动执行一次。多用于非静态资源的初始化
内部类
1、成员内部类
(1)就是类中的一个普通成员,类似前面我们学过的普通成员变量、成员方法
(2)创建对象:外部类名.内部类名 对象名 =new 外部类(...).new 内部类(...)
2、静态内部类
(1)有static修饰的内部类
(2)创建对象:外部类名.内部类名 对象名 =new 外部类.内部类(...)
(3)可以直接访问外部类的静态成员,不能直接访问外部类的实例成员(因为静态成员会比实例成员更优先加载)
3、匿名内部类
(1)示例:
public class test {
public static void main(String[] args) {
Animal animal = new Animal(){
@Override
public void cry() {
System.out.println("喵喵喵");
}
};
animal.cry();
}
}
abstract class Animal{
public abstract void cry();
}
匿名内部类实际上是有名字:外部类名$编号.class(如此示例中为test$1.class)
匿名内部类本质是一个子类,同时会立即构建一个子类对象
(2)常见的使用形式
public class test {
public static void main(String[] args) {
//完整写法
Animal animal = new Animal() {
@Override
public void cry() {
System.out.println("喵喵喵");
}
};
start(animal);
//缩写
start(new Animal() {
@Override
public void cry() {
System.out.println("汪汪汪");
}
});
}
public static void start(Animal animal) {
System.out.println("开始叫....");
animal.cry();
System.out.println("结束...");
}
}
interface Animal{
public abstract void cry();
}
(3)使用场景:开发中不是我们要主动去写匿名内部类,而是用别人的功能的时候,别人可以让我们写一个匿名内部类,我们才会写
比如,数组排序:
import java.util.Arrays;
import java.util.Comparator;
public class test {
public static void main(String[] args) {
Integer[] arr = {6, 2, 5, 8, 0, 7, 10, 100, 88};
Arrays.sort(arr,new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
System.out.println(Arrays.toString(arr));
}
}
Lambda表达式
1、概念:
(1)使用Lambda函数替代某些匿名内部类对象,从而让程序代码更简洁,可读性更好
(2)可以用于替代并简化函数式接口的匿名内部类,例如:
public class test {
public static void main(String[] args) {
//普通写法
Animal animal = new Animal() {
@Override
public void cry() {
System.out.println("11111");
}
};
//lambda写法
Animal animal2 = () -> {
//相当于直接编辑重写方法中的方法体
System.out.println("11111");
};
animal.cry();
animal2.cry();
}
}
//声明函数式接口的注解
@FunctionalInterface
interface Animal {
//在函数式接口中有且只能有一个方法,多了会报错
public void cry();
}
2、简化方式:
(1)参数类型可以省略(自动类型推断)
Calculator c = (x, y) -> {
return x + y;
};
(2)如果只有一个语句,可以省略 return 和 {}
Calculator c = (x, y) -> x + y;
(3)如果只有一个参数,可以省略小括号 ()
Calculator c = x -> x + 1;
3、可以引用方法(使用方法引用 ::)
(1)静态方法引用:
使用方法:"类名::静态方法"
使用场景:如果某个Lambda表达式里只是调用一个静态方法,并且“→”前后参数的形式一致,就可以使用静态方法引用
public class test {
public static void main(String[] args) {
Integer[] ints = new Integer[3];
ints[0] = 9;
ints[1] = 2;
ints[2] = 100;
Arrays.sort(ints,intComparator::compare);
}
}
class intComparator {
public static int compare(int a, int b) {
return a - b;
}
}
(2)实例方法引用:
使用方法:"对象名::静态方法"
使用场景:跟静态方法一致
public class test {
public static void main(String[] args) {
Integer[] ints = new Integer[3];
ints[0] = 9;
ints[1] = 2;
ints[2] = 100;
Arrays.sort(ints, IntComparator::compare);
IntComparator intComparator = new IntComparator(); //实例方法引用就比静态方法要多创建一个对象
Arrays.sort(ints, intComparator::compare2);
}
}
class IntComparator {
public static int compare(int a, int b) {
return a - b;
}
public int compare2(int a, int b) {
return a - b;
}
}
(3)特定类型方法引用:
使用方法:"特定类的名称::方法"
使用场景:如果某个Lambda表达式里只是调用一个特定类型的实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用
String[] strs = {"hello", "Hello" ,"apple" ,"Apple"};
//简化前
Arrays.sort(strs,((o1, o2) -> o1.compareToIgnoreCase(o2)));
//简化后
Arrays.sort(strs,(String::compareToIgnoreCase));
(4)构造方法引用:
使用方法:"类名::new"
使用场景:如果某个Lambda表达式里只是在创建对象,并且“→”前后参数情况一致,就可以使用构造器引用
public class test {
public static void main(String[] args) {
//简化前
CreateAnimal createAnimal = new CreateAnimal() {
@Override
public Animal createAnimal(String name) {
return new Animal(name);
}
};
//简化中
CreateAnimal createAnimal2 = name -> new Animal(name);
//简化后
CreateAnimal createAnimal3 = Animal::new;
}
}
interface CreateAnimal{
public Animal createAnimal(String name);
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Animal {
String name;
}
559

被折叠的 条评论
为什么被折叠?



