Java基础、面向对象编程
Java基础
Java环境变量
1 | JAVA_HOME=jdk安装路径 |
数组
1 | // 创建数组的三种方式 |
变量
变量分类:
- 成员变量:类变量(static)、实例变量
- 局部变量:形参,方法体、代码块中声明的变量
存储位置:
- 局部变量:栈
- 实例变量:堆
- 类变量:方法区
变量匹配原则:
- 就近原则
形参传递机制
- 基本数据类型:传递数据值,即创建一个新的变量,并传递数据值。
- 引用数据类型:传递引用,即创建一个引用变量,并传递引用的地址。
可变参数
用于传递多个相同类型的参数,其实就是一个数组
如果形参还有其它参数,则可变参数必须放在参数列表的最后。
- 定义:
修饰符 返回值类型 方法名(参数类型... 形参名) {}
- 例子:Arrays类的asList方法,就用到了可变参数。
1 | public static <T> List<T> asList(T... a) { |
final 关键字
- final: 不可改变。可以用于修饰类、方法和变量。
- 类:被修饰的类,不能被继承。
- 方法:被修饰的方法,不能被重写。
- 变量:被final修饰的变量只能被赋值一次,不能更改;若是引用类型则不可修改其引用。
1 | 修饰符 final class 类名 {} |
Jvm内存分区
- 栈(stack): 存放局部变量, 方法运行时使用的内存
- 堆(Heap): 存储对象或者数组,new来创建的,都存储在堆内存。
- 堆内存数据的默认值: 0, 0.0, ‘\u0000’, false, null(引用)
- 方法区(Method Area): 存储已被虚拟机加载的类信息、常量、静态变量
- 本地方法栈: 为JVM使用native本地方法而准备的
- 程序计数器(Program Counter Register):记录下一条jvm指令的执行地址
- 通过程序计数器,来恢复线程的正确执行位置
面向对象
继承
继承提高了代码的维护性、拓展性,但增加了代码的耦合度(更改父类代码可能会导致子类发生变化)
语法:class 子类名 extends 父类名 {}
注意:
私有成员可以会被子类继承,但对子类来说是不可见的
成员变量不能被覆盖:子类定义了父类中存在的变量,则类中会有两个变量,一个是子类的一个是父类
接口与抽象类
定义接口
1 | public interface 接口名称 { |
定义抽象类
1 | 修饰符 abstract class 类名 { |
接口与抽象类的区别
- 接口的方法默认是 public,所有方法在接口中不能有实现(jdk8 可以有默认方法和静态方法,jdk9可以有私有方法 ),而抽象类可以有非抽象的方法。
- 接口中除了 static、final 变量,不能有其他变量,而抽象类中则不一定。
- 一个类可以实现多个接口,但只能实现一个抽象类。接口自己本身可以通过 extends 关键字扩展多个接口。
- 接口方法默认修饰符是 public,抽象方法可以有 public、protected 和 default 这些修饰符(抽象方法就是为了被重写所以不能使用 private 关键字修饰!)。
- 从设计层面来说,抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象,是一种行为的规范。
注意:
- 接口没有静态代码块和构造方法
- 类与类之间是单继承的,类与接口之间时多实现的,接口与接口之间是多继承的
- 实现多个接口,发生默认方法冲突时,必须要实现该默认方法
- 父类继承的方法与实现的接口的默认方法冲突,子类优先使用父类继承的方法
多态
父类类型作为方法形参,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展性与便利。
多态中的转型
向上转型:子到父(安全)
- 左边可以对象、也可以是接口
- 弊端:不能访问子类特有的方法,需要向下转型
向下转型:父到字(加强制转换)
使用
instanceof
判断对象是由哪个类实例化的1
2
3if (对象 instanceof 类) {
System.out.println("是");
}
重写Override
- 不能被重写的方法
- final方法
- 静态方法
- 子类中不可见方法,如私有方法
- 对象的多态性
- 子类重写了父类的方法,通过子类对象调用的一定子类重写过的方法。
- 非静态方法默认调用对象是this, 而this对象在构造器或者说是
<init>
方法中指的是正在创建的对象。- 如:创建子类对象时,调用父类
<init>
方法,此方法中的this对象就是这个正在的子类对象。
- 如:创建子类对象时,调用父类
类初始化
- 创建实例对象前需要先加载并初始化类
- main方法所在的类需要先加载和初始化
- 初始化字类前需要初始化父类
- 类的初始化就是执行
<clinit>()
方法, 只执行一次<clinit>
方法由静态类变量显示赋值代码和静态代码块组成,先后顺序由类中代码顺序决定。
实例初始化
- 实例初始化就是执行
<init>()
方法- 每次创建实例,都会调用构造器对应的
<init>
方法。 <init>
方法首行是super
方法,即执行父类的<init>
方法。- 然后是实例变量显示赋值代码和非静态块,顺序取决与类中代码的顺序。
- 最后是对应的构造器代码。
- 每次创建实例,都会调用构造器对应的
内部类
将一个类定义在另一个类里面。在描述事物时,若一个事物内部还包含其他事物,就可以使用内部类这种结构。
内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的class文件,文件名外部类$内部类.class
成员内部类
将一个类定义在另一个类里面,方法外。
1 | class 外部类 { |
内部类可以直接访问外部类的成员,包括私有成员。
外部类要访问内部类的成员,必须要建立内部类的对象。
1
外部类名.内部类名 对象名 = new 外部类型().new 内部类型();
- 访问外部类同名变量:
外部类名.this.外部变量名
静态内部类
将一个静态类定义在另一个类里面,方法外。
特点:
- 不会随着外部类加载而加载,要在用到的时候才会单独加载
- 外部类中,可以通过
内部类名.
的方式访问内部类成员,包括私有的
局部内部类
将一个类定义在另一类的方法中。若内部类需要访问方法所在的局部变量,那么这个局部变量必须是常量。因为方法运行结束后,局部变量就会消失,而在方法中new出来的对象不会立刻消亡。
1 | public class Outer { |
匿名内部类
匿名内部类 :是内部类的简化写法。它的本质是一个 带具体实现的 父类或者父接口的匿名的子类对象。
匿名对象只能在创建对象时使用一次,而 匿名内部类不是。
匿名内部类必须继承一个父类或者实现一个父接口
1
2
3
4
5
6
7
8
9父类名或者接口名 obj new 父类名或者接口名() {
// 方法重写
public void method() {}
};
obj.method();
// 匿名对象
new 父类名或者接口名() {...}.method();
包装类
Byte, Short, Integer, Long, Float, Double, Character, Boolean
装箱拆箱
装箱:从基本类型转换为对应的包装类对象。
拆箱:从包装类对象转换为对应的基本类型。
使用包装类中的
valueof
方法1
2Integer a = new Integer(4); // 装箱
Integer b = Integer.valueOf(4); // 拆箱
自动装箱/自动拆箱 (JDK 1.5)
1
2Integer i = 1 // 自动装箱
i = i + 1 // 先拆箱,再装箱
缓存机制
当使用自动装箱的时候,就会触发Java的缓存机制。这个时候java虚拟机会创建一系列的整数并且缓存到一个数组中以便直接使用,这就是缓存策略。
Byte,Short,Long 有固定范围: -128 到 127。
对于 Character, 范围是 0 到 127。
- Long源码
1 | public static Long valueOf(long l) { |
字符串转基本类型
除了Character类之外,其他所有包装类都具有parseXxx静态方法可以将字符串参数转换为对应的基本类型
如果字符串参数的内容无法正确转换为对应的基本类型,则会抛出java.lang.NumberFormatException
异常。
public static byte parseByte(String s)
:string – > bytepublic static short parseShort(String s)
:string –> shortpublic static int parseInt(String s)
:string –> intpublic static long parseLong(String s)
:string –> longpublic static float parseFloat(String s)
:string –> floatpublic static double parseDouble(String s)
:string –> doublepublic static boolean parseBoolean(String s)
:string –> boolean1
2
3String s1 = "123";
byte b = Byte.parseByte(s1);
System.out.println(b); // 123
基础类型转字符串
- 使用’+’: 基础类型 + “”
- 包装类的静态方法tostring
- String类的静态方法valueof(), 传入任意类型
常用类
Scanner 类
一个可以解析基本类型和字符串的简单文本扫描器
1 | Scanner sc = new Scanner(System.in); |
Random 类
此类的实例用于生成伪随机数。
1 | Random rand = new Random(); |
ArrayList 类
ArrayList对象不能存储基本类型,只能存储引用类型的数据
- public boolean add(E e) :将指定的元素添加到此集合的尾部
- public E remove(int index) :移除此集合中指定位置上的元素
- public E get(int index) :返回此集合中指定位置上的元素
- public int size() :返回此集合中的元素数
String 类
String
类代表字符串。字符串是常量,它们的值在创建之后不能更改,底层是一个被final修饰的字节数组。
- public int length () :返回此字符串的长度。
- public String concat (String str) :将指定的字符串连接到该字符串的末尾。
- public char charAt (int index) :返回指定索引处的 char值。
- public int indexOf (String str) :返回指定字符串第一次出现在该字符串内的索引。
- public String substring (int beginIndex) :从beginIndex开始截取字符串到字符串结尾。
- public String substring (int beginIndex, int endIndex) :含beginIndex,不含endIndex。
- public String[] split(String regex) :将此字符串按照给定的规则拆分为字符串数组。
- public boolean endsWith(String suffix): 测试此字符串是否以指定的后缀结束。
- public boolean StartsWith(String prefix): 测试此字符串是否以指定的前缀开始。
- public boolean matches(String regex) : 正则匹配
- replace
- replaceAll
- intern():从常量池中找与这个字符串相等的串,找到则返回,无则在池中新建
Arrays 类
java.util.Arrays 此类包含用来操作数组的各种方法,比如排序和搜索等。其所有方法均为静态方法,
- public static String toString(int[] a) :数组转字符串
- public static void sort(int[] a) :按升序进行排序
- public static
T[] copyOf(T[] original, int newLength):返回一个新数组
Math 类
java.lang.Math 类包含用于执行基本数学运算的方法, 其所有方法均为静态方法
- public static double abs(double a) :返回 double 值的绝对值。
- public static double ceil(double a) :返回大于等于参数的最小的整数。
- public static double floor(double a) :返回小于等于参数最大的整数。
- public static long round(double a) :返回最接近参数的 long。(相当于四舍五入方法)
Object 类
java.lang.Object
类是Java语言中的根类,即所有类的父类。
tostring 方法
public String toString()
:返回该对象的字符串表示。- 默认该字符串内容就是
对象的类型+@+内存地址值
。
- 默认该字符串内容就是
equals 方法
public boolean equals(Object obj)
:比较其他某个对象是否与此对象“相等”。- 不能容忍空指针, 容易抛出空指针异常
- 默认为地址比较
- 如果没有覆盖重写equals方法,那么Object类中默认进行
==
运算符的对象地址比较,只要不是同一个对象,结果必然为false。
- 如果没有覆盖重写equals方法,那么Object类中默认进行
- 对象内容比较
- 如果希望进行对象的内容比较,即所有或指定的部分成员变量相同就判定两个对象相同,则可以覆盖重写equals方法。
hashCode 方法
hashCode方法返回对象的哈希值,是一个十进制整数,由系统随机给出(实际上就是对象的逻辑地址值)。
哈希冲突:两个元素不同,但有相同的哈希值。
Objects 类
java.util.Objects
类, 是JDK7中添加了一个Objects工具类,它提供了一些方法来操作对象,它由一些静态的实用方法组成,这些方法是null-save(空指针安全的)或null-tolerant(容忍空指针的)。
Date 类
java.util.Date
类 表示特定的瞬间,精确到毫秒。
Date对象,以表示自从标准基准时间(称为“历元(epoch)”,即1970年1月1日00:00:00 GMT)以来的指定毫秒数。由于我们处于东八区,所以我们的基准时间为1970年1月1日8时0分0秒。
public Date()
:使用无参构造,可以自动设置当前系统时间的毫秒时刻public Date(long date)
:指定long类型的构造参数,可以自定义毫秒时刻。public long getTime()
把日期对象转换成对应的时间毫秒值。Date类对Object类中的toString方法进行了覆盖重写, 返回一个时间字符串(Thu Jan 01 08:00:00 CST 1970)
DateFormat 类
java.text.DateFormat
是日期/时间格式化子类的抽象类,我们通过这个类可以帮我们完成日期和文本之间的转换,也就是可以在Date对象与String对象之间进行来回转换。常用的子类java.text.SimpleDateFormat
。
public SimpleDateFormat(String pattern)
:用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat对象。参数pattern是一个字符串,代表日期时间的自定义格式。
格式规则: 年月日时分秒 – y M d H m s
1
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public String format(Date date)
:将Date对象格式化为字符串。public Date parse(String source)
:将字符串解析为Date对象。练习:计算一个人已经出生了多少天
1
2
3
4
5
6
7
8
9
10
11
12
13System.out.println("请输入出生日期(yyyy-MM-dd): ");
String birthdayString = new Scanner(System.in).next();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date birthdayDate = df.parse(birthdayString);
Date currentDate = new Date();
long delta = currentDate.getTime() - birthdayDate.getTime();
if (delta < 0) {
System.out.println("尚未出生!");
} else {
System.out.println("已出生" + delta / (1000*60*60*24) + "天");
}
Calendar类
java.util.Calendar
是日历类, 是一个抽象类,在Date后出现,替换掉了许多Date的方法。该类将所有可能用到的时间信息封装为静态成员变量,方便获取。
public static Calendar getInstance()
:使用默认时区和语言环境获得一个日历, 是Calendar子类的一个静态方法1
Calendar cal = Calendar.getInstance();
public int get(int field)
:返回给定日历字段的值。日历字段(field) 含义 YEAR 年 MONTH 月(从0开始,一月为0) DAY_OF_MONTH / DATE 月中的天(几号) HOUR 时(12小时制) HOUR_OF_DAY 时(24小时制) MINUTE 分 SECOND 秒 DAY_OF_WEEK 周中的天(从周日开始,周日为1) public void set(int field, int value)
:将给定的日历字段设置为给定值。public abstract void add(int field, int amount)
:根据日历的规则,为给定的日历字段添加或减去指定的时间量。public Date getTime()
:返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。注意:
- 西方星期的开始为周日,中国为周一。
- Calendar类中,月份的表示是以0-11代表1-12月
- 日期是有大小关系的,时间靠后,时间越大。
System 类
java.lang.System
类中提供了大量的静态方法,可以获取与系统相关的信息或系统级操作。
public static long currentTimeMillis()
:返回以毫秒为单位的当前时间public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
:将数组中指定的数据拷贝到另一个数组中。- src, dest: 源数组, 目标数组
- srcPos, destPos: 源数组,目标数组起始位置索引
- length: 复制元素个数
StringBuilder
java.lang.StringBuilder
又称为可变字符序列,它是一个类似于 String 的字符串缓冲区,通过某些方法调用可以改变该序列的长度和内容。它的内部拥有一个数组用来存放字符串内容,进行字符a串拼接时,直接在数组中加入新内容。(默认16字符空间,超过自动扩充)
stringBuilder单线程使用, stringBuffer多线程使用
public StringBuilder()
:构造一个空的StringBuilder容器。public StringBuilder(String str)
:构造一个StringBuilder容器,并将字符串添加进去。public StringBuilder append(...)
:添加任意类型数据的字符串形式,并返回当前对象自身。public String toString()
:将当前StringBuilder对象转换为String对象。
Collection 集合
java.util.Collection
是单列集合类的根接口,有两个重要的子接口,分别是java.util.List
和java.util.Set
。
List
的特点是元素有序、元素可重复。- 实现类有
java.util.ArrayList
和java.util.LinkedList
,
- 实现类有
Set
的特点是元素无序,而且不可重复。- 主要实现类有
java.util.HashSet
和java.util.TreeSet
。
- 主要实现类有
Collection集合通用操作
public Iterator iterator()
: 获取集合对应的迭代器,用来遍历集合中的元素的。public boolean add(E e)
: 把给定的对象添加到当前集合中 。public void clear()
:清空集合中所有的元素。public boolean remove(E e)
: 把给定的对象在当前集合中删除。public boolean contains(E e)
: 判断当前集合中是否包含给定的对象。public boolean isEmpty()
: 判断当前集合是否为空。public int size()
: 返回集合中元素的个数。public Object[] toArray()
: 把集合中的元素,存储到数组中。
List 集合
java.util.List
接口继承自Collection
接口,是单列集合的一个重要分支。
特点:有序、可重复。
ArrayList 集合
java.util.ArrayList
集合数据存储的结构是数组结构。元素增删慢,查找快。
public void add(int index, E element)
: 将指定的元素,添加到该集合中的指定位置上。public E get(int index)
:返回集合中指定位置的元素。public E remove(int index)
: 移除列表中指定位置的元素, 返回的是被移除的元素。public E set(int index, E element)
:用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
LinkedList 集合
java.util.LinkedList
集合数据存储的结构是链表结构, 是一个双向链表。元素增删快,查找慢。
在开发时,LinkedList
集合也可以作为堆栈,队列的结构使用。
public void addFirst(E e)
:将指定元素插入此列表的开头。public void addLast(E e)
:将指定元素添加到此列表的结尾。public E getFirst()
:返回此列表的第一个元素。public E getLast()
:返回此列表的最后一个元素。public E removeFirst()
:移除并返回此列表的第一个元素。public E removeLast()
:移除并返回此列表的最后一个元素。public E pop()
:从此列表所表示的堆栈处弹出一个元素。public void push(E e)
:将元素推入此列表所表示的堆栈。public boolean isEmpty()
:如果列表不包含元素,则返回true。
Vector 集合
Vector是最早期的集合,是同步的,现在基本不再使用。
Set 集合
java.util.Set
接口和java.util.List
接口一样,同样继承自Collection
接口。
与List
不同的是,Set
元素无序,不能重复。
HashSet 集合
java.util.HashSet
是Set
接口的一个实现类,HashSet
底层的是一个java.util.HashMap
。
HashSet
是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。
如何保证元素唯一的:hashCode
与equals
方法
- 先比较哈希值,相同再使用equals方法比较。
- 所以使用哈希表存储自定义类型时,必须要重写
hashCode
和equals
方法
LinkedHashSet
java.util.LinkedHashSet
也是Set接口的实现类。
与HashSet的不同在于增加了一个链表,用来存储元素存储的顺序。
Iterator迭代器
Iterator
接口也是Java集合中的一员,主要用于迭代访问(即遍历)Collection
中的元素。
迭代:Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,如果还有就再取出出来。一直把集合中的所有元素全部取出。
操作
public boolean hasNext()
:如果仍有元素可以迭代,则返回 true。public E next()
:返回迭代的下一个元素。集合中已经没有元素了,还继续使用迭代器的next方法,将会发生
java.util.NoSuchElementException
1
2
3
4
5
6
7
8
9Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
Iterator iter = coll.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
for-each循环
JDK1.5,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能进行增删操作。
格式
1 | for(元素的数据类型 变量 : Collection集合or数组) {} |
例子
1 | for (String s : coll) { |
Map 集合
java.util.Map
中的集合,元素是成对存在。每个元素由键(key唯一)与值两部分组成,通过键可以找对所对应的值。需要重写键的hashCode()
方法、equals()
方法。
public V put(K key, V value)
: 把指定的键与值添加到Map集合中。- key不重复,返回null;
- key重复更新value,返回原来的value
public V remove(Object key)
: 把指定的键元素删除,返回被删除元素的值。public V get(Object key)
根据指定的键,在Map集合中获取对应的值。boolean containsKey(Object key)
判断集合中是否包含指定的键。public Set<K> keySet()
: 获取Map集合中所有的键,存储到Set集合中。public Set<Map.Entry<K,V>> entrySet()
: 获取到Map集合中所有的键值对对象的集合(Set集合)。Map.Entry
:Map中的一对键和值又称做Map
中的一个Entry(项)
。Entry
将键值对的对应关系封装成了对象。即键值对对象。getKey()
:获取键值对的keygetValue()
:获取键值对的value
HashMap / LinkedHashMap
HashMap<k, v>
和 LinkedHashMap<k, v>
是Map下重要的两个子类。具体实现可类比Set接口的子类HashSet
和LinkedHashSet
。
- 可以存储<null, null>
Hashtable
Hashtable和Vector集合一样,在jdk1.2后被取代了,但其子类Properties集合依然活跃在历史的舞台。Properies是一个唯一与IO流相结合的集合。
- 同步单线程, 底层是一个哈希表
- Hashtable 不能存储<null, null>
遍历Map
集合
键找值的方式:
1 | Map<Integer, String> map = new HashMap<>(); |
键值对方法是:使用Map.Entry
对象遍历
1 | for (Map.Entry<Integer, String> m : map.entrySet()) { |
案例:统计每个字符出现的次数
1 | String s = "aaaBBBBBBBCCcccccddd"; |
泛型
在前面学习集合时,我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对象,并且进行相应的操作,这时必须采用类型转换。
泛型是一种未知类型。在创建对象时确定具体的类型,没有指定泛型时默认为Object类型。
泛型是数据类型的一部分,我们将类名与泛型合并一起看做数据类型。
泛型类
语法:修饰符 class 类名<代表泛型的变量> {}
1 | class ArrayList<E>{ |
泛型方法
语法:修饰符 interface接口名<代表泛型的变量> {}
1 | public class Demo { |
泛型接口
语法:修饰符 <代表泛型的变量> 返回值类型 方法名(参数) {}
1 | public interface MyGenericInterface<E>{ |
泛型通配符
当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。也就是说只能接受数据,不能往该集合中存储数据。
为什么不用<Object>
- 因为泛型不存在继承关系,
Collection<Object> list = new ArrayList<String>()
这种是错误的。
1 | void showList(ArrayList<Object> list) {} // 只能接受List<Object>类型的 |
高级用法 – 受限泛型
- 泛型的上限
- 格式:
类型名称 <? extends T> coll
- 意义:
用于接收T及其子类
, 不能添加数据,用于读取操作。如:coll.get(0)
- 格式:
- 泛型的下限:
- 格式:
类型名称 <? super T> 对象名称
- 意义:
用于取出T及其父类型
,可以添加数据。如:coll.add(new T)
- 格式:
Collections 工具类
java.utils.Collections
是集合工具类,用来对集合进行操作。
常用方法
public static <T> boolean addAll(Collection<T> c, T... elements)
:往集合中添加一些元素。public static void shuffle(List<?> list) 打乱顺序
:打乱集合顺序。public static <T> void sort(List<T> list)
:将集合中元素按照默认规则排序(升)- 不可直接进行比较的类型,需要实现
comparable
接口,重写compareTo
方法
- 不可直接进行比较的类型,需要实现
public static <T> void sort(List<T> list,Comparator<? super T> )
:将集合中元素按照指定规则排序。需要实现
java.util.Comparator
接口(比较器), 重写比较方法1
int compare(T o1, T o2) {}
然后再将new出来的比较器对象传给sort方法
Comparable和Comparator的区别
- Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序。
- Comparator:强行对某个对象进行整体排序。可以将Comparator 传递给sort方法,从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。
jdk9 新特性
Java 9,添加了几种集合工厂方法,更方便创建少量元素的集合、map实例。新的List、Set、Map的静态工厂方法可以更方便地创建集合的不可变实例。
注意
- of()方法只是Map,List,Set这三个接口的静态方法,其父类接口和子类实现并没有这类方法,比如 HashSet,ArrayList等
- Set, Map接口在调用of方法时,不能由重复元素
- 修改of()方法返回的集合,会报
java.lang.UnsupportedOperationException
异常
例子
1 | List<Integer> list = List.of(1, 2, 3, 4, 5); // 返回的list是不可变的 |