【Object类】
地位:是所有类的祖宗。它是
java.lang
包中的一个类,所有其他类(无论是直接还是间接)都继承自Object
类。常用方法:
🍋
equals(Object obj)
作用:用于比较两个对象是否相等。
返回值:如果两个对象相等,返回
true
;否则返回false
。默认实现:比较两个对象的内存地址(即是否是同一个对象)。如果需要比较对象的内容,需要重写该方法。
public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object obj) { if (this == obj) return true; // 检查是否是同一个对象 if (obj == null || getClass() != obj.getClass()) return false; // 检查是否为null或类型是否一致 Person person = (Person) obj; return age == person.age && name.equals(person.name); } } public class Main { public static void main(String[] args) { Person p1 = new Person("Alice", 25); Person p2 = new Person("Alice", 25); // System.out.println(p1.equals(p2)); // 使用默认实现,比较地址,输出:false System.out.println(p1.equals(p2)); // 重写equals()方法,比较内容,输出:true } }
🍉
toString()
作用:返回对象的字符串表示形式。
返回值:一个字符串,描述对象的内容。
默认实现:返回对象内存地址。通常需要重写该方法,以提供更有意义的字符串表示。
public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{name='" + name + "', age=" + age + "}"; } } public class Main { public static void main(String[] args) { Person p = new Person("Alice", 25); // System.out.println(p); // 输出:api.Person@5e8c92f4 // System.out.println(p.toString()); // 输出:api.Person@5e8c92f4 System.out.println(p); // 重写toString()方法,输出:Person{name='Alice', age=25} } }
🥝
hashCode()
作用:返回对象的哈希码值。
返回值:一个整数,表示对象的哈希码。
默认实现:根据对象的内存地址生成哈希码。如果重写了
equals()
方法,通常也需要重写hashCode()
方法,以确保两个相等的对象具有相同的哈希码。public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Person person = (Person) obj; return age == person.age && name.equals(person.name); } @Override public int hashCode() { return Objects.hash(name, age); } } public class Main { public static void main(String[] args) { Person p1 = new Person("Alice", 25); Person p2 = new Person("Alice", 25); System.out.println(p1.hashCode() == p2.hashCode()); // 输出:true } }
🍏
getClass()
作用:返回对象的运行时类。
返回值:一个
Class
对象,表示对象所属的类。public class Main { public static void main(String[] args) { Object obj = new String("Hello"); System.out.println(obj.getClass().getName()); // 输出:java.lang.String } }
🍇
clone()
作用:创建并返回对象的浅拷贝。
返回值:一个新对象,是当前对象的副本。
默认实现:通过调用
Object.clone()
方法实现。需要实现Cloneable
接口,并重写clone()
方法。public class Person implements Cloneable { private String name; private int age; private Address address; public Person(String name, int age, Address address) { this.name = name; this.age = age; this.address = address; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "Person{name='" + name + "', age=" + age + ", address=" + address + "}"; } } public class Address { private String city; private String street; public Address(String city, String street) { this.city = city; this.street = street; } @Override public String toString() { return "Address{city='" + city + "', street='" + street + "'}"; } } public class Main { public static void main(String[] args) throws CloneNotSupportedException { Address address = new Address("Beijing", "No.1 Street"); Person p1 = new Person("Alice", 25, address); Person p2 = (Person) p1.clone(); System.out.println(p1); // 输出:Person{name='Alice', age=25, address=Address{city='Beijing', street='No.1 Street'}} System.out.println(p2); // 输出:Person{name='Alice', age=25, address=Address{city='Beijing', street='No.1 Street'}} // 修改p2的地址信息 p2.address.city = "Shanghai"; System.out.println(p1); // 输出:Person{name='Alice', age=25, address=Address{city='Shanghai', street='No.1 Street'}} System.out.println(p2); // 输出:Person{name='Alice', age=25, address=Address{city='Shanghai', street='No.1 Street'}} } }
浅拷贝
定义:浅拷贝是指创建一个新对象,然后将当前对象的非静态字段复制到新对象中。如果字段是值类型的(如基本数据类型或字符串),那么将复制字段的值;如果字段是引用类型的(如数组或其他对象),则复制引用但不复制引用的对象。因此,原始对象和副本对象将引用同一个对象。
实现方式:
- 实现
Cloneable
接口。- 重写
Object.clone()
方法,并将其访问权限改为public
。深拷贝
定义:深拷贝是指创建一个新对象,然后将当前对象的所有字段值复制到新对象中。如果字段是引用类型,则会递归地创建新的对象副本,而不是复制引用。因此,原始对象和副本对象完全独立,修改一个对象不会影响另一个对象。
实现方式:
- 实现
Cloneable
接口。- 重写
Object.clone()
方法,并在方法中递归地克隆所有引用类型的字段。public class Person implements Cloneable { ... @Override protected Object clone() throws CloneNotSupportedException { Person clonedPerson = (Person) super.clone(); // 递归克隆引用类型的字段 clonedPerson.address = (Address) this.address.clone(); return clonedPerson; } ... } public class Address implements Cloneable { ... @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } ... } public class Main { public static void main(String[] args) throws CloneNotSupportedException { Address address = new Address("Beijing", "No.1 Street"); Person p1 = new Person("Alice", 25, address); Person p2 = (Person) p1.clone(); System.out.println(p1); // 输出:Person{name='Alice', age=25, address=Address{city='Beijing', street='No.1 Street'}} System.out.println(p2); // 输出:Person{name='Alice', age=25, address=Address{city='Beijing', street='No.1 Street'}} // 修改p2的地址信息 p2.address.city = "Shanghai"; System.out.println(p1); // 输出:Person{name='Alice', age=25, address=Address{city='Beijing', street='No.1 Street'}} System.out.println(p2); // 输出:Person{name='Alice', age=25, address=Address{city='Shanghai', street='No.1 Street'}} } }
总结:在实际开发中,合理重写
Object
类的方法(如equals()
、hashCode()
、toString()
等)是非常重要的。
【Objects类】
地位:
Objects
类是java.util
包中的一个工具类,提供了一系列静态方法,用于操作对象(特别是null
值的处理)。这些方法可以简化代码,提高代码的可读性和安全性。!!注意区分:
Object
类是所有类的父类,而Objects
类是一个工具类。常用方法:
🍎
Objects.equals(Object a, Object b)
作用:比较两个对象是否相等。
特点:如果两个对象都为
null
,则返回true
;如果只有一个对象为null
,则返回false
;否则调用equals()
方法进行比较。public class Main { public static void main(String[] args) { String str1 = null; String str2 = null; System.out.println(Objects.equals(str1, str2)); // 输出:true String str3 = "Hello"; String str4 = "Hello"; System.out.println(Objects.equals(str3, str4)); // 输出:true String str5 = "Hello"; String str6 = "World"; System.out.println(Objects.equals(str5, str6)); // 输出:false } }
原理:看下
Objects.equals的源码就知道了,如下:
🥦isNull()
作用:检查传入的对象是否为
null
。返回值:如果对象为
null
,返回true
。如果对象不为null
,返回false
。import java.util.Objects; public class Main { public static void main(String[] args) { String str1 = null; String str2 = "Hello"; System.out.println(Objects.isNull(str1)); // 输出:true System.out.println(Objects.isNull(str2)); // 输出:false } }
Objects.isNull的源码分析:
【包装类】
一、作用
- 将基本数据类型封装成对象,允许基本数据类型作为对象使用,从而可以利用面向对象的特性(如泛型、集合框架等)。Java为每种基本数据类型都提供了一个对应的包装类,这些包装类都位于
java.lang
包中。- 提供工具(静态)方法,用于基本数据类型和字符串之间的转换,以及一些常见操作。
二、使用
1. 自动装箱(Autoboxing)
自动装箱是指Java编译器在需要时自动将基本数据类型转换为其对应的包装类。
2. 自动拆箱(Unboxing)
自动拆箱是指Java编译器在需要时自动将包装类转换为其对应的基本数据类型。
public class Main { public static void main(String[] args) { // 将字符串转换为整数 String str = "123"; int num = Integer.parseInt(str); System.out.println(num); // 输出:123 // 将整数转换为字符串 int num2 = 456; String str2 = Integer.toString(num2); System.out.println(str2); // 输出:456 // 获取最大值和最小值 System.out.println(Integer.MAX_VALUE); // 输出:2147483647 System.out.println(Integer.MIN_VALUE); // 输出:-2147483648 // 比较两个包装类对象 Integer i1 = 100; Integer i2 = 100; System.out.println(i1 == i2); // 输出:true(因为Integer缓存机制) Integer i3 = 1000; Integer i4 = 1000; System.out.println(i3 == i4); // 输出:false(因为Integer缓存范围是-128到127) } }
三、静态方法
1.
parseInt(String s)
:将字符串转换为整数。int num = Integer.parseInt("123");
2.
toString(int i)
:将整数转换为字符串。String str = Integer.toString(456);
3.
valueOf(String s)
:将字符串转换为包装类对象。Integer i = Integer.valueOf("123");
4.
MAX_VALUE
和MIN_VALUE
:获取包装类的最大值和最小值。System.out.println(Integer.MAX_VALUE); // 输出:2147483647 System.out.println(Integer.MIN_VALUE); // 输出:-2147483648
四、注意事项
1. 性能问题
虽然包装类提供了很多便利,但它们是对象,因此比基本数据类型占用更多的内存。在性能敏感的场景中,应尽量使用基本数据类型。
2. 缓存机制的限制
包装类的缓存机制只适用于某些范围内的值。例如,
Integer
类只缓存-128
到127
之间的值。当使用自动装箱或Integer.valueOf()
方法时,如果值在这个范围内,会直接返回缓存的对象。超出这个范围时,每次调用都会创建新的对象。3.
==
运算符的使用在比较包装类对象时,应避免使用
==
运算符,因为这会比较对象的引用,而不是值。如果需要比较值,应使用equals()
方法。public class Main { public static void main(String[] args) { Integer i1 = 100; Integer i2 = 100; System.out.println(i1 == i2); // 输出:true(因为Integer缓存机制) Integer i3 = 1000; Integer i4 = 1000; System.out.println(i3 == i4); // 输出:false(因为Integer缓存范围是-128到127) System.out.println(i3.equals(i4)); // 输出:true(比较值) } }
【StringBuilder类】
一、用法与局限
作用:
StringBuilder
是一个用于高效处理字符串拼接的类。它提供了一种可变的字符序列,允许在运行时动态修改字符串的内容,而不会像String
那样每次操作都创建一个新的对象。因此,
StringBuilder
在处理大量字符串拼接时性能更高,非常适合用于构建复杂的字符串。
局限:
StringBuilder
是线程不安全的,如果需要线程安全的字符串构建器,可以使用StringBuffer
(StringBuffer
的性能稍差,但提供了线程安全的保证)。二、构造方法
1. 无参构造方法:创建一个空的
StringBuilder
,默认初始容量为16。StringBuilder sb = new StringBuilder();
2. 指定初始容量的构造方法:创建一个具有指定初始容量的
StringBuilder
。StringBuilder sb = new StringBuilder(32);
3. 从字符串初始化的构造方法:创建一个包含指定字符串内容的
StringBuilder
。StringBuilder sb = new StringBuilder("Hello");
三、常用方法
🥭
append(Object obj)
作用:将指定对象的字符串表示形式拼接到
StringBuilder
的末尾。返回值:返回当前
StringBuilder
对象。StringBuilder sb = new StringBuilder(); sb.append("Hello"); sb.append(" "); sb.append(123); // 也可以链式拼接 // sb.append("Hello").append(" ").append(123); System.out.println(sb.toString()); // 输出:Hello 123
🥑
reverse()
作用:反转
StringBuilder
中的字符。返回值:返回当前
StringBuilder
对象。StringBuilder sb = new StringBuilder("Hello"); sb.reverse(); System.out.println(sb.toString()); // 输出:olleH
🍓
toString()
作用:将
StringBuilder
的内容转换为String。返回值:返回一个
String
对象。StringBuilder sb = new StringBuilder("Hello"); String str = sb.toString(); System.out.println(str); // 输出:Hello
🥬
length()
作用:返回
StringBuilder
的长度。返回值:返回一个整数,表示
StringBuilder
的字符数。StringBuilder sb = new StringBuilder("Hello"); System.out.println(sb.length()); // 输出:5
StringBuffer
的作用、构造方法和常用方法等都与StringBuilder
一样,唯一的区别就是StringBuffer
是线程安全的,而StringBuilder
是线程不安全的。public class Main { public static void main(String[] args) { long startTime, endTime; // 使用 StringBuffer startTime = System.currentTimeMillis(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < 1000000; i++) { sb.append(i); } endTime = System.currentTimeMillis(); System.out.println("StringBuffer time: " + (endTime - startTime) + " ms"); //输出:200 ms // 使用 StringBuilder startTime = System.currentTimeMillis(); StringBuilder sb2 = new StringBuilder(); for (int i = 0; i < 1000000; i++) { sb2.append(i); } endTime = System.currentTimeMillis(); System.out.println("StringBuilder time: " + (endTime - startTime) + " ms"); //输出:100 ms } }
总结:
StringBuffer
:线程安全的可变字符序列,适用于多线程环境。
StringBuilder
:线程不安全的可变字符序列,适用于单线程环境,性能更高。
【StringJoiner 类】
作用:
StringJoiner
是 Java 8 引入的一个用于拼接字符串的工具类,它允许以指定的分隔符将一组字符串连接成一个单独的字符串。它基于StringBuilder
实现,因此性能与StringBuilder
相当,且是非线程安全的。构造方法:
1. 仅指定分隔符:前缀和后缀默认为空字符串。
StringJoiner joiner = new StringJoiner(",");
2. 指定分隔符、前缀和后缀:可以自定义拼接结果的格式。
StringJoiner joiner = new StringJoiner(",", "[", "]");
常用方法:
🍥
add(CharSequence newElement)
添加一个新的字符串元素。如果元素为
null
,则添加字符串"null"
。joiner.add("Apple").add("Banana");
🍺
toString()
返回当前拼接的结果。如果未添加任何元素,则返回前缀和后缀的组合,或者通过
setEmptyValue
设置的空值。String result = joiner.toString();
🍟
merge(StringJoiner other)
将另一个
StringJoiner
的内容(不包括前缀和后缀)作为新元素添加到当前StringJoiner
中。StringJoiner anotherJoiner = new StringJoiner(",").add("Orange").add("Grapes"); joiner.merge(anotherJoiner);
🍔
length()
返回当前拼接结果的长度。
int length = joiner.length();
【Math类】
Math相当于是一个工具类,提供的方法全部是完成数学操作的静态方法,直接用类名调用即可,而无需创建实例。
常用方法:
(1) 基本数学运算
绝对值
double abs(double a)
最大值和最小值
double max(double a, double b) double min(double a, double b)
四舍五入
double round(double a)
向上取整和向下取整
double ceil(double a) double floor(double a)
(2) 幂运算
平方根
double sqrt(double a)
立方根
double cbrt(double a)
指数运算
double pow(double a, double b)
(3) 三角函数
正弦、余弦、正切
double sin(double a) double cos(double a) double tan(double a)
反正弦、反余弦、反正切
double asin(double a) double acos(double a) double atan(double a)
(4) 随机数生成
生成随机数
static double random()
(5) 其他常用方法
对数运算
double log(double a) // 自然对数 double log10(double a) // 以10为底的对数
角度转换
double toRadians(double angdeg) // 将角度转换为弧度 double toDegrees(double angrad) // 将弧度转换为角度
【System类】
System代表系统,也是一个工具类,里面的方法都是与系统操作相关的静态方法。因此可以直接通过类名调用,而无需创建实例。
常用方法:
获取当前时间(毫秒)
static long currentTimeMillis()
示例:
long currentTime = System.currentTimeMillis(); System.out.println("Current Time in Milliseconds: " + currentTime);
退出程序
static void exit(int status)
示例:
System.exit(0); // 正常退出程序
加载动态库
static void load(String filename) static void loadLibrary(String libname)
示例:
System.loadLibrary("myLibrary"); // 加载本地库
【Runtime类】
Runtime
类代表了Java程序的运行时环境,用于管理Java虚拟机(JVM)的运行状态。每个Java程序在运行时都会启动一个JVM实例,而每个JVM实例都会自动包含一个Runtime
类的实例。Runtime
类是单例模式的实现,无法直接实例化,只能通过Runtime.getRuntime()
方法获取当前运行时环境的实例。常用方法:
方法 描述 public static Runtime getRuntime()
获取当前运行时环境的 Runtime
实例。public void exit(int status)
终止当前的虚拟机, status
为退出状态码。public Process exec(String command)
执行指定的命令,启动一个新的进程。 public int availableProcessors()
返回JVM可用的处理器数量(通常为CPU核心数)。 public long freeMemory()
返回JVM当前空闲的内存量(以字节为单位)。 public long totalMemory()
返回JVM当前总共可用的内存量(以字节为单位)。 public void gc()
建议JVM执行垃圾回收。 public class RuntimeExample { public static void main(String[] args) { // 获取 Runtime 实例 Runtime runtime = Runtime.getRuntime(); // 获取系统资源信息 System.out.println("可用处理器数: " + runtime.availableProcessors()); System.out.println("JVM 总内存: " + runtime.totalMemory() / 1024 / 1024 + " MB"); System.out.println("JVM 空闲内存: " + runtime.freeMemory() / 1024 / 1024 + " MB"); System.out.println("JVM 最大可用内存: " + runtime.maxMemory() / 1024 / 1024 + " MB"); // 执行外部程序 try { Process process = runtime.exec("notepad.exe"); // 在Windows上打开记事本 Thread.sleep(3000); // 等待3秒 process.destroy(); // 关闭进程 } catch (Exception e) { e.printStackTrace(); } } }
注意事项:
Runtime
类的方法可能会抛出异常,例如exec()
方法可能会抛出IOException
。使用
exit()
方法时需谨慎,因为它会立即终止JVM,可能导致资源未正确释放。
gc()
方法只是建议JVM进行垃圾回收,并不能保证立即执行。
【BigDecimal类】
BigDecimal
类是Java中用于精确表示和计算浮点数的类,避免了使用float
和double
类型时可能出现的精度问题。BigDecimal
类是不可变类,每次操作都会返回一个新的BigDecimal
实例。常用方法:
【日期、时间类】
🐋Date
需要知道:如何创建日期对象?如何获取时间毫秒值?如何将时间毫秒值转成日期对象?
🐻SimpleDateFormat
需要知道:SimpleDateFormat有什么作用?如何创建SimpleDateFormat对象?格式化方法?解析时间的方法?
import java.util.Date; public class Test1Date { public static void main(String[] args) { // 目标:掌握Date日期类的使用。 // 1、创建一个Date的对象:代表系统当前时间信息的。 Date d = new Date(); System.out.println(d); // 2、拿到时间毫秒值。 long time = d.getTime(); System.out.println(time); // 3、把时间毫秒值转换成日期对象: 2s之后的时间是多少。 time += 2 * 1000; Date d2 = new Date(time); System.out.println(d2); // 4、直接把日期对象的时间通过setTime方法进行修改 Date d3 = new Date(); d3.setTime(time); System.out.println(d3); System.out.println("-----------------------------------------------------"); // 目标:掌握SimpleDateFormat的使用。 // 5、格式化日期对象,和时间 毫秒值。 SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a"); String rs = sdf.format(d); String rs2 = sdf.format(time); System.out.println(rs); System.out.println(rs2); // 目标:掌握SimpleDateFormat解析字符串时间 成为日期对象。 String dateStr = "2022-12-12 12:12:11"; // 6、创建简单日期格式化对象 , 指定的时间格式必须与被解析的时间格式一模一样,否则程序会出bug。 SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date d2 = sdf2.parse(dateStr); System.out.println(d2); } }
🐭Calendar
需要知道:如何创建Calender对象?Calender常用方法?
注意:Calender是可变对象,一旦修改后其对象本身表示的时间将产生变化。
import java.util.Calendar; import java.util.Date; public class Test4Calendar { public static void main(String[] args) { // 目标:掌握Calendar的使用和特点。 // 1、得到系统此刻时间对应的日历对象。 Calendar now = Calendar.getInstance(); System.out.println(now); // 2、获取日历中的某个信息 int year = now.get(Calendar.YEAR); System.out.println(year); int days = now.get(Calendar.DAY_OF_YEAR); System.out.println(days); // 3、拿到日历中记录的日期对象。 Date d = now.getTime(); System.out.println(d); // 4、拿到时间毫秒值 long time = now.getTimeInMillis(); System.out.println(time); // 5、修改日历中的某个信息 now.set(Calendar.MONTH, 9); // 修改月份成为10月份。 now.set(Calendar.DAY_OF_YEAR, 125); // 修改成一年中的第125天。 System.out.println(now); // 6、为某个信息增加或者减少多少 now.add(Calendar.DAY_OF_YEAR, 100); now.add(Calendar.DAY_OF_YEAR, -10); now.add(Calendar.DAY_OF_MONTH, 6); now.add(Calendar.HOUR, 12); now.set(2026, 11, 22); System.out.println(now); } }
以上3类是JDK8之前的时间API。JDK8之后有修改新增的时间API,即用即查即可。
【Arrays类】
Arrays
类代表数组操作类,工具类,里面都是操作数组的静态方法。因此可以直接通过类名调用,而无需创建实例。常用方法:
方法 描述 public static void sort(T[] a)
对数组进行升序排序 public static void sort(T[] a, Comparator<? super T> c)
使用自定义比较器对数组进行排序 public static int binarySearch(T[] a, T key)
在已排序的数组中使用二分查找法查找指定元素 public static void fill(T[] a, T val)
用指定值填充数组 public static boolean equals(T[] a, T[] a2)
比较两个数组是否相等 public static String toString(T[] a)
返回数组的字符串表示 public static T[] copyOf(T[] original, int newLength)
创建一个指定长度的数组副本 public static T[] copyOfRange(T[] original, int from, int to)
创建一个数组的子数组副本
🐼自定义排序:
法一:让该对象的类实现Comparable(比较规则)接口,然后重写compareTo方法,自己制定比较规则。
// 方式一:让类实现比较规则接口Comparable public class Student implements Comparable<Student>{ private String name; private int age; private double height; .... @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", height=" + height + '}'; } /** 比较方法 比较者:this 被比较者:o * @param o * @return */ @Override public int compareTo(Student o) { // 制定比较规则:(升序规则) // 如果认为比较者大于被比较者 返回正整数。 // 如果认为比较者小于被比较者 返回负整数。 // 如果认为比较者等于被比较者 返回0。 // 按照年龄排序(升序) // if(this.age > o.age) { // return 1; // }else if(this.age < o.age){ // return -1; // } // return 0; //return this.age - o.age; // 搞定了(升序) return o.age - this.age ; // 搞定了(降序了) } }
法二:使用
sort(T[] a, Comparator<? super T> c)方法,创建
Comparator比较器接口的匿名内部类对象,然后自己制定比较规则。Arrays.sort(students, new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { // 制定比较规则:(升序规则) // 如果认为比较者大于被比较者 返回正整数。 // 如果认为比较者小于被比较者 返回负整数。 // 如果认为比较者等于被比较者 返回0。 // if(o1.getHeight() > o2.getHeight()){ // return 1; // }else if(o1.getHeight() < o2.getHeight()){ // return -1; // } // return 0; // return Double.compare(o1.getHeight(), o2.getHeight()); // 升序 return Double.compare(o2.getHeight(), o1.getHeight()); // 降序 } }); System.out.println(Arrays.toString(students));
【Lambda表达式】
作用:简化匿名内部类的代码写法。
格式:(被重写方法的形参列表)->{
被重写方法的方法体代码;
};
注意:Lambda表达式并不是说能简化全部匿名内部类的写法,只能简化函数式接口的匿名内部类。
什么是函数式接口?就是有且仅有一个抽象方法的接口。
提示:有 @FunctionalInterface 注解的接口一定是函数式接口。
public class LambdaTest { public static void main(String[] args) { // 目标:认识Lambda表达式. // Animal a = new Animal(){ // @Override // public void run() { // System.out.println("狗跑的贼快~~"); // } // }; // a.run(); // 注意:Lambda表达式并不是说能简化全部匿名内部类的写法,只能简化函数式接口的匿名内部类。 // 错误的代码! // Animal a = () -> { // System.out.println("狗跑的贼快~~"); // }; // a.run(); // 正确的代码: // Swimming s = new Swimming(){ // @Override // public void swim() { // System.out.println("学生快乐的游泳~~~~"); // } // }; // s.swim(); Swimming s = () -> { System.out.println("学生快乐的游泳~~~~"); }; s.swim(); } } interface Swimming{ void swim(); } abstract class Animal{ public abstract void run(); }
省略写法我觉得没必要,先略过!
【方法引用】
静态方法引用
格式:类名::静态方法
使用场景:如果某个Lambda表达式里只是调用一个静态方法,并且前后参数的形式一致,就可以使用静态方法引用。
实例方法引用
格式:对象名::实例方法
使用场景:如果某个Lambda表达式里只是调用一个实例方法,并且前后参数的形式一致,就可以使用实例方法引用。
// Test.java import java.util.Arrays; import java.util.Comparator; public class Test { public static void main(String[] args) { Student[] students = new Student[4]; students[0] = new Student("蜘蛛精", 169.5, 23); students[1] = new Student("紫霞", 163.8, 26); students[2] = new Student("紫霞", 163.8, 26); students[3] = new Student("至尊宝", 167.5, 24); // 原始写法:对数组中的学生对象,按照年龄升序排序 // Arrays.sort(students, new Comparator<Student>() { // @Override // public int compare(Student o1, Student o2) { // return o1.getAge() - o2.getAge(); // 按照年龄升序排序 // } // }); // 使用Lambda简化后的形式 // Arrays.sort(students, (o1, o2) -> o1.getAge() - o2.getAge()); // Arrays.sort(students, (o1, o2) -> CompareByData.compareByAge(o1, o2)); // 静态方法引用 // Arrays.sort(students, CompareByData::compareByAge); System.out.println("--------------------------------------------------------------"); // Arrays.sort(students, (o1, o2) -> o2.getAge() - o1.getAge()); // 降序 CompareByData compare = new CompareByData(); // Arrays.sort(students, (o1, o2) -> compare.compareByAgeDesc(o1, o2)); // 降序 // 实例方法引用 Arrays.sort(students, compare::compareByAgeDesc); // 降序 System.out.println(Arrays.toString(students)); } } // CompareByData.java public class CompareByData { public static int compareByAge(Student o1, Student o2){ return o1.getAge() - o2.getAge(); // 升序排序的规则 } public int compareByAgeDesc(Student o1, Student o2){ return o2.getAge() - o1.getAge(); // 降序排序的规则 } }
特定类型的方法引用
格式:类型::方法
使用场景:如果某个Lambda表达式里只是调用一个实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,就可以使用特定类型的方法引用。
import java.util.Arrays; import java.util.Comparator; public class Test2 { public static void main(String[] args) { String[] names = {"boby", "angela", "Andy" ,"dlei", "caocao", "Babo", "jack", "Cici"}; // 进行排序(默认是按照字符串的首字符编号进行升序排序的) // Arrays.sort(names); // 要求忽略首字符大小写进行排序。 // Arrays.sort(names, new Comparator<String>() { // @Override // public int compare(String o1, String o2) { // // 制定比较规则。o1 = "Andy" o2 = "angela" // return o1.compareToIgnoreCase(o2); // } // }); // Arrays.sort(names, ( o1, o2) -> o1.compareToIgnoreCase(o2) ); // 特定类型的方法引用! Arrays.sort(names, String::compareToIgnoreCase); System.out.println(Arrays.toString(names)); } }
构造器引用
格式:类名::new
使用场景:如果某个Lambda表达式里只是在创建对象,并且前后参数的形式一致,就可以使用构造器引用。
还不是很理解,先做个笔记留个足迹,在开发中也没有必要刻意去简化,先写出来,再考虑简化 or 优化吧!hhhhhhh
以上!自学用,防遗忘!