文章链接至:sycblog.fun

目录

封装(Encapsulation)

继承(Extend)

多态(Polymorphism)

类变量和类方法(Static)

代码块 (Codeblock)

final 关键字

抽象类 (Abstract)

接口 (Interface)

内部类 (InnerClass)

枚举(Enumoration)

异常(Exception)

常用类

包装类 (Wrapper)

String 类

StringBuffer 类

Stringbuilder 类

Math 类

Arrays 类

System 类

BigInteger 和 BigDecimal 类

日期类(Date)

集合

Collection 接口和常用方法

List 接口和常用方法

Set 接口和常用方法

Map 接口和常用方法

总结 开发中如何选择集合实现类

Collections 工具类

泛型


封装(Encapsulation

基本介绍

面向对象编程有三大特征:封装、继承和多态

封装介绍

封装(encapsulation)就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法],才能对数据进行操作

封装的理解和好处

  1. 隐藏实现细节:方法(连接数据库)<-- 调用(传入参数..)

  2. 可以对数据进行验证,保证安全合理

封装的实现步骤 (三步)

  1. 将属性进行私有化 private [不能直接修改属性]

  2. 提供一个公共的(public)set方法,用于对属性判断并赋值

public void setXxx(类型 参数名){    //Xxx 表示某个属性//加入数据验证的业务逻辑属性 = 参数名;
}
  1. 提供一个公共的(public)get方法,用于获取属性的值

public 数据类型 getXxx(){    //权限判断,Xxx 某个属性return xx;
}

继承(Extend

继承给编程带来的便利

1) 代码的复用性提高了

2) 代码的扩展性和维护性提高了

继承的深入讨论/细节问题@@@

1) 子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问

2) 子类必须调用父类的构造器, 完成父类的初始化

3) 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过

4) 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)

5) super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)

6) super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

7) java 所有类都是 Object 类的子类, Object 是所有类的基类

8) 父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)

9) 子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制。

思考:如何让 A 类继承 B 类和 C 类? 【A 继承 B,B 继承 C】

10) 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系

super 关键字

基本介绍

super 代表父类的引用,用于访问父类的属性、方法、构造器

基本语法

1.访问父类的属性,访问父类的 private 属性

super.属性名;

2.访问父类的方法,不能访问父类的 private 方法

super.方法名(参数列表);

3.访问父类的构造器

super(参数列表); //只能放在构造器的第一句,且只能出现一句

super 给编程带来的便利/细节@@@

1.调用父类构造器的好处

分工明确,父类属性由父类初始化,子类属性由子类初始化

2.当子类中有和父类中的成员(属性和方法)重名时,为了访问父类中的成员,必须通过 super。如果没有重名,使用 super、this、或直接访问是一样的效果

3.super 的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用 super 去访问爷爷类的成员;如果多个上级类(基类)中都有同名的成员,使用 super 去访问遵循就近原则。A->B->C,当然也需要遵守访问权限的相关规则

super 和 this 的比较

No.

区别点

this

super

1

访问属性

访问本类中的属性,如果本类中没有此属性则从父类中继续查找

直接从父类开始查找属性

2

调用方法

访问本类中的方法,如果本类没有次方法则从父类继续查找

直接从父类开始查找方法

3

调用构造器

调用本类构造器,必须放在构造器的首行

调用父类构造器,必须放在构造器首行

3

特殊

表述当前对象

子类中访问父类对象

方法重写/覆盖(override)

基本介绍

方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称,返回类型,参数一样,那么我们就说子类的这个方法覆盖了父类的方法

重写注意事项和使用细节 @@@

方法重写也叫方法覆盖,需要满足下面的条件

1.子类的方法的形参列表,方法名称,要和父类的方法的形参列表,方法名称完全一样

2.子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类。比如 父类 返回类型是 Object,子类方法返回类型是 String。

3.子类方法不能缩小父类方法的访问权限。

public > protected > 默认 > private

方法重写和重载的区别

名称

发生范围

方法名

形参列表

返回类型

修饰符

重载(overload)

本类

必须一样

类型,个数或者顺序至少有一个不同

无要求

无要求

重写(override)

父子类

必须一样

相同

子类重写的方法返回类型和父类返回类型一致,或者是其子类

子类方法不能缩小父类方法的访问范围

多态(Polymorphism

面向对象编程-多态

多[多种]态[状态]基本介绍

方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。

多态的具体体现

1) 方法的多态

重写和重载就体现多态

2) 对象的多态 (核心,困难,重点)

(1)一个对象的编译类型和运行类型可以不一致

(2)对象的编译类型在定义对象时,就确定了,不能改变

(3)对象的运行类型是可以变化的

(4)编译类型看定义时 = 号的左边,运行类型看 = 号的右边

多态注意事项和细节讨论

多态的前提是:

两个对象(类)存在继承关系

多态的向上转型

(1)本质:父类的引用指向了子类的对象

(2)语法:父类类型 引用名 = new 子类类型();

(3)特点:编译类型看左边,运行类型看右边

可以调用父类中的所有成员(需遵守访问权限),不能调用子类中特有成员;最终运行效果看子类的具体实现

多态的向下转型

(1)语法:子类类型 引用名 = (子类类型) 父类引用;

(2)只能强转父类的引用,不能强转父类的对象

(3)要求父类的引用必须指向的是当前目标类型的对象

(4)当向下转型后,可以调用子类类型中所有的成员

属性没有重写之说!属性的值看编译类型

instanceOf 比较操作符,用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型

java 的动态绑定机制(非常非常重要.) @@@

Java 重要特性: 动态绑定机制

1.当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定

2.当调用对象属性时,没有动态绑定机制,哪里声明哪里使用

多态的应用

1) 多态数组

数组的定义类型为父类类型,里面保存的实际元素类型为子类类型

1) 多态参数

方法定义的形参类型为父类类型,实参类型允许为子类类型

equals 方法 ==和equals的对比

1) == 是一个比较运算符

  1. 既可以判断基本类型,又可以判断引用类型

  2. 如果判断基本类型,判断的是值是否相等

  3. 如果判断引用类型,判断的是地址是否相等,即判定是不是同一个对象

2) equals 是Object类中的方法

  1. 只能判断引用类型

  2. 默认判断的是地址是否相等,子类中往往重写该方法,用于判断是否相等

类变量和类方法(Static

什么是类变量

类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象修改它时,修改的也是同一个变量

定义类变量语法

访问修饰符 static 数据类型 变量名; //推荐

static 访问修饰符 数据类型 变量名;

访问类变量语法

类名.类变量名 //推荐

对象名.类变量名

【静态变量的访问修饰符的访问权限与范围 和 普通属性是一样的】

类变量使用注意事项和细节讨论@@@

  1. 什么时候需要类变量

当我们需要让某个类的所有对象共享一个变量时,就可以考虑使用类变量(静态变量)

  1. 类变量与实例变量(普通变量)区别

类变量是该类的所有对象共享的,而实例变量是每个对象独享的

  1. 加上 static 称为类变量或静态变量,否则称为实例变量/普通变量/非静态变量

  2. 类变量可以通过 类名.类变量名 或者 对象名.类变量名 来访问

  3. 实例变量不能通过 类名.类变量名 方式访问

  4. 类变量是在类加载时就初始化了,也就是说,即使你没有创建对象,只要类加载了,就可以使用类变量了

  5. 类变量的生命周期是随类的加载开始,随着类消亡而销毁

类方法基本介绍

类方法也叫静态方法

形式如下:

访问修饰符 static 数据返回类型 方法名(){ } //推荐

static 访问修饰符 数据返回类型 方法名(){ }

类方法的调用

使用方式:

类名.类方法名

对象名.类方法名

类方法使用注意事项和细节讨论@@@

  1. 类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区:类方法中无 this 参数普通方法中隐含着 this 参数

  2. 类方法可以通过类名调用,也可以通过对象名调用

  3. 普通方法和对象有关,需要通过 对象名.方法名(参数) ,不能通过类名调用

  4. 类方法中不允许使用和对象有关的关键字,比如 this 和 super 。普通方法(成员方法)可以

  5. 类方法(静态方法)中只能访问 静态变量或静态方法

  6. 普通成员方法,既可以访问 非静态成员,也可以访问静态成员

小结:静态方法只能访问静态的成员,非静态的方法可以访问(所有成员)静态成员和非静态成员(必须遵守访问权限)

代码块 (Codeblock)

基本介绍

代码块又称为初始化块,属于类中的成员[即是类的一部分],类似与方法,将逻辑语句封装在方法体中,通过{}包围起来

但和方法不同,没有方法名,没有返回值,没有参数,只有方法体,而且不用通过对象或类显示调用,而是加载类时,或创建对象时隐式调用

基本语法

修饰符{

代码

};

说明注意:

  1. 修饰符 可选,要写的话,也只能写 static

  2. 代码块分为两类,使用 static 修饰的叫静态代码块,没有 static 修饰的,叫普通代码块/非静态代码块

  3. 逻辑语句可以为任何逻辑语句(输入,输出,方法调用,循环,判断等)

  4. ; 号可以写,也可以省略

代码块的好处

  1. 相当于另外一种形式的构造器(对构造器的补充机制),可以作初始化的操作

  2. 场景:如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性

代码块使用注意事项和细节讨论@@@

  1. static 代码块也叫静态代码块,作用就是对类进行初始化。而且它随着类的加载而执行,并且只会执行一次。如果是普通代码块,每创建一个对象,就执行一次

  2. 类什么时候被加载

①创建对象实例时(new)

②创建子类对象实例,父类也会被加载

③使用类的静态成员时(静态属性,静态方法)

  1. 普通代码块,在创建对象实例时,就会被隐式调用

被创建一次就会调用一次

如果只是使用类的静态成员时,普通代码块并不会执行

小结:@@@

  1. static 代码块是类加载时执行,只会执行一次

  2. 普通代码块是在创建对象时调用的,创建一次,调用一次

  3. 类加载的三种情况,需要记住

①创建对象实例时(new) ②创建子类对象实例,父类也会被加载 ③使用类的静态成员时(静态属性,静态方法)

  1. 创建一个对象时,在一个类调用顺序是:

调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用)

调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按定义顺序调用)

调用构造方法

  1. 构造器的最前面其实隐含了 super() 和 调用普通代码块;静态相关的代码块,属性初始化,在类加载时,就执行完毕,因此是优先于构造器和普通代码块执行的

  2. 当创建一个子类对象时(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:

①父类的静态代码块和静态属性

②子类的静态代码块和静态属性

③父类的普通代码块和普通属性初始化

④父类的构造方法

⑤子类的普通代码块和普通属性初始化

⑥子类的构造方法

(优先级一样,按定义顺序执行)

  1. 静态代码块只能直接调用静态成员(静态属性和方法),普通代码块可以调用任意成员

final 关键字

基本介绍

final 可以修饰类,属性,方法和局部变量

在某些情况下,程序员可能有以下需求,就会使用到 final :

  1. 当不希望类被继承时

  2. 当不希望父类的某个方法被子类覆盖/重写时

  3. 当不希望类的某个属性值被修改时

  4. 当不希望某个局部变量被修改

final 使用注意事项和细节讨论@@@

  1. final 修饰的属性又叫常量,一般用 XX_XX_XX 来命名

  2. final修饰的属性在定义时,必须赋初值,并且以后不能再修改,赋值可以在如下位置之一【选择一个位置赋初值即可】:

①定义时

②在构造器中

③在代码块中

  1. 如果 final 修饰的属性是静态的,则初始化的位置只能是

①定义时

②在静态代码块中

不能在构造器中赋值

  1. final 类不能继承,但是可以实例化对象

  2. 如果类不是 final 类,但是含有 final 方法,则该方法虽然不能被重写,但是可以被继承

  3. 一般来说,如果一个类已经是 final 类了,就没有必要再将方法修饰成 final 方法

  4. final 不能修饰构造方法(即构造器)

  5. final 和 static 往往搭配使用,效率更高,不会导致类加载。底层编译做了优化处理

  6. 包装类(Integer,Double,Float,Boolean,String 等都是 final 类

抽象类 (Abstract)

抽象类的介绍

  1. 用 abstract 关键字来修饰一个类时,这个类就叫抽象类

访问修饰符 abstract 类名 {// 成员;
}
  1. 用 abstract 关键字来修饰一个方法时,这个方法就是抽象方法

访问修饰符 abstract 返回类型 方法名 (参数列表) ;
// 没有方法体
  1. 抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类

10.6.4 抽象类使用的注意事项和细节讨论@@@

  1. 抽象类不能被实例化

  2. 抽象类不一定要包含抽象方法。也就是说,抽象类可以没有 abstract 方法

  3. 一旦类包含了 abstract 方法,则这个类必须声明为 abstract

  4. abstract 只能修饰类和方法,不能修饰属性和其他的

  5. 抽象类可以有任意成员【抽象类本质还是类】

  6. 抽象方法不能有主体,即不能实现

  7. 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为 abstract 类

  8. 抽象方法不能使用 private,final,static 来修饰,因为这些关键字都是和重写相违背的

接口 (Interface)

基本介绍

接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体情况把这些方法写出来。语法:

interface 接口名 {// 属性;// 抽象方法;
}
class 类名 implements 接口 {// 自己的属性;// 自己的方法;// 必须实现接口的所有抽象方法;
}

注意事项和细节@@@

  1. 接口不能被实例化

  2. 接口中所有的方法是 public 方法,接口中抽象方法,可以不用 abstract 修饰

  3. 一个普通类实现接口,就必须将该接口所有方法都实现

  4. 抽象类实现接口,可以不用实现接口的方法

  5. 一个类同时可以实现多个接口

  6. 接口中的属性,只能是 final 的,而且是 public static final 修饰符 比如:int a=1; //实际上是 public static final int a=1;(必须初始化)

  7. 接口中属性的访问形式:接口名.属性名

  8. 接口不能继承其他的类,但是可以继承多个别的接口

  9. 接口的修饰符只能是 public 和默认,这点和类的修饰符是一样的

实现接口 vs 继承类

当子类继承了父类,就自动的拥有父类的功能。如果子类需要扩展功能,可以通过实现接口的方式扩展,可以理解为 实现接口

1.接口和继承解决的问题不同

继承的价值主要在于:解决代码的复用性和可维护性

接口的价值主要在于:设计,设计好各种规范(方法),让其他类去实现这些方法。即更加的灵活

2.接口比继承更加灵活

继承是满足 is-a 的关系,而接口只需要满足 like-a 的关系

3.接口在一定程度上实现代码解耦【即:接口规范性+动态绑定机制】

接口与抽象类的默认访问权限

关于抽象类

JDK 1.8时,抽象类的方法默认访问权限变为 default(JDK 1.8以前,抽象类的方法默认访问权限为 protected)

关于接口

JDK 1.9时,接口中的方法可以是 public , default 也可以是 private (JDK 1.8以前,接口中的方法必须是 public 的 JDK 1.8时,接口中的方法可以是 public,也可以是 default)

内部类 (InnerClass)

基本语法

public class InnerClass01 {     //外部其他类 public static void main(String[] args) {} }
class Outer {     //外部类 private int n1 = 100;    //属性public Outer(int n1) {    //构造器 this.n1 = n1; } public void m1() {    //方法 System.out.println("m1()"); }{//代码块 System.out.println("代码块..."); } class Inner {     //内部类, 在 Outer 类的内部 }
}

内部类的分类

定义在外部类的局部位置上(比如方法内):

  1. 局部内部类(有类名)

  2. 匿名内部类(没有类名)

定义在外部类的成员位置上:

  1. 成员内部类(没有 static 修饰)

  2. 静态内部类(使用 static 修饰)

局部内部类的使用

说明:局部内部类是定义在外部类的局部位置,比如方法中,并且有类名

  1. 可以直接访问外部类的所有成员,包含私有成员

  2. 不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用 final 修饰,因为局部变量也可以使用 final

  3. 作用域:仅仅在定义它的方法或代码块中

  4. 局部内部类访问外部类的成员 访问方式:直接访问

  5. 外部类访问局部内部类的成员 访问方式:创建对象,再访问

(注意:必须在作用域内)

小结:(1)局部内部类定义在方法中/代码块中

(2)作用域在方法体或者代码块中

(3)本质仍然是一个类

  1. 外部其他类不能访问局部内部类(因为局部内部类地位是一个局部变量)

  2. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类.this.成员)去访问

匿名内部类的使用(重要!!!!!!!)@@@

  1. 本质是类(2)内部类(3)该类没有名字(4)同时还是一个对象

说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名

匿名内部类的基本语法

new 类或接口 (参数列表) {类体;
}
  1. 匿名内部类的语法比较奇特,因为匿名内部类既是一个类的定义,同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征,因此可以调用匿名内部类方法

  2. 可以直接访问外部类的所有成员,包含私有成员

  3. 不能添加访问修饰符,因为它的地位就是一个局部变量

  4. 作用域:仅仅在定义它的方法中或代码块中

  5. 匿名内部类访问外部类成员 访问方式:直接访问

  6. 外部其他类不能访问匿名内部类(因为匿名内部类地位是一个局部变量)

  7. 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问

成员内部类的使用

说明:成员内部类是定义在外部类的成员位置,并且没有 static 修饰

  1. 可以直接访问外部类的所有成员,包含私有成员

  2. 可以添加任意访问修饰符(public,protected,默认,private),因为它的地位就是一个成员

  3. 作用域:和外部类的其他成员一样,为整个类体(在外部类的成员方法中创建成员内部类对象,再调用方法)

  4. 成员内部类 访问 外部类成员(比如:属性)访问方式:直接访问

  5. 外部类 访问 成员内部类 访问方式:创建对象,再访问

  6. 外部其他类 访问 成员内部类

方式 1 : outer08.new Inner08(); 相当于把 new Inner08()当做是outer08 成员 这就是一个语法,不要特别的纠结

方式 2 :在外部类中,编写一个方法,可以返回对象

  1. 如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问

静态内部类的使用

说明:静态内部类是定义在外部类的成员位置,并且有 static 修饰

  1. 可以直接访问外部类的所有静态成员,包含私有成员,但不能直接访问非静态成员

  2. 可以添加任意访问修饰符(public,protected,默认,private),因为它的地位就是一个成员

  3. 作用域:同其他的成员,为整个类体

  4. 静态内部类 访问 外部类(比如:静态属性)访问方式:直接访问所有静态成员

  5. 外部类 访问 静态内部类 访问方式:创建对象,在访问

  6. 外部其他类 访问 静态内部类

方式 1 :因为静态内部类,是可以通过类名直接访问(前提是满足访问权限)

方式 2 :编写一个方法,可以返回静态内部类的对象实例

  1. 如果外部类和静态内部类的成员重名时,静态内部类访问时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员)去访问

枚举(Enumoration

枚举的二种实现方式

  1. 自定义类实现枚举

  2. 使用 enum 关键字实现枚举

自定义类实现枚举

  1. 将构造器私有化,目的防止 直接 new

  2. 去掉 setXxx 方法, 防止属性被修改,可以提供 get 方法

  3. 在本类内部,直接创建固定的对象

  4. 对外暴露对象(通过为对象添加 public final static 修饰符)

enum 关键字实现枚举

enum 关键字实现枚举注意事项

  1. 当我们使用 enum 关键字开发一个枚举类时,默认会继承 Enum 类, 而且是一个 final 类

  2. 传统的 public static final Season2 SPRING = new Season2("春天", "温暖"); 简化成 SPRING("春天", "温暖"), 这里必须知道,它调用的是哪个构造器

  3. 如果使用无参构造器 创建 枚举对象,则实参列表和小括号都可以省略

  4. 当有多个枚举对象时,使用逗号“ , ”间隔,最后有一个分号“ ; ”结尾

  5. 枚举对象必须放在枚举类的行首

enum 常用方法

  1. toString:Enum 类已经重写过了,返回的是当前对象名,子类可以重写该方法,用于返回对象的属性信息

  2. name:返回当前对象名(常量名),子类中不能重写

  3. ordinal:返回当前对象的位置号,默认从 0 开始

  4. values:返回当前枚举类中所有的常量

  5. valueOf:将字符串转换成枚举对象,要求字符串必须 为已有的常量名,否则报异常!

  6. compareTo:比较两个枚举常量,比较的就是编号!

enum 实现接口

  1. 使用 enum 关键字后,就不能再继承其它类了,因为 enum 会隐式继承 Enum,而 Java 是单继承机制

  2. 枚举类和普通类一样,可以实现接口,如下形式:

enum 类名 implements 接口 1,接口 2 { };

异常(Exception

异常体系图

执行过程中所发生的异常事件可分为两大类:

  1. Error(错误):Java虚拟机无法解决的严重问题。如:JVM系统内部错误,资源耗尽等严重情况。比如:StackOverflowError(栈溢出)和OutOfMemoryError(内存溢出) 是严重错误,程序会崩溃

  2. Exception:其他因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。Exception 分为两大类:运行时异常(程序运行时,发生的异常)和编译时异常(编程时,编译器检查出的异常)

常见的运行时异常 (RuntimeException)

  1. NullPointerException 空指针异常

当应用程序试图在需要对象的地方使用 null 时,抛出该异常

  1. ArithmeticException 数学运算异常

当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此类的一个实例

  1. ArrayIndexOutOfBoundsException 数组下标越界异常

用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引

  1. ClassCastException 类型转换异常

当试图将对象强制转换为不是实例的子类时,抛出该异常

  1. NumberFormatException 数字格式不正确异常

当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常(使用异常我们可以确保输入是满足条件数字)

常见的编译异常

  1. SQLException 操作数据库时,查询表可能发生异常

  2. IOException 操作文件时,发生的异常

  3. FileNotFoundException 当操作一个不存在的文件时,发生异常

  4. ClassNotFoundException 加载类,而该类不存在是,发生异常

  5. EOFException 操作文件,到文件末尾,发生异常

  6. IllegalArguementException 参数异常

异常处理的方式

  1. try-catch-finally 程序员在代码中捕获发生的异常,自行处理

  2. throws 将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM

try-catch 方式处理异常(快捷键 ctrl + alt + t)

try {// 可疑代码;// 将异常生成对应的异常对象,传递给 catch 块;
} catch (异常) {//    对异常的处理;
} finally {//释放资源等;
}

try-catch 方式处理异常-注意事项

  1. 如果异常发生了,则异常发生后面的代码不会执行,直接进入到 catch 块

  2. 如果异常没有发生,则顺序执行 try 的代码块,不会进入到 catch

  3. 如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用如下代码- finally

  4. 如果 try 代码块有可能有多个异常,可以使用多个 catch 分别捕获不同的异常,相应处理。要求子类异常写在前面,父类异常写在后面

  5. 可以进行 try-finally 配合使用, 这种用法相当于没有捕获异常, 因此程序会直接崩掉/退出。应用场景,就是执行一段代码,不管是否发生异常, 都必须执行某个业务逻辑

throws 异常处理

基本介绍

在方法声明中用 throws 语句可以声明抛出异常的列表, throws 后面的异常类型可以是方法中产生的异常类型,也可以是它的父类

基本语法

访问修饰符 方法名 () throws 异常类型 {
}

注意事项和使用细节

  1. 对于编译异常,程序中必须处理,比如 try-catch 或者 throws

  2. 对于运行时异常,程序中如果没有处理,默认就是 throws 的方式处理

  3. 子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常类型的子类型

  4. 在 throws 过程中,如果有方法 try-catch , 就相当于处理异常,就可以不必 throws

自定义异常

基本概念

当程序中出现了某些“错误”,但该错误信息并没有在 Throwable 子类中描述处理,这个时候可以自己设计异常类,用于描述该错误信息

自定义异常的步骤

  1. 定义类:自定义一个异常类名继承 Exception 或 RuntimeException

  2. 如果继承Exception,属于编译异常

  3. 如果继承 RuntimeException,属于运行异常(一般继承 RuntimeException)

自定义异常基本语法

public class 类名 {public static void main(String[] args){//设置抛出异常机制throw new 自己定义的异常名;}
}
class 自己定义的异常名 extends RuntimeException {public 自己定义的异常名 (String message) {//构造器 super(message); }
}

throw 和 throws的区别

意义

位置

后面跟的东西

throws

处理异常的一种方式

方法声明处

异常类型

throw

手动生成异常对象的关键字

方法体中

异常对象

常用类

包装类 (Wrapper)

包装类的分类

  1. 针对八种基本数据类型相应的引用类型—包装类

  2. 有了类的特点,就可以调用类中的方法。

基本数据类型

包装类

boolean

Boolean

char

Char

byte

Byte

父类 Number

short

Short

int

Int

long

Long

float

Float

double

Double

包装类和基本数据的转换

  1. jdk5 以前是手动装箱和拆箱方式

  2. jdk5 以后(含jdk5)是自动装箱和拆箱方式

  3. 自动装箱底层调用的是 valueOf 方法,比如 IntegerOf()

  4. 其它包装类的用法类似,不一一举例

这里以 int 和 Integer 演示

public class Integer01 {public static void main(String[] args) {//演示 int <--> Integer 的装箱和拆箱//jdk5 前是手动装箱和拆箱//手动装箱 int->Integerint n1 = 100;Integer integer = new Integer(n1);Integer integer1 = Integer.valueOf(n1);//手动拆箱 Integer -> intint i = integer.intValue();//jdk5 后,就可以自动装箱和自动拆箱int n2 = 200;//自动装箱 int->IntegerInteger integer2 = n2; //底层使用的是 Integer.valueOf(n2)//自动拆箱 Integer->intint n3 = integer2; //底层仍然使用的是 intValue()方法}
}

包装类型和 String 类型的相互转换

这里以 Integer 和 String 演示,其它类似

public class WrapperVSString {public static void main(String[] args) {//包装类(Integer)->StringInteger i = 100;//自动装箱//方式 1String str1 = i + "";//方式 2String str2 = i.toString();//方式 3String str3 = String.valueOf(i);//String -> 包装类(Integer)String str4 = "12345";//方式 1 使用到自动装箱Integer i2 = Integer.parseInt(str4);//方式 2 使用构造器Integer i3 = new Integer(str4);}
}

Integer 类和 Character 类的常用方法

public class WrapperMethod {public static void main(String[] args) {System.out.println(Integer.MIN_VALUE); //返回最小值System.out.println(Integer.MAX_VALUE);//返回最大值System.out.println(Character.isDigit('a'));//判断是不是数字System.out.println(Character.isLetter('a'));//判断是不是字母System.out.println(Character.isUpperCase('a'));//判断是不是大写System.out.println(Character.isLowerCase('a'));//判断是不是小写System.out.println(Character.isWhitespace('a'));//判断是不是空格System.out.println(Character.toUpperCase('a'));//转成大写System.out.println(Character.toLowerCase('A'));//转成小写}
}

String 类

String 类的理解和创建对象

  1. String 对象用语保存字符串,也就是一组字符序列

  2. 字符串常量对象是双引号括起的字符序列。例如:"你好","123","boy" 等

  3. 字符串的字符使用 Unicode 字符编码,一个字符(不区分字母还是汉字)占两个字节

代码示例

public class String01 {public static void main(String[] args) {//1.String 对象用于保存字符串,也就是一组字符序列//2. "jack" 字符串常量, 双引号括起的字符序列//3. 字符串的字符使用 Unicode 字符编码,一个字符(不区分字母还是汉字)占两个字节//4. String 类有很多构造器,构造器的重载// 常用的有 String s1 = new String(); ////String s2 = new String(String original);//String s3 = new String(char[] a);//String s4 = new String(char[] a,int startIndex,int count)//String s5 = new String(byte[] b)//5. String 类实现了接口 Serializable【String 可以串行化:可以在网络传输】// 接口 Comparable [String 对象可以比较大小]//6. String 是 final 类,不能被其他的类继承//7. String 有属性 private final char value[]; 用于存放字符串内容//8. 一定要注意:value 是一个 final 类型, 不可以修改(需要功力):即 value 不能指向// 新的地址,但是单个字符内容是可以变化String name = "jack";name = "tom";final char[] value = {'a','b','c'};char[] v2 = {'t','o','m'};value[0] = 'H';//value = v2; 不可以修改 value 地址}
}

创建 String 对象的两种方式与区别

方式一:直接赋值 String s1 = "hsp";

先从常量池查看是否有 "hsp" 数据空间,如果有,直接指向;如果没有则重新创建,然后指向。s1 最终指向的是常量池的空间地址

方式二:调用构造器 String s2 = new String("hsp");

先在堆中创建空间,里面维护了 value 属性,指向常量池的 hsp 空间。如果常量池没有 "hsp" ,重新创建,如果有,直接通过 value 指向。最终指向的是堆中的空间地址

字符串的特性

  1. String 是一个 final 类,代表不可变的字符序列

  2. 字符串是不可变的。一个字符串对象一旦被分配,期内容是不可变的

String 类的常见方法

  1. equals 比较内容是否相同,区分大小写

  2. equalsIgnoreCase 忽略大小写的判断内容是否相等

  3. length 获取字符的个数,字符串的长度

  4. indexOf 获取字符在字符串对象中第一次出现的索引,索引从 0 开始,如果找不到,返回 -1

  5. lastIndexOf 获取字符在字符串中最后一次出现的索引,索引从 0 开始,如果找不到,返回 -1

  6. substring 截取指定范围的子串

  7. toUpperCase 转换成大写

  8. toLowerCase 转换成小写

  9. concat 拼接字符串

  10. replace 替换字符串中的字符

  11. split 分割字符串

  12. toCharArray 转换成字符数组

  13. compareTo 比较两个字符串的大小,如果前者大,则返回正数,后者大,则返回负数,如果相等,返回 0

  14. format 格式字符串(%s , %d , %.2f,%c 称为占位符)

  1. 这些占位符由后面变量来替换

  2. %s 表示后面由 字符串来替换

  3. %d 是整数来替换

  4. %.2f 表示使用小数来替换,替换后,只会保留小数点两位, 并且进行四舍五入的处理

  5. %c 使用 char 类型来替换

StringBuffer 类

基本介绍

  1. java.lang.StringBuffer 代表可变字符序列,可以对字符串内容进行增删

  2. 很多方法与 String 相同,但 StringBuffer 是可变长度的

  3. StringBuffer 是一个容器

String VS StringBuffer

  1. String 保存的是字符串常量,里面的值不能更改,每次 String 类的更新实际上就是更改地址,效率较低

  2. StringBuffer 保存的是字符串变量,里面的值可以更改,每次 StringBuffer 的更新实际上可以更新内容,不用每次更新地址,效率较高

String 和 StringBuffer 相互转换

代码示例

public class StringAndStringBuffer {public static void main(String[] args) {//看 String --> StringBufferString str = "hello tom";//方式 1 使用构造器//注意: 返回的才是 StringBuffer 对象,对 str 本身没有影响StringBuffer stringBuffer = new StringBuffer(str);//方式 2 使用的是 append 方法StringBuffer stringBuffer1 = new StringBuffer();stringBuffer1 = stringBuffer1.append(str);//看看 StringBuffer ->StringStringBuffer stringBuffer3 = new StringBuffer("韩顺平教育");//方式 1 使用 StringBuffer 提供的 toString 方法String s = stringBuffer3.toString();//方式 2: 使用构造器来搞定String s1 = new String(stringBuffer3);}
}

StringBuffer 类常见方法

代码示例

public class StringBufferMethod {public static void main(String[] args) {StringBuffer s = new StringBuffer("hello");//增s.append(',');// "hello,"s.append("张三丰");//"hello,张三丰"s.append("赵敏").append(100).append(true).append(10.5);System.out.println(s);//"hello,张三丰赵敏 100true10.5"//删/** 删除索引为 >=start && <end 处的字符* 解读: 删除 11~14 的字符 [11, 14)*/s.delete(11, 14);System.out.println(s);//"hello,张三丰赵敏 true10.5"//改//老韩解读,使用 周芷若 替换 索引 9-11 的字符 [9,11)s.replace(9, 11, "周芷若");System.out.println(s);//"hello,张三丰周芷若 true10.5"//查找指定的子串在字符串第一次出现的索引,如果找不到返回-1int indexOf = s.indexOf("张三丰");System.out.println(indexOf);//6//插//老韩解读,在索引为 9 的位置插入 "赵敏",原来索引为 9 的内容自动后移s.insert(9, "赵敏");System.out.println(s);//"hello,张三丰赵敏周芷若 true10.5"//长度System.out.println(s.length());//22}
}

Stringbuilder 类

基本介绍

  1. 一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API ,但不保证同步(StringBuilder 不是线程安全)。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区单个线程使用的时候。如果可以,建议有限采用该类,因为在大多数实现中,它比 StringBuffer 要快

  2. 在StringBuilder 上的主要操作是 append 和 insert 方法,可以重载这些方法,以接收任意类型的数据

StringBuilder 常用方法

StringBuilder 和 StringBuffer 均代表可变的字符,方法是一样的,所以使用和 StringBuffer 一样

String、StringBuffer 和 StringBuilder 的比较

  1. StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且方法也是一样

  2. String :不可变字符序列,效率低,但是复用率高(如果要对 String 做大量修改,不要使用 String)

  3. StringBuffer :可变字符序列,效率较高(增删),线程安全

  4. SringBuilder :可变字符序列,效率最高,线程不安全

String、StringBuffer 和 StringBuilder 的选择

  1. 如果字符串存在大量的修改操作,一般使用 StringBuffer 或 Stringbuilder

  2. 如果字符串存在大量的修改操作,并在单线程的情况,使用 StringBuiler

  3. 如果字符串存在大量的修改操作,并在多线程的情况,使用 StringBuffer

  4. 如果对字符串很少修改,被多个对象引用,使用 String

Math 类

基本介绍

Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数

常见方法示例(均为静态方法)

public class MathMethod {public static void main(String[] args) {//看看 Math 常用的方法(静态方法)//1.abs 绝对值int abs = Math.abs(-9);System.out.println(abs);//9//2.pow 求幂double pow = Math.pow(2, 4);//2 的 4 次方System.out.println(pow);//16//3.ceil 向上取整,返回>=该参数的最小整数(转成 double);double ceil = Math.ceil(3.9);System.out.println(ceil);//4.0//4.floor 向下取整,返回<=该参数的最大整数(转成 double)double floor = Math.floor(4.001);System.out.println(floor);//4.0//5.round 四舍五入 Math.floor(该参数+0.5)long round = Math.round(5.51);System.out.println(round);//6//6.sqrt 求开方double sqrt = Math.sqrt(9.0);System.out.println(sqrt);//3.0//7.random 求随机数// random 返回的是 0 <= x < 1 之间的一个随机小数// 思考:请写出获取 a-b 之间的一个随机整数,a,b 均为整数 ,比如 a = 2, b=7// 即返回一个数 x 2 <= x <= 7// 老韩解读 Math.random() * (b-a) 返回的就是 0 <= 数 <= b-a// (1) (int)(a) <= x <= (int)(a + Math.random() * (b-a +1) )// (2) 使用具体的数给小伙伴介绍 a = 2 b = 7// (int)(a + Math.random() * (b-a +1) ) = (int)( 2 + Math.random()*6)// Math.random()*6 返回的是 0 <= x < 6 小数// 2 + Math.random()*6 返回的就是 2<= x < 8 小数// (int)(2 + Math.random()*6) = 2 <= x <= 7// (3) 公式就是 (int)(a + Math.random() * (b-a +1) )for (int i = 0; i < 100; i++) {System.out.println((int) (2 + Math.random() * (7 - 2 + 1)));}//max , min 返回最大值和最小值int min = Math.min(1, 9);int max = Math.max(45, 90);System.out.println("min=" + min);System.out.println("max=" + max);}
}

Arrays 类

基本介绍

Arrays 里面包含了一系列静态方法,用于管理或操作数组(比如排序和搜索)

常见方法示例(均为静态方法)

public class ArraysMethod01 {public static void main(String[] args) {//1. toString 返回数组的字符串形式Integer[] integers = {1, 20, 90};System.out.println(Arrays.toString(integers));//2. sort 排序Integer[] sortArr = {1, -1, 7, 0, 3};Arrays.sort(sortArr);System.out.println(Arrays.toString(sortArr));//3. binarySearch 二分查找Integer[] searchArr = {1,2,4,7,23,45,47,89};int index = Arrays.binarySearch(searchArr,23);System.out.println(index);//4. copyOf 数组copyInteger[] newArr = Arrays.copyOf(searchArr, searchArr.length-1);System.out.println(Arrays.toString(newArr));//5. fill 数组元素填充Integer[] num = {1,2,3,4,5,7,6};Arrays.fill(num,66);System.out.println(Arrays.toString(num));}
}

System 类

常见方法示例

public class System_ {public static void main(String[] args) {//1. exit 退出当前程序System.out.println("ok1");// //1. exit(0) 表示程序退出// //2. 0 表示一个状态 , 正常的状态System.exit(0);//程序执行到此就会结束System.out.println("ok2");//2. arraycopy :复制数组元素,比较适合底层调用,// 一般使用 Arrays.copyOf 完成复制数组int[] src={1,2,3};int[] dest = new int[3];// dest 当前是 {0,0,0}//主要是搞清楚这五个参数的含义// * @param src the source array. // srcPos: 从源数组的哪个索引位置开始拷贝// * @param srcPos starting position in the source array. // dest : 目标数组,即把源数组的数据拷贝到哪个数组// * @param dest the destination array. // destPos: 把源数组的数据拷贝到 目标数组的哪个索引// * @param destPos starting position in the destination data. // length: 从源数组拷贝多少个数据到目标数组// * @param length the number of array elements to be copied.System.arraycopy(src, 0, dest, 0, src.length);System.out.println("dest=" + Arrays.toString(dest));//[1, 2, 3]//3. currentTimeMillens:返回当前时间距离 1970-1-1 的毫秒数System.out.println(System.currentTimeMillis());}
}

BigInteger 和 BigDecimal 类

基本介绍

  1. BigInteger 适合保存比较大的整型

  2. BigDecimal 适合保存精度更高的浮点型(小数)

public class BigInteger_ {public static void main(String[] args) {//当我们编程中,需要处理很大的整数,long 不够用//可以使用 BigInteger 的类来搞定// long l = 23788888899999999999999999999l;// System.out.println("l=" + l);BigInteger bigInteger = new BigInteger("23788888899999999999999999999");BigInteger bigInteger2 = new BigInteger("1009999999999999999999999999999");System.out.println(bigInteger);//1. 在对 BigInteger 进行加减乘除的时候,需要使用对应的方法,不能直接进行 + - * ///2. 可以创建一个 要操作的 BigInteger 然后进行相应操作BigInteger add = bigInteger.add(bigInteger2);System.out.println(add);//加BigInteger subtract = bigInteger.subtract(bigInteger2);System.out.println(subtract);//减BigInteger multiply = bigInteger.multiply(bigInteger2);System.out.println(multiply);//乘BigInteger divide = bigInteger.divide(bigInteger2);System.out.println(divide);//除}
}
public class BigDecimal_ {public static void main(String[] args) {//当我们需要保存一个精度很高的数时,double 不够用//可以是 BigDecimal// double d = 1999.11111111111999999999999977788d;// System.out.println(d);BigDecimal bigDecimal = new BigDecimal("1999.11");BigDecimal bigDecimal2 = new BigDecimal("3");System.out.println(bigDecimal);//1. 如果对 BigDecimal 进行运算,比如加减乘除,需要使用对应的方法//2. 创建一个需要操作的 BigDecimal 然后调用相应的方法即可System.out.println(bigDecimal.add(bigDecimal2));System.out.println(bigDecimal.subtract(bigDecimal2));System.out.println(bigDecimal.multiply(bigDecimal2));//System.out.println(bigDecimal.divide(bigDecimal2));//可能抛出异常 ArithmeticException//在调用 divide 方法时,指定精度即可. BigDecimal.ROUND_CEILING//如果有无限循环小数,就会保留 分子 的精度System.out.println(bigDecimal.divide(bigDecimal2, BigDecimal.ROUND_CEILING));}
}

日期类(Date)

第三代日期类

public class LocalDate01 {public static void main(String[] args) {//第三代日期//1. 使用 now() 返回表示当前日期时间的 对象LocalDateTime ldt = LocalDateTime.now(); //LocalDate.now();//LocalTime.now()System.out.println(ldt);//2. 使用 DateTimeFormatter 对象来进行格式化// 创建 DateTimeFormatter 对象DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");String format = dateTimeFormatter.format(ldt);System.out.println("格式化的日期=" + format);System.out.println("年=" + ldt.getYear());System.out.println("月=" + ldt.getMonth());//英文月份System.out.println("月=" + ldt.getMonthValue());//数字月份System.out.println("日=" + ldt.getDayOfMonth());System.out.println("时=" + ldt.getHour());System.out.println("分=" + ldt.getMinute());System.out.println("秒=" + ldt.getSecond());LocalDate now = LocalDate.now(); //可以获取年月日LocalTime now2 = LocalTime.now();//获取到时分秒//提供 plus 和 minus 方法可以对当前时间进行加或者减//看看 890 天后,是什么时候 把 年月日-时分秒LocalDateTime localDateTime = ldt.plusDays(890);System.out.println("890 天后=" + dateTimeFormatter.format(localDateTime));//看看在 3456 分钟前是什么时候,把 年月日-时分秒输出LocalDateTime localDateTime2 = ldt.minusMinutes(3456);System.out.println("3456 分钟前 日期=" + dateTimeFormatter.format(localDateTime2));}
}

集合

集合的好处

  1. 可以动态保存任意多个对象,使用比较方便

  2. 提供了一系列方便的操作对象的方法

  3. 使用集合添加、删除新元素的示意代码

集合的框架体系

Collection 接口和常用方法

Collection 接口实现类的特点

  1. Collection实现子类可以存放多个元素,每个元素可以是 Object

  2. 有些 Collection 的实现类,可以存放重复元素,有些不可以

  3. 有些 Collection 的实现类,有些是有序的(List),有些不是有序的(Set)

  4. Collection 接口没有直接的实现子类,是通过它的子接口 List 和 Set 来实现的

Collection 接口遍历元素方式 1-使用 Iterator(迭代器)

基本介绍

  1. Iterator 对象成为迭代器,主要用于遍历 Collection 集合中的元素

  2. 所有实现了 Collection 接口的集合类都有一个 iterator() 方法,用以返回一个实现了 Iterator 接口的对象,即可以返回一个迭代器

  3. Iterator 仅用于遍历集合,Iterator 本身并不存放对象

基本语法

//方式一
Iterator iterator = 集合名.iterator();// 得到一个集合的迭代器
while (iterator.hasNext()) { // while 快捷键 -> itit
// hasNext() 判断是否还有下一个元素,如果没有则退出Object next =  iterator.next();    // 接收元素// next() 作用:1.下移 2.将下移以后集合位置上的元素返回System.out.println(next);
}
//方式二
for(元素类型 元素名 : 集合名或数组名) {System.out.println(元素名);
}

List 接口和常用方法

List 接口基本介绍

List 接口是 Collection 接口的子接口

  1. List 集合类中元素有序(即添加顺序和取出顺序一致),且可重复

  2. List 集合类中的每个元素都有其对应的顺序索引,即支持索引

  3. List 容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素

  4. JDK API 中 List 接口的常用实现类有:ArrayList , LinkedList , Vector

List 接口的常用方法

代码示例

public class ListMethod {@SuppressWarnings({"all"})public static void main(String[] args) {List list = new ArrayList();list.add("张三丰");list.add("贾宝玉");
// void add(int index, Object ele):在 index 位置插入 ele 元素
//在 index = 1 的位置插入一个对象list.add(1, "韩顺平");System.out.println("list=" + list);
// boolean addAll(int index, Collection eles):从 index 位置开始将 eles 中的所有元素添加进来List list2 = new ArrayList();list2.add("jack");list2.add("tom");list.addAll(1, list2);System.out.println("list=" + list);
// Object get(int index):获取指定 index 位置的元素System.out.println(list.get(3));
// int indexOf(Object obj):返回 obj 在集合中首次出现的位置System.out.println(list.indexOf("tom"));//2
// int lastIndexOf(Object obj):返回 obj 在当前集合中末次出现的位置list.add("韩顺平");System.out.println("list=" + list);System.out.println(list.lastIndexOf("韩顺平"));
// Object remove(int index):移除指定 index 位置的元素,并返回此元素list.remove(0);System.out.println("list=" + list);
// Object set(int index, Object ele):设置指定 index 位置的元素为 ele , 相当于是替换. list.set(1, "玛丽");System.out.println("list=" + list);
// List subList(int fromIndex, int toIndex):返回从 fromIndex 到 toIndex 位置的子集合
// 注意返回的子集合 fromIndex <= subList < toIndexList returnlist = list.subList(0, 2);System.out.println("returnlist=" + returnlist);}}

List 的三种遍历方式 [ArrayList, LinkedList,Vector]

方式一:使用 iterator

Iterator iterator = list.iterator();
while(iterator.hasNext()) {Object o = iterator.next();System.out.println(o);
}

方式二:使用增强 for

for(Object o : list) {System.out.println(o);
}

方式三:使用普通 for

for(int i=0; i<list.size(); i++){Object object = list.get(i);System.out.println(object);
}

ArrayList 和 LinkedList 的比较

底层结构

增删的效率

改查的效率

ArrayList

可变数组

较低,通过数组扩容

较高

ListedList

双向链表

较高,通过链表追加

较低

Set 接口和常用方法

Set 接口基本介绍

  1. 无序(添加和取出的顺序不一致),没有索引

  2. 不允许重复元素,所以最多包含一个 null

  3. JDK API 中 Set 接口的常用实现类有:HashSet , TreeSet

Set 接口的常用方法

和 List 接口一样,Set 接口也是 Collection 的子接口,因此,常用方法和 Collection 接口一样

Set 接口的遍历方式

同 Collection 的遍历方式一样,因为 Set 接口是 Collection 接口的子接口

  1. 可以使用迭代器

  2. 增强 for

  3. 不能使用索引的方式来获取

Set 接口实现类-HashSet

HashSet 的全面说明

  1. HashSet 实现了 Set 接口

  2. HashSet 底层实际上是 HashMap

  3. 可以存放 null 值,但是只能有一个 null

  4. HashSet 不保证元素是有序的,取决于 hash 后,在确定索引的结果(即,不保证存放元素的顺序和取出的顺序一致)

  5. 不能有重复元素/对象,在前面 Set 接口使用已经讲过

Set 接口实现类-LinkedHashSet

LinkedHashSet 的全面说明

  1. LinkedHashSet 是 HashSet 的子类

  2. LinkedHashSet 底层是一个 LinkedHashMap ,底层维护了一个 数组 + 双向链表

  3. LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的

  4. LinkedHashSet 不允许添加重复元素

Map 接口和常用方法

Map 接口实现类的特点

  1. Map 与 Collection 并列存在。用于保存具有映射关系的数据:Key-Value(双列元素)

  2. Map 中的 Key 和 Value 可以是任何引用类型的数据,会封装到 HashMap$Node 对象中

  3. Map 中的 key 不允许重复,原因和 HashSet 一样

  4. Map 中的 value 可以重复

  5. Map 的 key 可以为 null ,value 也可以为 null ,注意 key 为 null 只能有一个,value 为 null 可以多个

  6. 常用 String 类作为 Map 的key

  7. key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到对应的 value

Map 接口遍历方法

@SuppressWarnings({"all"})
public class MapFor {public static void main(String[] args) {Map map = new HashMap();map.put("邓超", "孙俪");map.put("王宝强", "马蓉");map.put("宋喆", "马蓉");map.put("刘令博", null);map.put(null, "刘亦菲");map.put("鹿晗", "关晓彤");
//第一组: 先取出 所有的 Key , 通过 Key 取出对应的 ValueSet keyset = map.keySet();//(1) 增强 forSystem.out.println("-----第一种方式-------");for (Object key : keyset) {System.out.println(key + "-" + map.get(key));}
//(2) 迭代器System.out.println("----第二种方式--------");Iterator iterator = keyset.iterator();while (iterator.hasNext()) {Object key = iterator.next();System.out.println(key + "-" + map.get(key));}
//第二组: 把所有的 values 取出Collection values = map.values();
//这里可以使用所有的 Collections 使用的遍历方法
//(1) 增强 forSystem.out.println("---取出所有的 value 增强 for----");for (Object value : values) {System.out.println(value);}
//(2) 迭代器System.out.println("---取出所有的 value 迭代器----");Iterator iterator2 = values.iterator();while (iterator2.hasNext()) {Object value = iterator2.next();System.out.println(value);}
//第三组: 通过 EntrySet 来获取 k-vSet entrySet = map.entrySet();// EntrySet<Map.Entry<K,V>>
//(1) 增强 forSystem.out.println("----使用 EntrySet 的 for 增强(第 3 种)----");for (Object entry : entrySet) {
//将 entry 转成 Map.EntryMap.Entry m = (Map.Entry) entry;System.out.println(m.getKey() + "-" + m.getValue());}
//(2) 迭代器System.out.println("----使用 EntrySet 的 迭代器(第 4 种)----");Iterator iterator3 = entrySet.iterator();while (iterator3.hasNext()) {Object entry = iterator3.next();
//System.out.println(next.getClass());//HashMap$Node -实现-> Map.Entry (getKey,getValue)
//向下转型 Map.EntryMap.Entry m = (Map.Entry) entry;System.out.println(m.getKey() + "-" + m.getValue());}}
}

Map 接口实现类-HashMap

HashMap 小结

  1. Map 接口的常用实现类:HashMap , Hashtable 和 Properties

  2. HashMap 是 Map 接口使用频率最高的实现类

  3. HashMap 是以 key-value 键值对的方式来存储数据(HashMap$Node 类型)

  4. key 不能重复,但是值可以重复,允许使用 null 键和 null值

  5. 如果添加相同的 key ,则会覆盖原来的 key-value ,等同于修改(key 不会替换,value 会替换)

  6. 与 HashSet 一样,不保证映射的顺序,因为底层是以 hash 表的方式来存储的

  7. HashMap 没有实现同步,因此线程是不安全的,方法没有做同步的互斥操作,没有 synchronized

Map 接口实现类-Hashtable

Hashtable 的基本介绍

  1. 存放的元素是键值对:即 K-V

  2. Hashtable 的键和值都不能为 null ,否则会抛出 NullPointerException

  3. Hashtable 使用方法基本上和 HashMap 一样

  4. Hashtable 是线程安全的(synchronized),HashMap 是线程不安全的

Hashtable 和 HashMap 对比

版本

线程安全(同步)

效率

允许null键null值

HashMap

1.2

不安全

可以

Hashtable

1.0

安全

较低

不可以

Map 接口实现类-Properties

基本介绍

  1. Properties 类继承自 Hashtable 类并且实现了 Map接口,也是使用一种键值对的形式来保存数据

  2. 它的使用特点和 Hashtable 类似

  3. Properties 还可以用于从 xxx.properties 文件中,加载数据到 Properties 类对象,并进行读取和修改

  4. 说明:工作后 xxx.properties 文件通常作为配置文件,这个知识点在IO流举例

总结 开发中如何选择集合实现类

在开发中,选择什么集合实现类,主要取决于业务操作特点,然后根据集合实现类特性进行选择,分析如下:

  1. 先判断存储类型(一组对象[单列]或一组键值对[双列])

  2. 一组对象[单列]:Collection接口

允许重复:List

增删多:LinkedList(底层维护了一个双向链表)

改查多:ArrayList(底层维护 Object 类型的可变数组)

不允许重复:Set

无序:HashSet(底层是 HashMap,维护了一个哈希表 即(数组 + 链表 + 红黑树))

排序:TreeSet

插入和取出顺序一致:LinkedHashSet ,维护数组 + 双向链表

  1. 一组键值对[双列]:Map

键无序:HashMap(底层是:哈希表)

键排序:TreeMap

键插入和取出顺序一致:LinkedHashMap

读取文件:Properties

Collections 工具类

Collections 工具类介绍

  1. Collections 是一个操作 Set , List 和 Map 等集合的工具类

  2. Collections 中提供了一系列静态的方法对集合元素进行排序,查询和修改等操作

排序操作:(均为 static 方法)

  1. reverse(List):反转 List 中元素的顺序

  2. shuffle(List):对 List 集合元素进行随机排序

  3. sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序

  4. sort(List , Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序

  5. swap(List , int , int):将指定 List 集合中的 i 处元素和 j 处元素进行交换

查找,替换:

  1. Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素

  2. Object max(Collection , Comparator):根据 Comparator 指定的顺序返回给定集合中的最大元素

  3. Object min(Collection)

  4. Object min(Collection , Comparator)

  5. int frequency(Collection , Object):返回指定集合中指定元素的出现次数

  6. void copy(List dest , List src):将 src 中的内容复制到 dest 中

  7. boolean replaceAll(List list , Object oldVal , Object newVal):使用新值替换 List 对象的所有旧值

泛型

泛型的好处

  1. 编译时,检查添加元素的类型,提高了安全性

  2. 减少了类型转换的次数,提高效率

  3. 不再提示编译警告

泛型的语法

泛型的声明

interface 接口 <T> {}
class 类 <K,V> {}
// 说明:
// 1.其中,T,K,V 不代表值,而是表示类型,且只能是引用类型
// 2.任意字母都可以。常用 T 表示,是 Type 缩写

泛型的实例化

要在类名后面指定类型参数的值(类型)。如:

List <Object> strList = new ArrayList <String> ();
Iterator <Customer> iterator = customers.iterator();
// 说明:
//在给泛型指定具体类型后,可以传入该类型或者其子类类型

自定义泛型

自定义泛型类

class 类名 <T,R,...> { //...表示可以由多个泛型成员;
}

注意细节

  1. 普通成员(属性,方法)可以使用泛型

  2. 使用泛型的数组,不能初始化

  3. 静态方法中不能使用类的泛型

  4. 泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定类型)

  5. 如果在创建对象时,没有指定类型,默认为 Object

自定义泛型接口

interface 接口名 <T,R,...>{
}

注意细节

  1. 接口中,静态成员也不能使用泛型(这个和泛型类的规定一样)

  2. 泛型接口的类型,在继承接口或者实现接口时确定

  3. 没有指定类型,默认为 Object

自定义泛型方法

修饰符 <T,R,...> 返回类型 方法名(参数列表){
}

注意细节

  1. 泛型方法,可以定义在普通类中,也可以定义在泛型类中

  2. 当泛型方法被调用时,类型会确定

  3. public void eat(E e) {},修饰符后没有 <T,R,...> ,eat 方法不是泛型方法,而是使用了泛型

泛型的继承和通配符说明

  1. 泛型不具备继承性

  2. <?> :支持任意泛型类型

  3. <? extends A>:支持A类以及A类的子类,规定了泛型的上限

  4. <? super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限

韩顺平JAVA学习笔记(入门自用)相关推荐

  1. B站韩顺平java学习笔记(三)--运算符章节

    目录 一.算术运算符 1.  表格 2.  练习题: 二. 关系运算符 1.  表格 三.逻辑运算符 1.  表格 2.  练习题 四.赋值运算符 1.  介绍 2.细节特点 五.三元运算符 1.  ...

  2. B站韩顺平java学习笔记(六)--面向对象编程章节

    目录 一.类和对象 1.定义及区别 2.对象内存布局 3.属性/成员变量 (1)基本介绍 (2)注意事项和细节说明 (3)访问属性 4.对象 (1)创建对象 (2)对象分配机制 ​(3)Java创建对 ...

  3. B站韩顺平java学习笔记(二十五)-- 正则表达式章节

    目录 一  正则表达式入门 1  极速体验正则表达式威力 二  为什么要学正则表达式 三  正则表达式基本介绍 1  介绍 2  正则表达式底层实现

  4. 韩顺平Java学习笔记_IO流专题

    目录 一 文件 1.文件的概念: 文件是保存数据的地方 2.文件流:文件在程序中是以流的形式来操作的 2.1.输入流指数据从数据源(文件)到程序(内存)的路径 2.2.输出流指数据从程序(内存)到数据 ...

  5. 韩顺平Java学习笔记P245对象创建流程分析P246this关键字-P250

    P245对象创建流程分析 //1.先在方法区加载方法类 //2.在堆里开空间一个存放age,一个存放name //3.(先默认初始化有默认值age=0,name=null,再显示初始化age=90,n ...

  6. B站韩顺平java学习笔记(十六)-- 多线程基础章节

    目录 一  线程介绍 1  线程相关概念 (1)程序 (2)进程 (3)什么是线程 (4)其他相关概念 (5)查看电脑有多少个cpu核 二  线程的使用 1  线程的创建 (1)继承Thread类,重 ...

  7. B站韩顺平java学习笔记(八)-- 房屋出租系统(项目)章节

    目录 一 项目需求说明 1 项目界面 二  房屋租赁程序框架图 ​三  系统实现 1  完成House类 2  显示主菜单和完成退出软件的功能 3  完成显示房屋列表的功能 4  添加房屋信息的功能 ...

  8. B站韩顺平java学习笔记(二十三)-- MYSQL基础篇 章节

    目录 一  数据库 1  数据库简单原理图 2  使用命令行窗口连接MYSQL数据库 3  MySQL三层结构 4  数据在数据库中的存储方式 5  SQL语句分类 6  创建数据库 7  查看.删除 ...

  9. 韩顺平Java自学笔记 反射

    一.反射入门案例 目录 一.反射入门案例 二.反射的机制 1.反射的原理 2.反射相关的类 3.反射的优点和缺点 三.Class类详解 1.Class类的特征 2.Class的常用方法 3.获取Cla ...

  10. 韩顺平Java学习 泛型

    目录 一.泛型的语法 1.传统的方法遍历集合存在的问题 2.使用泛型来解决传统集合添加元素带来的问题 3.泛型使用介绍 4.泛型的使用细节 5.泛型课堂练习 二.自定义泛型 1.自定义泛型类的规范 ​ ...

最新文章

  1. 清华大学图神经网络综述:模型与应用
  2. Python_summary
  3. Java客户端操作zookeeper:获取/节点的子节点代码示例
  4. php列目录设置密码,PHP输入密码并列出目录文件生成超链接代码
  5. jquery.lazyload.js详解
  6. android 处理鼠标滚轮事件 【转】
  7. 语言差异引起的问题解决一例
  8. 打印机更换感光鼓单元k_干货,激光打印机常见故障维修方法总结
  9. android studio aspectj使用,androidStudio中使用 AspectJ
  10. windows 显示苹果分区_基准测试数据显示苹果M1运行Windows的表现比微软自家硬件好上近一倍...
  11. 【转】浅析Java中的final关键字
  12. 运算符和||运算符的优先级问题 专题
  13. android通过ContentProvider 取得电话本的数据
  14. Spring-jdbc-JdbcTemplate
  15. RK3288 error: undefined reference to 'LOGD'
  16. JS获取填报扩展单元格控件的值
  17. p2p网络终结者最高权限使用教程
  18. 计算机公式最小值,excel最小值函数
  19. 洛谷P4158 [SCOI2009]粉刷匠 题解
  20. 必要的先决条件安装失败_先决条件

热门文章

  1. 信号与系统思维导图框图(更新)
  2. android 使用shell模拟触屏_Android按键精灵 触摸精灵 触动精灵等软件模拟屏幕点击的基本原理...
  3. Linux卸载JDK(虚拟机自带JDK)
  4. 高等代数——大学高等代数课程创新教材(丘维声)——1.3笔记+习题
  5. 计算机抓取整个屏幕的按键,技术员搞定电脑截全屏快捷键【搞定方法】
  6. 阿里云OS和Android之争100问
  7. PDF转JPG的工具
  8. 《深入浅出WPF》视频列表
  9. 树莓派人脸识别源代码
  10. writeup 2019“新华三杯”中国医疗机构网络安全攻防演练大赛CTF(复赛)