• Java学习笔记零基础入门2


    前部分,基础篇章

    第八章面向对象编程(高级部分)

    目录

    第八章面向对象编程(高级部分)

    8.1 类变量和类方法

    8.1.1 什么是类变量

    8.1.2 如何定义类变量

    8.1.3 如何访问类变量

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

    8.1.5 类方法基本介绍

    8.1.6 类方法的调用

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

    8.2 理解main方法语法

    8.2.1 深入理解main方法

    8.2.2 特别提示:

    8.3 代码块

    8.3.1 基本介绍

    8.3.2 基本语法

    8.3.3 代码块的好处

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

    8.4 单例设计模式

    8.4.1 什么是单例模式

    8.4.2 单例模式应用实例

    8.4.3 饿汉式VS懒汉式

    8.5 final 关键字

    8.5.1 基本介绍

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

    8.6 抽象类

    8.6.1 抽象类快速入门

    8.6.2 抽象类的介绍

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

    8.7 接口

    8.7.1 基本介绍

    8.7.2 注意事项和细节

    8.7.3 实现接口vs继承类

    8.8 内部类

    8.8.1 基本介绍

    8.8.2 基本语法

    8.8.3 内部类的分类

    8.8.4 局部内部类的使用

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

    第九章枚举和注解

    9.1 先看一个需求

    9.2 枚举简介

    9.3 枚举的二种实现方式

    9.3.1 自定义类实现枚举

    9.3.2 自定义类实现枚举

    9.3.3  enum关键字实现枚举

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

    9.4 enum实现接口

    9.5 注解的理解

    9.6 基本的 Annotation 介绍

    9.6.1  @Override 注解的案例

    9.6.2 @Deprecated注解的案例

    9.6.3 @SuppressWarnings 注解的案例

    9.7 JDK 的元 Annotation(元注解, 了解)

    9.7.1 元注解的基本介绍

    9.7.2 元注解的种类 (使用不多,了解, 不用深入研究)

    9.7.3  @Retention 注解

    第十章异常-Exception

    10.1 异常介绍

    10.2 异常体系图一览

    10.2.1 异常体系图

    10.2.2 异常体系图的小结

    10.3 常见的运行时异常

    10.3.1 常见的运行时异常包括

    10.4 编译异常

    10.4.1 介绍

    10.4.2 常见的编译异常

    10.5 异常处理

    10.5.1 基本介绍

    10.5.2 异常处理的方式

    10.5.3 示意图

    10.6  try-catch 异常处理

    10.6.1 try-catch 方式处理异常说明

    10.6.2 try-catch-finally 执行顺序小结

    10.7 throws 异常处理

    10.7.1 基本介绍

    10.7.2 注意事项和使用细节

    10.8 自定义异常

    10.8.1 基本概念

    10.8.2 自定义异常的步骤

    10.9 throw 和 throws 的区别

    10.9.1 一览表

    第十一章常用类

    11.1 包装类

    11.1.1 包装类的分类

    11.1.2 包装类和基本数据的转换

    11.2 String类

    11.2.1 String类的理解和创建对象

    11.2.2 创建String对象的两种方式

    11.2.3 两种创建String对象的区别

    11.3 字符串的特性

    11.3.1 说明

    11.4 String 类的常见方法

    11.4.1 说明

    11.4.2 String类的常见方法一览

    11.5 StringBuffer 类

    11.5.1 基本介绍

    11.5.2 String VS StringBuffer

    11.5.3 String和StringBuffer相互转换

    11.6 StringBuilder类

    11.6.1 基本介绍

    11.6.2  StringBuilder常用方法

    11.6.3  String、StringBuffer 和 StringBuilder 的比较

    11.6.4 String、StringBuffer 和 StringBuilder 的选择

    11.7 Math 类

    11.7.1 基本介绍

    11.7.2 方法一览(均为静态方法)

    11.8 Arrays类

    11.9 System类

    11.9.1  System类常见方法

    11.10 BigInteger和BigDecimal类

    11.10.1  BigInteger和BigDecimal介绍

    第 十二 章集合

    12.1 集合的理解和好处

    12.1.1  数组

    12.1.2 集合

    12.2  集合的框架体系

    12. 3 Collection 接口和常用方法

    12.3.1 Collection 接口实现类的特点

    12.4 List接口和常用方法

    12.4.1 List接口基本介绍

    12.4.2  List的三种遍历方式

    12.5 ArrayList底层结构和源码分析

    12.5.1  ArrayList的注意事项

    12.5.2 ArrayList的底层操作机制源码分析(重点,难点.)

    12.6  Vector 底层结构和源码剖析

    12.6.1  Vector 的基本介绍

    12.6.2 Vector和ArrayList的比较

    12.7  LinkedList 底层结构

    12.7.1  LinkedList 的全面说明

    12.7.2 LinkedList 的底层操作机制

    12.8 ArrayList 和 LinkedList 比较

    12.8.1 ArrayList 和 LinkedList 的比较

    12.9 Set 接口和常用方法

    12.9.1  Set 接口基本介绍

    12.9.2 Set接口的常用方法

    12.9.3  Set接口的遍历方式

    12.10 Set 接口实现类-HashSet

    12.10.1 HashSet 的全面说明

    12.11 Map 接口和常用方法

    12.11.1 Map 接口实现类的特点 [很实用]

    12.11.2  Map 接口遍历方法

    12.11.3 HashMap 小结

    12.12 Map接口实现类-Hashtable

    12.12.1 HashTable的基本介绍

    12.12.2 Hashtable 和 HashMap 对比

    12.13  Map 接口实现类-Properties

    12.13.1  基本介绍

    12.14 总结-开发中如何选择集合实现类(记住)

    12.15 Collections工具类

    12.15.1 Collections工具类介绍

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

    12.15.3 查找、替换

    第 十三 章泛型

    13.1 泛型的理解和好处

    13.1.1 泛型的好处

    13.2 泛型介绍

    13.3 泛型的语法

    13.3.1 泛型的声明

    13.3.2 泛型的实例化

    13.3.3 泛型使用的注意事项和细节

    13.4 自定义泛型

    13.4.1 自定义泛型类(难度)

    13.5  泛型的继承和通配符

    13.5.1 泛型的继承和通配符说明


    8.1 类变量和类方法

    8.1.1 什么是类变量

    类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量。这个从前面的图也可看出来。

    8.1.2 如何定义类变量

    定义语法:
    访问修饰符static 数据类型变量名;
    static 访问修饰符数据类型变量名;

    8.1.3 如何访问类变量

    类名.类变量名
    或者  对象名.类变量名【静态变量的访问修饰符的访问权限和范围和普通属性是一样的。】
    推荐使用:    类名.类变量名;

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

    1.什么时候需要用类变量
    当我们需要让某个类的所有对象都共享一个变量时,就可以考虑使用类变量(静态变量):比如:定义学生类,统计所有学生共交多少钱。    

    2.类变量与实例变量(普通属性)区别
    类变量是该类的所有对象共享的,而实例变量是每个对象独享的。

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

    4.类变量可以通过        类名.类变量名        或者        对象名.类变量名        来访问,但java设计者推荐我们使用        类名.类变量名方式访问。【前提是满足访问修饰符的访问权限和范围】

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

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

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

    8.1.5 类方法基本介绍

    类方法也叫静态方法。
    形式如下:
    访问修饰符  static  数据返回类型方法名  (){ }
    static  访问修饰符  数据返回类型方法名  (){ }

    8.1.6 类方法的调用

    使用方式:        类名.类方法名        或者        对象名.类方法名

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

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

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

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

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

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

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

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

    代码:

    1. packagecom.hspedu.static_;
    2. publicclassStaticMethodDetail{
    3. publicstaticvoidmain(String[]args){
    4. D.hi();//ok
    5. //非静态方法,不能通过类名调用
    6. //D.say();,错误,需要先创建对象,再调用
    7. newD().say();//可以
    8. }
    9. }
    10. class D {
    11. private int n1 = 100;
    12. private static int n2 = 200;
    13. public void say() {//非静态方法,普通方法
    14. }
    15. public static void hi() {//静态方法,类方法
    16. //类方法中不允许使用和对象有关的关键字,
    17. //比如this 和 super。普通方法(成员方法)可以。
    18. //System.out.println(this.n1);
    19. }
    20. //类方法(静态方法)中 只能访问 静态变量 或静态方法
    21. //口诀:静态方法只能访问静态成员.
    22. public static void hello() {
    23. System.out.println(n2);
    24. System.out.println(D.n2);
    25. //System.out.println(this.n2);不能使用
    26. hi();//OK
    27. //say();//错误
    28. }
    29. //普通成员方法,既可以访问 非静态成员,也可以访问静态成员
    30. //小结: 非静态方法可以访问 静态成员和非静态成员
    31. public void ok() {
    32. //非静态成员
    33. System.out.println(n1);
    34. say();
    35. //静态成员
    36. System.out.println(n2);
    37. hello();
    38. }
    39. }

    8.2 理解main方法语法

    8.2.1 深入理解main方法

    解释main方法的形式:public static void main(String[ ] args){ }
    1. main方法时虚拟机调用
    2. java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public
    3. java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static
    4.该方法接收String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数
    5. java 执行的程序 参数1 参数2 参数3 
     

    8.2.2 特别提示:

    1)在main()方法中,我们可以直接调用main方法所在类的静态方法或静态属性。
    2)但是,不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员

    8.3 代码块

    8.3.1 基本介绍

    代码化块又称为初始化块,属于类中的成员[即是类的一部分],类似于方法,将逻辑语句封装在方法体中,通过{ }包围起来。
    但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显式调用,而是加载类时,或创建对象时隐式调用。

    8.3.2 基本语法

    [修饰符]  {
            代码
    };
    说明注意:
    1)修饰符可选,要写的话,也只能写static
    2)代码块分为两类,使用static修饰的叫静态代码块,没有static修饰的,叫普通代码块/非静态代码块。
    3)逻辑语句可以为任何逻辑语句(输入、输出、方法调用、循环、判断等)
    4) ;号可以写上,也可以省略。

    8.3.3 代码块的好处

    1)相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作
    2)场景:如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性

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

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

    2) 类什么时候被加载
    1.创建对象实例时(new)
    2.创建子类对象实例,父类也会被加载
    3.使用类的静态成员时(静态属性,静态方法)   案例演示:A类extends B类的静态块

    3) 普通的代码块,在创建对象实例时,会被隐式的调用。
    被创建一次,就会调用一次。
    如果只是使用类的静态成员时,普通代码块并不会执行。

    小结:  1.static代码块是类加载时,执行,只会执行一次
    2.普通代码块是在创建对象时调用的,创建一次,调用一次
    3.类加载的3种情况,需要记住.

    4) 创建一个对象时,在一个类调用顺序是:(重点,难点):
    1.调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用)
    2.调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按定义顺序调用)
    3.调用构造方法。

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

    1. class A{
    2. public A(){ //构造器
    3. //这里有隐藏的执行要求
    4. //(1) superO://这个知识点,在前面讲解继承的时候,
    5. //(2)调用普通代码块的
    6. System.out.println("ok");
    7. }}

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

    1. 父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
    2. 子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
    3. 父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
    4. 父类的构造方法
    5. 子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
    6. 子类的构造方法  //面试题

    7)静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员。学习比较麻烦,工作轻松

    8.4 单例设计模式

    8.4.1 什么是单例模式

    单例(单个的实例)
    1. 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法
    2. 单例模式有两种方式: 1)饿汉式 2)懒汉式

    8.4.2 单例模式应用实例

    步骤如下:
    1)构造器私有化 =》防止直接new
    2)类的内部创建对象
    3)向外暴露一个静态的公共方法。getInstance
    代码:

    1. package com.hspedu.single_;
    2. public class SingleTon01 {
    3. public static void main(String[] args) {
    4. GirlFriend xh = new GirlFriend("小红");
    5. GirlFriend xb = new GirlFriend("小白");
    6. //通过方法可以获取对象
    7. GirlFriend instance = GirlFriend.getInstance();
    8. System.out.println(instance);
    9. GirlFriend instance2 = GirlFriend.getInstance();
    10. System.out.println(instance2);
    11. System.out.println(instance == instance2);//T
    12. //System.out.println(GirlFriend.n1);
    13. //...
    14. }}
    15. //有一个类, GirlFriend
    16. //只能有一个女朋友
    17. class GirlFriend {
    18. private String name;
    19. //public static int n1 = 100;
    20. //为了能够在静态方法中,返回 gf对象,需要将其修饰为static
    21. //對象,通常是重量級的對象, 餓漢式可能造成創建了對象,但是沒有使用.
    22. private static GirlFriend gf = new GirlFriend("小红红");
    23. //如何保障我们只能创建一个 GirlFriend 对象
    24. //步骤[单例模式-饿汉式]
    25. //1. 将构造器私有化
    26. //2. 在类的内部直接创建对象(该对象是static)
    27. //3. 提供一个公共的static方法,返回 gf对象
    28. private GirlFriend(String name) {
    29. System.out.println("構造器被調用.");
    30. this.name = name;
    31. }
    32. public static GirlFriend getInstance() {
    33. return gf;
    34. }
    35. @Override
    36. public String toString() {
    37. return "GirlFriend{" +
    38. "name='" + name + '\' +
    39. '}';
    40. }}
    41. package com.hspedu.single_;
    42. /**
    43. * 演示懶漢式的單例模式
    44. */
    45. public class SingleTon02 {
    46. public static void main(String[] args) {
    47. //new Cat("大黃");
    48. //System.out.println(Cat.n1);
    49. Cat instance = Cat.getInstance();
    50. System.out.println(instance);
    51. //再次調用getInstance
    52. Cat instance2 = Cat.getInstance();
    53. System.out.println(instance2);
    54. System.out.println(instance == instance2);//T
    55. }
    56. }
    57. //希望在程序運行過程中,只能創建一個Cat對象
    58. //使用單例模式
    59. class Cat {
    60. private String name;
    61. public static int n1 = 999;
    62. private static Cat cat ; //默認是 null
    63. //步驟
    64. //1.仍然構造器私有化
    65. //2.定義一個static 靜態屬性對象
    66. //3.提供一個public 的 static 方法,可以返回一個Cat對象
    67. //4.懶漢式,只有當用戶使用getInstance 時,才返回cat對象, 後面再次調用時,會返回上次創建的cat對象
    68. //
    69. 從而保證了單例
    70. private Cat(String name) {
    71. System.out.println("構造器調用...");
    72. this.name = name;
    73. }
    74. public static Cat getInstance() {
    75. if(cat == null) {//如果還沒有創建 cat 對象
    76. cat = new Cat("小可愛");
    77. }
    78. return cat;
    79. }
    80. @Override
    81. public String toString() {
    82. return "Cat{" +
    83. "name='" + name + '\' +
    84. '}';
    85. }}

    8.4.3 饿汉式VS懒汉式

    1. 二者最主要的区别在于创建对象的时机不同:饿汉式是在类加载就创建了对象实例,
    而懒汉式是在使用时才创建。
    2. 饿汉式不存在线程安全问题,懒汉式存在线程安全问题。(后面学习线程,会完善一把)
    3. 饿汉式存在浪费资源的可能。因为如果程序员一个对象实例都没有使用,那么饿汉式创建的对象就浪费了,懒汉式是使用时才创建,就不存在这个问题。
    4. 在我们javaSE标准类中,java.lang.Runtime就是经典的单例模式。

    8.5 final 关键字

    8.5.1 基本介绍

    final中文意思:最后的,最终的.
    final可以修饰类、属性、方法和局部变量.
    在某些情况下,程序员可能有以下需求,就会使用到final:
    1) 当不希望类被继承时,可以用final修饰.
    2) 当不希望父类的某个方法被子类猎盖/重写(override)时,可以用final关键字修饰。
    3) 当不希望类的的某个属性的值被修改,可以用final修饰.
    4) 当不希望某个局部变量被修改,可以使用final修饰
    代码:

    1. //如果我们要求A类不能被其他类继承
    2. //可以使用final 修饰 A类
    3. final class A { }
    4. class C {
    5. //如果我们要求hi不能被子类重写
    6. //可以使用final 修饰 hi方法
    7. public final void hi() {}
    8. }
    9. //当不希望类的的某个属性的值被修改,可以用final修饰
    10. class E {
    11. public final double TAX_RATE = 0.08;//常量
    12. //当不希望某个局部变量被修改,可以使用final修饰
    13. class F {
    14. public void cry() {
    15. //这时,NUM 也称为 局部常量
    16. final double NUM = 0.01;
    17. //NUM = 0.9;
    18. System.out.println("NUM=" + NUM);

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

    1 final修饰的属性又叫常量,一般用 XX XX XX来命名
    2) final修饰的属性在定义时,必须赋初值,并且以后不能再修改,赋值可以在如下位置之一
            1. 定义时:如public final double TAX_RATE=0.08;
            2. 在构造器中
            3. 在代码块中。
    3)如果final修饰的属性是静态的,则初始化的位置只能是
            1. 定义时        2. 在静态代码块不能在构造器中赋值。
    4) final类不能继承,但是可以实例化对象。
    5) 如果类不是final类,但是含有final方法,则该方法虽然不能重写,但是可以被继承。

    代码:

    1. class AA{
    2. /*
    3. 1. 定义时:如 publicfinal doubleTAX_RATE=0.08;
    4. 2. 在构造器中
    5. 3. 在代码块中
    6. */
    7. public final double TAX_RATE = 0.08;//1.定义时赋值
    8. public final double TAX_RATE2 ;
    9. public final double TAX_RATE3 ;
    10. public AA() {//构造器中赋值
    11. TAX_RATE2= 1.1;
    12. }
    13. {//在代码块赋值
    14. TAX_RATE3= 8.8;
    15. }
    16. /*
    17. 如果final 修饰的属性是静态的,则初始化的位置只能是
    18. 1 定义时 2 在静态代码块 不能在构造器中赋值。
    19. */
    20. public static final double TAX_RATE = 99.9;
    21. public static final double TAX_RATE2 ;
    22. static {
    23. TAX_RATE2= 3.3;
    24. }
    25. }
    26. //final 类不能继承,但是可以实例化对象
    27. final class CC { }
    28. //即,仍然遵守继承的机制.
    29. class DD {
    30. public final void cal() {
    31. //如果类不是final 类,但是含有final方法,则该方法虽然不能重写,但是可以被继承
    32. System.out.println("cal()方法");
    33. }

    5)一般来说,如果一个类已经是final类了,就没有必要再将方法修饰成final方法。
    6) final不能修饰构造方法(即构造器)
    7) final和static往往搭配使用,效率更高,不会导致类加载.底层编译器做了优化处理。

    1. class Demo{
    2. public static final int i=16; //
    3. static{
    4. System.out.println(“学习~");
    5. }}

    8)包装类(Integer,Double,Float,Boolean等都是final),String也是final类。

    8.6 抽象类

    8.6.1 抽象类快速入门

    当父类的一些方法不能确定时,可以用abstract关键字来修饰该方法,这个方法就是抽象方法,用abstract来修饰该类就是抽象类。
    我们看看如何把Animal做成抽象类,并让子类Cat类实现。

    1. abstract class Animal{
    2. String name;
    3. int age;
    4. abstract public void cry();
    5. }

    8.6.2 抽象类的介绍

    1) 用abstract关键字来修饰一个类时,这个类就叫抽象类
            访问修饰符  abstract 类名 {
            }
    2) 用abstract关键字来修饰一个方法时,这个方法就是抽象方法
         访问修饰符 abstract 返回类型 方法名 (参数列表);  //没有方法体
    3) 抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类()
    4) 抽象类,    是考官比较爱问的知识点,在框架和设计模式使用较多

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

    1) 抽象类不能被实例化
    2) 抽象类不一定要包含abstract方法。也就是说,抽象类可以没有abstract方法
    3) 一旦类包含了abstract方法,则这个类必须声明为abstract
    4) abstract 只能修饰类和方法,不能修饰属性和其它的。
    5) 抽象类可以有任意成员【抽象类本质还是类】,比如: 非抽象方法、构造器、静态属性等等
    6) 抽象方法不能有主体,即不能实现.如下所示
                                      abstract void aaa(){};   是错误的!!!
    7) 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,
         除非它自己也声明为abstract类。
    8) 抽象方法不能使用private、final和static来修饰,因为这些关键字都是和重写相违背的。

    8.7 接口

    8.7.1 基本介绍

    接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,在根据具体情况把这些方法写出来。语法:
            interface 接口名 {
                    //属性
                    //抽象方法
            }
            class 类名 implements 接口 {
                    自己属性;
                    自己方法;
                    必须实现的接口的抽象方法
            }
    小结:接口是更加抽象的抽象的类,抽象类里的方法可以有方法体,接口里的所有方法都没有方法体【jdk7.0】。接口体现了程序设计的多态和高内聚低偶合的设计思想。
    特别说明:Jdk8.0后 接口类可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现

    8.7.2 注意事项和细节

    1) 接口不能被实例化
    2) 接口中所有的方法是 public 方法,接口中抽象方法,可以不用 abstract 修饰:
             void aaa();
            实际上是 abstract void aa(); 
    3) 一个普通类实现接口,就必须将该接口的所有方法都实现。
    4) 抽象类实现接口,可以不用实现接口的方法。
    5) 一个类同时可以实现多个接口
    6) 接口中的属性,只能是 final 的,而且是 public static final修饰符。
       比如:int a=1;实际上是 public static final int a=1;(必须初始化)
    7) 接口中属性的访问形式:接口名.属性名
    8) 接口不能继承其它的类,但是可以继承多个别的接口
        interface  A extends B,C{ }
    9) 接口的修饰符只能是 public和默认,这点和类的修饰符是一样的。

    8.7.3 实现接口vs继承类

    接口和继承解决的问题不同
        继承的价值主要在于: 解决代码的复用性和可维护性。
        接口的价值主要在于: 设计,设计好各种规范(方法),让其它类去实现这些方法。即更加的灵活..
    接口比继承更加灵活
        接口比继承更加灵活,继承是满足is- a的关系,而接口只需满足like - a的关系。
    接口在一定程度  上实现代码解耦[即:接口规范性+动态绑定机制]

    8.8 内部类

    如果定义类在局部位置(方法中/代码块):(1) 局部内部类 (2) 匿名内部类
    定义在成员位置 (1) 成员内部类 (2) 静态内部类

    8.8.1 基本介绍

    一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)。是我们类的第五大成员【思考:类的五大成员是哪些?[属性、方法、构造器、代码块、内部类]】,内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系,注意:内部类是学习的难点,同时也是重点,后面看底层源码时,有大量的内部类.

    8.8.2 基本语法

    1. class Outer{//外部类
    2. class Inner{
    3. //内部类
    4. }}
    5. class Other{//外部其他类
    6. }

    8.8.3 内部类的分类

    定义在外部类局部位置上(比如方法内):
    1)局部内部类((有类名)
    2)匿名内部类(没有类名,重点!!!!!!!!)

    定义在外部类的成员位置上:
    1)成员内部类(没用static修饰)
    2)静态内部类(使用static修饰)

    8.8.4 局部内部类的使用

    说明:局部内部类是定义在外部类的局部位置,比如方法中,并且有类名。
    1.可以直接访问外部类的所有成员,包含私有的
    2.不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用
            修饰符的。但是可以使用final修饰,因为局部变量也可以使用final
    3.作用域:仅仅在定义它的方法或代码块中。
    4.局部内部类 ---访问---->外部类的成员[访问方式:直接访问]
    5.外部类---访问---->局部内部类的成员
    访问方式:创建对象,再访问(注意:必须在作用域内)
            记住:(1)局部内部类定义在方法中/代码块
                    (2)作用域在方法体或者代码块中
                    (3)本质仍然是一个类
    6.外部其他类---不能访问----->局部内部类(因为局部内部类地位是一个局部变量)
    7.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
    System.out.println("外部类的n2=”+外部类名.this.n2);

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

     (1)本质是类  (2)内部类  (3)该类没有名字  (4)同时还是一个对象
    说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名
    1. 匿名内部类的基本语法
            new 类或接口 (参数列表){
                    类体
            };
    2. 匿名内部类的语法比较奇特,请大家注意,因为匿名内部类既是一个类的定义同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征,对前面代码分析可以看出这个特点,因此可以调用匿名内部类方法。
    3. 可以直接访问外部类的所有成员,包含私有的
    4. 不能添加访问修饰符,因为它的地位就是一个局部变量。
    5. 作用域:仅仅在定义它的方法或代码块中
    6. 匿名内部类---访问---->外部类成员[访问方式:直接访问]
    7. 外部其他类---不能访问----->匿名内部类(因为匿名内部类地位是一个局部变量)
    8. 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
    代码:

    1. package com.hspedu.innerclass;
    2. public class AnonymousInnerClassDetail {
    3. public static void main(String[] args) {
    4. Outer05 outer05 = new Outer05();
    5. outer05.f1();
    6. //外部其他类---不能访问----->匿名内部类
    7. System.out.println("main outer05 hashcode=" + outer05);
    8. }
    9. }
    10. class Outer05 {
    11. private int n1 = 99;
    12. public void f1() {
    13. //创建一个基于类的匿名内部类
    14. //不能添加访问修饰符,因为它的地位就是一个局部变量
    15. //作用域 : 仅仅在定义它的方法或代码块中
    16. Person p = new Person(){
    17. private int n1 = 88;
    18. @Override
    19. public void hi() {
    20. //可以直接访问外部类的所有成员,包含私有的
    21. //如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,
    22. //默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员)去访问
    23. System.out.println("匿名内部类重写了 hi 方法 n1=" +n1 +
    24. " 外部内的n1="+Outer05.this.n1 );
    25. //Outer05.this 就是调用 f1 的 对象
    26. System.out.println("Outer05.this hashcode=" + Outer05.this);
    27. }
    28. };
    29. p.hi();//动态绑定, 运行类型是 Outer05$1
    30. //也可以直接调用, 匿名内部类本身也是返回对象
    31. // class 匿名内部类 extends Person {}
    32. }
    33. new Person(){
    34. @Override
    35. public void hi() {
    36. System.out.println("匿名内部类重写了 hi 方法,哈哈...");
    37. }
    38. @Override
    39. public void ok(String str) {
    40. super.ok(str);
    41. }
    42. }.ok("jack");
    43. }
    44. class Person {//类
    45. public void hi() {
    46. System.out.println("Person hi()");
    47. }
    48. public void ok(String str) {
    49. System.out.println("Personok()"+str);
    50. }
    51. }
    52. //抽象类/接口...

    第九章枚举和注解

    9.1 先看一个需求

    要求创建季节(Season)对象,请设计并完成
            classSeason{  //类
                    private  String  name;
                    private  String  desc;  //描述
                    //构造器
                    //getXX
                    //setXX
            }

    1. publicstaticvoidmain(String[]args){
    2. // //使用
    3. // Seasonspring=newSeason("春天","温暖");
    4. // Seasonwinter=newSeason("冬天","寒冷");
    5. // Seasonsummer=newSeason("夏天","炎热");
    6. // Seasonautumn=newSeason("秋天","凉爽");
    7. autumn.setName("XXX");
    8. autumn.setDesc("非常的热..");
    9. //因为对于季节而已,他的对象(具体值),是固定的四个,不会有更多
    10. //安老师的这个设计类的思路,不能体现季节是固定的四个对象
    11. //因此,这样的设计不好===> 枚举类[枚: 一个一个 举: 例举 , 即把具体的对象一个一个例举出来的类
    12. // 就称为枚举类]
    13. Season other = new Season("红天", "~~~");

    9.2 枚举简介

    1) 枚举对应英文(enumeration, 简写 enum)
    2) 枚举是一组常量的集合。
    3) 可以这里理解:枚举属于一种特殊的类,里面只包含一组有限的特定的对象。

    9.3 枚举的二种实现方式

    1) 自定义类实现枚举
    2) 使用enum 关键字实现枚举

    9.3.1 自定义类实现枚举

    1. 不需要提供setXxx方法,因为枚举对象值通常为只读;
    2. 对枚举对象/属性使用 final + static 共同修饰,实现底层优化;
    3. 枚举对象名通常使用全部大写 , 常量的命名规范;
    4. 枚举对象根据需要,也可以有多个属性。
     

    1. package com.hspedu.enum_;
    2. public class Enumeration02 {
    3. public static void main(String[] args) {
    4. System.out.println(Season.AUTUMN);
    5. System.out.println(Season.SPRING);
    6. }}
    7. //演示字定义枚举实现
    8. class Season {//类
    9. private String name;
    10. private String desc;//描述
    11. //定义了四个对象, 固定.
    12. public static final Season SPRING = new Season("春天", "温暖");
    13. public static final Season WINTER = new Season("冬天", "寒冷");
    14. public static final Season AUTUMN = new Season("秋天", "凉爽");
    15. public static final Season SUMMER = new Season("夏天", "炎热");
    16. //1. 将构造器私有化,目的防止 直接 new
    17. //2. 去掉setXxx 方法, 防止属性被修改
    18. //3. 在 Season 内部,直接创建固定的对象
    19. //4. 优化,可以加入 final 修饰符
    20. private Season(String name, String desc) {
    21. this.name = name;
    22. this.desc = desc;
    23. }
    24. public String getName() {
    25. return name;
    26. }
    27. public String getDesc() {
    28. return desc;
    29. }
    30. @Override
    31. public String toString() {
    32. return "Season{" +
    33. "name='" + name + '\' +
    34. ", desc='" + desc + '\' +
    35. '}';
    36. }}

    9.3.2 自定义类实现枚举

    进行自定义类实现枚举,有如下特点:

    1)构造器私有化
    2)本类内部创建一组对象[四个春夏秋冬]
    3)对外暴露对象(通过为对象添加publicfinalstatic修饰符)
    4)可以提供get方法,但是不要提供set

    9.3.3  enum关键字实现枚举

    1. packagecom.hspedu.enum_;
    2. publicclassEnumeration03{
    3. publicstaticvoidmain(String[]args){
    4. System.out.println(Season2.AUTUMN);
    5. System.out.println(Season2.SUMMER);
    6. }}
    7. //演示使用enum关键字来实现枚举类
    8. enum Season2{//类
    9. //定义了四个对象, 固定.
    10. //public static final Season SPRING = new Season("春天", "温暖");
    11. //public static final Season WINTER = new Season("冬天", "寒冷");
    12. // public static final Season AUTUMN = new Season("秋天", "凉爽");
    13. //public static final Season SUMMER = new Season("夏天", "炎热");
    14. //如果使用了enum 来实现枚举类
    15. //1. 使用关键字 enum 替代 class
    16. //2. public static final Season SPRING = new Season("春天", "温暖") 直接使用
    17. //SPRING("春天", "温暖") 解读 常量名(实参列表)
    18. //3. 如果有多个常量(对象), 使用 ,号间隔即可
    19. //4. 如果使用enum 来实现枚举,要求将定义常量对象,写在前面
    20. //5. 如果我们使用的是无参构造器,创建常量对象,则可以省略 ()
    21. SPRING("春天", "温暖"),WINTER("冬天", "寒冷"),AUTUMN("秋天", "凉爽"),
    22. SUMMER("夏天", "炎热")/*,What()*/;
    23. private String name;
    24. private String desc;//描述
    25. private Season2() {//无参构造器
    26. }
    27. private Season2(String name, String desc) {
    28. this.name = name;
    29. this.desc = desc;
    30. }
    31. publicStringgetName(){
    32. returnname;
    33. }
    34. publicStringgetDesc(){
    35. returndesc;
    36. }
    37. @Override
    38. publicStringtoString(){
    39. return"Season{"+
    40. "name='"+name+'\''+
    41. ",desc='"+desc+'\''+
    42. '}';
    43. } }

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

    1) 当我们使用enum关键字开发一个枚举类时,默认会继承Enum类,而且是一个final类;
    2) 传统的public static  final  Season2  SPRING = new  Season2  ("春天","温暖");
        简化成SPRING("春天","温暖"),这里必 须知道,它调用的是哪个构造器;
    3) 如果使用无参构造器创建枚举对象,则实参列表和小括号都可以省;
    4) 当有多个枚举对象时,使用,间隔,最后有一个分号结尾;
    5) 枚举对象必须放在枚举类的行首。

    说明:使用关键字enum时,会隐式继承Enum类, 这样我们就可以使用Enum类相关的方法。

    9.4 enum实现接口

    1)  使用enum关键字后,就不能再继承其它类了,因为enum会隐式继承Enum,而Java是单继承机制。
    2)  枚举类和普通类一样,可以实现接口,如下形式。 enum类名implements接口1,接口2{ }

    9.5 注解的理解

    1) 注解(Annotation)也被称为元数据(Metadata),用于修饰解释 包、类、方法、属性、构造器、局部变量等数据信息。
    2) 和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息。
    3) 在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE中注解占据了更重要的角 色,例如用来配置应用程序的任何切面,代替javaEE旧版中所遗留的繁冗代码和XML配置等。

    9.6 基本的 Annotation 介绍

    使用 Annotation 时要在其前面增加 @ 符号, 并把该 Annotation 当成一个修饰符使用。用于修饰它支持的程序元素

    三个基本的 Annotation:
    1) @Override: 限定某个方法,是重写父类方法, 该注解只能用于方法
    2) @Deprecated: 用于表示某个程序元素(类, 方法等)已过时
    3) @SuppressWarnings: 抑制编译器警告

    9.6.1  @Override 注解的案例

    1. packagecom.hspedu.annotation_;
    2. publicclassOverride_{
    3. publicstaticvoidmain(String[]args){
    4. }}
    5. classFather{//父类
    6. publicvoidfly(){
    7. System.out.println("Fatherfly...");
    8. }
    9. publicvoidsay(){}
    10. }
    11. class Son extends Father {//子类
    12. //1. @Override 注解放在 fly 方法上,表示子类的fly方法时重写了父类的fly
    13. //2. 这里如果没有写 @Override 还是重写了父类fly
    14. //3. 如果你写了@Override 注解,编译器就会去检查该方法是否真的重写了父类的
    15. 方法,如果的确重写了,则编译通过,如果没有构成重写,则编译错误
    16. //4. 看看 @Override 的定义
    17. /*
    18. */
    19. 解读: 如果发现 @interface 表示一个 注解类
    20. @Target(ElementType.METHOD)
    21. @Retention(RetentionPolicy.SOURCE)
    22. public @interface Override {
    23. }
    24. @Override
    25. //说明
    26. public void fly() {
    27. System.out.println("Son fly....");
    28. }
    29. @Override
    30. public void say() {}
    31. }

    Override使用说明
    1.@Override表示指定重写父类的方法(从编译层面验证),如果父类没有fly方法,则会报错
    2.如果不写@Override注解,而父类仍有public void fly00,仍然构成重写
    3.@Override只能修饰方法,不能修饰其它类,包,属性等等
    4.查看@Override注解源码为@Target(ElementType.METHOD),说明只能修饰
    方法
    5.@Target是修饰注解的注解,称为元注解,记住这个概念.

    9.6.2 @Deprecated注解的案例

    1. //1.@Deprecated修饰某个元素,表示该元素已经过时
    2. //2.即不在推荐使用,但是仍然可以使用
    3. //3.查看@Deprecated注解类的源码
    4. //4. 可以修饰方法,类,字段, 包, 参数 等等
    5. //5. @Deprecated 可以做版本升级过渡使
    6. /*
    7. @Documented
    8. @Retention(RetentionPolicy.RUNTIME)
    9. @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER,TYPE})
    10. public @interface Deprecated {
    11. }
    12. */
    13. @Deprecated
    14. class A{
    15. @Deprecated
    16. public int n1 = 10;
    17. @Deprecated
    18. public void hi(){
    19. }

    9.6.3 @SuppressWarnings 注解的案例

    @SuppressWarnings: 抑制编译器警告

    1. /1. 当我们不希望看到这些警告的时候,可以使用 SuppressWarnings注解来抑制警告信息
    2. //2. 在{""} 中,可以写入你希望抑制(不显示)警告信息
    3. //3. 可以指定的警告类型有
    4. all,抑制所有警告
    5. boxing,抑制与封装/拆装作业相关的警告
    6. //cast,抑制与强制转型作业相关的警告
    7. //dep-ann,抑制与淘汰注释相关的警告
    8. //deprecation,抑制与淘汰的相关警告
    9. //fallthrough,抑制与 switch 陈述式中遗漏 break 相关的警告
    10. //finally,抑制与未传回finally 区块相关的警告
    11. //hiding,抑制与隐藏变数的区域变数相关的警告
    12. //incomplete-switch,抑制与 switch 陈述式(enum case)中遗漏项目相关的警告
    13. //javadoc,抑制与 javadoc 相关的警告
    14. //nls,抑制与非nls 字串文字相关的警告
    15. //null,抑制与空值分析相关的警告
    16. //rawtypes,抑制与使用raw类型相关的警告
    17. //resource,抑制与使用 Closeable 类型的资源相关的警告
    18. //restriction,抑制与使用不建议或禁止参照相关的警告
    19. //serial,抑制与可序列化的类别遗漏serialVersionUID 栏位相关的警告
    20. //static-access,抑制与静态存取不正确相关的警告
    21. //static-method,抑制与可能宣告为 static 的方法相关的警告
    22. //super,抑制与置换方法相关但不含super呼叫的警告
    23. //synthetic-access,抑制与内部类别的存取未最佳化相关的警告
    24. //sync-override,抑制因为置换同步方法而遗漏同步化的警告
    25. //unchecked,抑制与未检查的作业相关的警告
    26. //unqualified-field-access,抑制与栏位存取不合格相关的警告
    27. //unused,抑制与未用的程式码及停用的程式码相关的警告
    28. //4. 关于SuppressWarnings 作用范围是和你放置的位置相关
    29. //5.
    30. /*
    31. 比如 @SuppressWarnings 放置在 main方法,那么抑制警告的范围就是 main
    32. 通常我们可以放置具体的语句, 方法, 类.
    33. 看看 @SuppressWarnings 源码
    34. //(1) 放置的位置就是 TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE
    35. //(2) 该注解类有数组 String[]values() 设置一个数组比如 {"rawtypes", "unchecked", "unused"}
    36. @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    37. @Retention(RetentionPolicy.SOURCE)
    38. public @interface SuppressWarnings {
    39. String[] value();
    40. */

    @SuppressWarnings注解的案例
    说明各种值
    1)  unchecked是忽略没有检查的警告
    2)  rawtypes是忽略没有指定泛型的警告(传参时没有指定泛型的警告错误)
    3)  unused是忽略没有使用某个变量的警告错误
    4)  @SuppressWarnings可以修饰的程序元素为,查看@Target
    5) 生成@SupperssWarnings时,不用背,直接点击左侧的黄色提示,就可以选择(注意可以指定生成的位置)

    9.7 JDK 的元 Annotation(元注解, 了解)

    9.7.1 元注解的基本介绍

    JDK 的元 Annotation 用于修饰其他 Annotation
    元注解: 本身作用不大,讲这个原因希望大家看源码时,可以知道他是干什么的

    9.7.2 元注解的种类 (使用不多,了解, 不用深入研究)

    1) Retention   //指定注解的作用范围,三种 SOURCE,CLASS,RUNTIME
    2) Target   // 指定注解可以在哪些地方使用
    3) Documented   //指定该注解是否会在javadoc体现
    4) Inherited   //子类会继承父类注解

    9.7.3  @Retention 注解

    说明:
    只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 可以保留多长时间,@Rentention 包含一个 RetentionPolicy 类型的成员变量, 使用 @Rentention 时必须为该 value 成员变量指定值:
    @Retention 的三种值
    1)  RetentionPolicy.SOURCE: 编译器使用后,直接丢弃这种策略的注释
    2)  RetentionPolicy.CLASS: 编译器将把注解记录在 class 文件中. 当运行 Java 程序时,JVM 不会保留注解。这是默认 值。
    3)  RetentionPolicy.RUNTIME:编译器将把注解记录在 class 文件中. 当运行 Java 程序时,JVM 会保留注解. 程序可以 通过反射获取该注解。

    第十章异常-Exception

    10.1 异常介绍

    基本概念
    Java语言中,将程序执行中发生的不正常情况称为“异常”。(开发过程中的语法错误和逻辑错误不是异常)
    执行过程中所发生的异常事件可分为两大类
    1)Error(错误):Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError[栈溢出]和OOM(out of memory). Error是严重错误,程序会崩溃。
    2) Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等,Exception分为两大类:运行时异常[程序运行时,发生的异常]和编译时异常[编程时,编译器检查出的异常]。

    10.2 异常体系图一览

    10.2.1 异常体系图

    10.2.2 异常体系图的小结

    1. 异常分为两大类,运行时异常和编译时异常.
    2. 运行时异常,编译器检查不出来。一般是指编程时的逻辑错误,是程序员应该避免其出现的异常。java.lang.RuntimeException类及它的子类都是运行时异常
    3. 对于运行时异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响
    4. 编译时异常,是编译器要求必须处置的异常。

    10.3 常见的运行时异常

    10.3.1 常见的运行时异常包括

    1)  NullPointerException 空指针异常:当应用程序试图在需要对象的地方使用 null 时,抛出该异常

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

    3)  ArrayIndexOutOfBoundsException 数组下标越界异常:用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引

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

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

    10.4 编译异常

    10.4.1 介绍

    编译异常是指在编译期间,就必须处理的异常,否则代码不能通过编译。

    10.4.2 常见的编译异常

    SQLException  //操作数据库时,查询表可能发生异常
    IOException  //操作文件时,发生的异常
    FileNotFoundException  //当操作一个不存在的文件时,发生异常
    ClassNotFoundException  //加载类,而该类不存在时,异常
    EOFException  //操作文件,到文件未尾,发生异常
    IllegalArguementException  //参数异常

    10.5 异常处理

    10.5.1 基本介绍

    异常处理就是当异常发生时,对异常处理的方式。

    10.5.2 异常处理的方式

    1) try-catch-finally
    程序员在代码中捕获发生的异常,自行处理
    2) throws
    将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM

    10.5.3 示意图

    10.6  try-catch 异常处理

    10.6.1 try-catch 方式处理异常说明

    1) Java提供try和catch块来处理异常。try块用于包含可能出错的代码。catch块用于处理try块中发生的异常。可以根据需要在程序中有多个try...catch块。
    2)基本语法
            try {
                    //可疑代码
                    //将异常生成对应的异常对象,传递给catch块
            } catch(异常) {
                    //对异常的处理
            }   
            //如果没有finally,语法是可以通过

    1. 如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块
    2. 如果异常没有发生,则顺序执行try的代码块,不会进入到catch
    3. 如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用如下代码-finally
    4. 可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如(Exception在后,NullPointerException在前),如果发生异常,只会匹配一个catch。
    5. 可以进行try-finally配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉/退出。应用场景,就是执行一段代码,不管是否发生异常,都必须执行某个业务逻辑

    10.6.2 try-catch-finally 执行顺序小结

    1)如果没有出现异常,则执行try块中所有语句,不执行catch块中语句,如果有finally,最后还需要执行finally里面的语句
    2)如果出现异常,则try块中异常发生后,try块剩下的语句不再执行。将执行catch块中的语句,如果有finally,最后还需要执行finally里面的语句!

    10.7 throws 异常处理

    10.7.1 基本介绍

    1)如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。
    2)在方法声明中用throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。

    10.7.2 注意事项和使用细节

    1) 对于编译异常,程序中必须处理,比如try-catch或者throws
    2) 对于运行时异常,程序中如果没有处理,默认就是throws的方式处理
    3) 子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型
    4) 在throws 过程中,如果有方法 try-catch,就相当于处理异常,就可以不必throws
    代码:
     

    1. packagecom.hspedu.throws_;
    2. importjava.io.FileInputStream;
    3. importjava.io.FileNotFoundException;
    4. publicclassThrowsDetail{
    5. publicstaticvoidmain(String[]args){
    6. f2();
    7. }
    8. publicstaticvoidf2()/*throwsArithmeticException*/{
    9. //1.对于编译异常,程序中必须处理,比如try-catch或者throws
    10. //2.对于运行时异常,程序中如果没有处理,默认就是throws的方式处理
    11. intn1=10;
    12. intn2=0;
    13. doubleres=n1/n2;}
    14. public static void f1() throws FileNotFoundException {
    15. //这里大家思考问题 调用f3() 报错
    16. //1. 因为f3() 方法抛出的是一个编译异常
    17. //2. 即这时,就要f1() 必须处理这个编译异常
    18. //3. 在 f1() 中,要么 try-catch-finally ,或者继续 throws 这个编译异常
    19. f3(); // 抛出异常
    20. }
    21. public static void f3() throws FileNotFoundException {
    22. FileInputStream fis = new FileInputStream("d://aa.txt");
    23. }
    24. public static void f4() {
    25. //1. 在 f4()中调用方法f5() 是OK
    26. //2. 原因是f5() 抛出的是运行异常
    27. f5();
    28. }
    29. //3. 而 java 中,并不要求程序员显示处理,因为有默认处理机制
    30. public static void f5() throws ArithmeticException {
    31. }}
    32. class Father { //父类
    33. public void method() throws RuntimeException {
    34. }
    35. }
    36. class Son extends Father {//子类
    37. //3. 子类重写父类的方法时,对抛出异常的规定:子类重写的方法,
    38. //所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常类型的子类型
    39. //4. 在 throws 过程中,如果有方法 try-catch, 就相当于处理异常,就可以不必throws
    40. @Override
    41. public void method() throws ArithmeticException {
    42. }}

    10.8 自定义异常

    10.8.1 基本概念

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

    10.8.2 自定义异常的步骤

    1) 定义类:自定义异常类名(程序员自己写)继承Exception或RuntimeException
    2) 如果继承Exception,属于编译异常
    3) 如果继承RuntimeException,属于运行异常 (一般来说,继承RuntimeException)

    10.9 throw 和 throws 的区别

    10.9.1 一览表

    第十一章常用类

    11.1 包装类

    11.1.1 包装类的分类

    1) 针对八种基本数据类型相应的引用类型—包装类
    2) 有了类的特点,就可以调用类中的方法。

    11.1.2 包装类和基本数据的转换

    1) jdk5前的手动装箱和拆箱方式,  装箱:基本类型->包装类型,反之,拆箱
    2) jdk5 以后(含jdk5)的自动装箱和拆箱方式
    3) 自动装箱底层调用的是valueOf方法,比如Integer.valueOf()
    4) 其它包装类的用法类似,不一一举例

    11.2 String类

    11.2.1 String类的理解和创建对象

    11.2.2 创建String对象的两种方式

    1)方式一:直接赋值  String s ="xueixi";
    2)方式二:调用构造器   String s = new String("xuexi");

    11.2.3 两种创建String对象的区别

    1.方式一:先从常量池查看是否有"xuexi"数据空间,如果有,直接指向;如果没有则重新创建,然后指向。S最终指向的是常量池的空间地址
    2.方式二:先在堆中创建空间,里面维护了value属性,指向常量池的xuexi空间。如果常量池没有"xuexi",重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址。
    3.画出两种方式的内存分布图
     

    11.3 字符串的特性

    11.3.1 说明

    1) String是一个final类,代表不可变的字符序列
    2)字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的
            1.以下语句创建了几个对象?画出内存布局图。
                    String s1 = "hello";
                    s1="haha"; //1min 
                    //创建了2个对象.

    11.4 String 类的常见方法

    11.4.1 说明

    String类是保存字符串常量的。每次更新都需要重新开辟空间,效率较低,因此java设计者还提供了StringBuilder和 StringBuffer来增强String的功能,并提高效率。
                    //看看这段代码
                    String s = new String("");
                    for( int i = o; i< 80000; i++){
                    s += "hello";  }

    11.4.2 String类的常见方法一览

    1. equals  //区分大小写,判断内容是否相等
    2. equalslgnoreCase //忽略大小写的判断内容是否相等
    3. length //获取字符的个数,字符串的长度
    4. indexOf //获取字符在字符串中第1次出现的索引,索引从0开始,如果找不到,返回-1
    5. lastIndexOf  //获取字符在字符串中最后1次出现的索引,索引从0开始,如找不到,返回-1
    6. substring  //截取指定范围的子串
    7. trim //去前后空格
    8. charAt:获取某索引处的字符,注意不能使用Str[index]这种方式.

    11.5 StringBuffer 类

    11.5.1 基本介绍

        java.lang.StringBuffer代表可变的字符序列,可以对字符串内容进行增删。很多方法与String相同,但StringBuffer是可变长度的。
       StringBuffer是一个容器。
    1. StringBuffer的直接父类是AbstractStringBuilder 
    2. StringBuffer实现了Serializable,即StringBuffer的对象可以串行化
    3. 在父类中AbstractStringBuilder有属性char[]value,不是final   该value数组存放字符串内容,引出存放在堆中的
    4. StringBuffer是一个final类,不能被继承
    5. 因为StringBuffer字符内容是存在char[]value,所有在变化(增加/删除)   不用每次都更换地址(即不是每次创建新对象),所以效率高于Strin

    11.5.2 String VS StringBuffer

    1)  String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上就是更改地址,效率较低
    2)  StringBuffer保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新实际上可以更新内容,不用每次更新地址,效率较高

    11.5.3 String和StringBuffer相互转换

    1. //看String——>StringBuffer
    2. Stringstr="hellotom";
    3. //方式1使用构造器
    4. //注意:返回的才是StringBuffer对象,对str本身没有影响
    5. StringBufferstringBuffer=newStringBuffer(str);
    6. //方式2使用的是append方法
    7. StringBufferstringBuffer1=newStringBuffer();
    8. stringBuffer1=stringBuffer1.append(str);
    9. //看看StringBuffer->String
    10. StringBufferstringBuffer3=newStringBuffer("韩顺平教育");
    11. //方式1使用StringBuffer提供的toString方法
    12. Strings=stringBuffer3.toString();
    13. //方式2:使用构造器来搞定
    14. Strings1=newString(stringBuffer3);

    11.6 StringBuilder类

    11.6.1 基本介绍

    1) 一个可变的字符序列。此类提供一个与StringBuffer 兼容的 API,但不保证同步(StringBuilder 不是线程安全)。该类被设计用作 StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer要快。
    2) 在 StringBuilder 上的主要操作是append和 insert方法,可重载这些方法,以接受任意类型的数据。

    11.6.2  StringBuilder常用方法

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

    1.StringBuilder是final
    2.继承了AbstractStringBuilder,属性char[ ] value,内容存到value
    3.实现Serializable接口,序列化(所谓序列化即可以保存类型和数据

    1. StringBuilder 继承 AbstractStringBuilder 类
    2. 实现了 Serializable ,说明 StringBuilder 对象是可以串行化(对象可以网络传输,可以保存到文件)
    3. StringBuilder 是 final 类, 不能被继承
    4. StringBuilder 对象字符序列仍然是存放在其父类 AbstractStringBuilder 的 char[] value; 因此,字符序列是堆中
    5. StringBuilder 的方法,没有做互斥的处理,即没有synchronized 关键字,因此在单线程的情况下使用  StringBuilder

    11.6.3  String、StringBuffer 和 StringBuilder 的比较

    1)  StringBuilder 和 StringBuffer非常类似,均代表可变的字符序列,而且方法也一样
    2)  String:不可变字符序列,效率低,但是复用率高。
    3)  StringBuffer:可变字符序列、效率较高(增删)、线程安全,看源码
    4)  StringBuilder:可变字符序列、效率最高、线程不安全
    5)  String使用注意说明:
            string s="a";  //创建了一个字符串
            s +="b";  //实际上原来的"a"字符串对象已经丢弃了,现在又产生了一个字符串s+"b”(也就               是"ab")。如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降
            低效率。如果这样的操作放到循环中,会极大影响程序的性能
            结论:如果我们对String做大量修改,不要使用String

    11.6.4 String、StringBuffer 和 StringBuilder 的选择

    使用的原则,结论:
    1. 如果字符串存在大量的修改操作,一般使用StringBuffer 或StringBuilder
    2. 如果字符串存在大量的修改操作,并在单线程的情况,使用 StringBuilder
    3. 如果字符串存在大量的修改操作,并在多线程的情况,使用 StringBuffer
    4. 如果我们字符串很少修改,被多个对象引用,使用String,比如配置信息等
            StringBuilder的方法使用和StringBuffer 一样,不再说.

    11.7 Math 类

    11.7.1 基本介绍

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

    11.7.2 方法一览(均为静态方法)

    11.8 Arrays类

    Arrays里面包含了一系列静态方法,用于管理或操作数组(比如排序和搜索)
    1)  toString返回数组的字符串形式
            Arrays.toString(arr)
    2)  sort 排序(自然排序和定制排序)  Integer arr[] = {1,-1,7,0,89 };
    3) binarySearch 通过二分搜索法进行查找,要求必须排好序int index =Arrays.binarySearch(arr,3);
    4) copyOf数组元素的复制
            Integerl] newArr = Arrays.copyOf(arr, arr.length);
    5) fil数组元素的填充
            Integer[] num = new Integer[]{9.3.21};  Arrays.fill(num,99);
    6) equals比较两个数组元素内容是否完全一致  boolean equals = Arrays.equals(arr, arr2);
    7)  asList将一组值,转换成list
            List asList = Arrays.asList(2,3,4.5.6,1);
            System.out.println("asList=" + asList);

    具体情况请分析源码

    11.9 System类

    11.9.1  System类常见方法

    1)  exit 退出当前程序
    2)  arraycopy :复制数组元素,比较适合底层调用,一般使用Arrays.copyOf完成复制数组.
            int[] src = {1,2,33 };
            int[ dest = new int[3];
            System.arraycopy(src, 0, dest, 0. 3);
    3)  currentTimeMillens:返回当前时间距离1970-1-1的毫秒数
    4)  gc:运行垃圾回收机制 System.gc ( );

    11.10 BigInteger和BigDecimal类

    11.10.1  BigInteger和BigDecimal介绍

    应用场景:
    1)  Biglnteger适合保存比较大的整型
    2)  BigDecimal适合保存精度更高的浮点型(小数)

    常见方法:

    1) add 加        2) subtract 减        3) multiply 乘        4) divide 除

    还有 日期类 可了解

    第 十二 章集合

    12.1 集合的理解和好处

    前面我们保存多个数据使用的是数组,那么数组有不足的地方,我们分析一下

    12.1.1  数组

    1) 长度开始时必须指定,而且一旦指定,不能更改
    2) 保存的必须为同一类型的元素
    3) 使用数组进行增加/删除元素的示意代码-比较麻烦
            写出Person数组扩容示意代码。
            Person[ ] pers = new Person[1]; //大小是1
            per[0]=new Person();
            //增加新的Person对象?
            Person[ll pers2 = new Person[pers.length+1];//新创建数组
            for( ) { }  //拷贝pers数组的元素到pers2
            pers2[pers2.length-1]=new Person(); //添加新的对象

    12.1.2 集合

    1) 可以动态保存任意多个对象,使用比较方便!
    2) 提供了一系列方便的操作对象的方法:add,remove、set、get等
    3) 使用集合添加,删除新元素的示意代码-简洁了

    12.2  集合的框架体系

    Java 的集合类很多,主要分为两大类

    1.  集合主要是两组(单列集合 , 双列集合)
    2.  Collection 接口有两个重要的子接口 ListSet, 他们的实现子类都是单列集合
    3.  Map 接口的实现子类 是双列集合,存放的 K-V

    12. 3 Collection 接口和常用方法

    12.3.1 Collection 接口实现类的特点

    public interface Collection extends Iterable
    1) collection实现子类可以存放多个元素,每个元素可以是Object
    2) 有些Collection的实现类,可以存放重复的元素,有些不可以
    3) 有些Collection的实现类,有些是有序的(List),有些不是有序(Set)
    4) Collection接口没有直接的实现子类,是通过它的子接口Set 和 List来实现的

    Collection接口遍历元素方式
            1-使用Iterator(迭代器)
            2-for循环增强

    12.4 List接口和常用方法

    12.4.1 List接口基本介绍

    List 接口是collection接口的子接口
    1)  List集合类中元素有序(即添加顺序和取出顺序一致)、且可重复
    2)  List集合中的每个元素都有其对应的顺序索引,即支持索引。
    3)  List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。

    12.4.2  List的三种遍历方式

    1)方式一:使用iterator
                    lterator iter = col.iterator();
                    while(iter.hasNext0){
                    Object o = iter.next();  }
    2)方式二: 使用增强 for
                    for(Object o:col){ }
    3)方式三: 使用普通for
                    for(int i=0;i                 object object = list.get(i);
                    System.out.println(object); }
    说明:使用LinkedList完成使用方式和ArrayList一样

    12.5 ArrayList底层结构和源码分析

    12.5.1  ArrayList的注意事项

    1)permits all elements, including null , ArrayList可以加入null,并且多个
    2) ArrayList是由数组来实现数据存储的
    3)ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高)看源码.在多线程情况下,不建议使用ArrayList

    12.5.2 ArrayList的底层操作机制源码分析(重点,难点.)

    1) ArrayList中维护了一个0bject类型的数组elementData. [debug看源码]
            transient Object[] elementData;   //transient表示瞬间,短暂的,表示该属性不会被序列号
    2) 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加, 则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
    3) 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。
    建议:自己去debug一把我们的ArrayList的创建和扩容的流程.

    12.6  Vector 底层结构和源码剖析

    12.6.1  Vector 的基本介绍

    1) Vector类的定义说明
            public class vector
            extends AbstractList
            implements List,RandomAccess,Cloneable,Serializable
    2) Vector底层也是一个对象数组,protected object[] elementData;
    3) Vector是线程同步的,即线程安全, Vector类的操作方法带有synchronizec
            public synchronized E get(int index){
            if (index >= elementCount)
            throw new ArraylndexOutOfBoundsException(index);
            return elementData(index); }
    4) 在开发中,需要线程同步安全时,考虑使用Vector

    12.6.2 Vector和ArrayList的比较

    12.7  LinkedList 底层结构

    12.7.1  LinkedList 的全面说明

    1) LinkedList底层实现了双向链表和双端队列特点
    2) 可以添加任意元素(元素可以重复),包括null
    3) 线程不安全,没有实现同步

    12.7.2 LinkedList 的底层操作机制

    1) LinkedList底层维护了一个双向链表.
    2) LinkedList中维护了两个属性first和last分别指向首节点和尾节点
    3) 每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表.
    4) 所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。
    5) 模拟一个简单的双向链表
     

    12.8 ArrayList 和 LinkedList 比较

    12.8.1 ArrayList 和 LinkedList 的比较

    如何选择ArrayList和LinkedList:
    1. 如果我们改查的操作多,选择ArrayList
    2. 如果我们增删的操作多,选择LinkedList
    3)一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList
    4)在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList,另外一个模块是LinkedList,也就是说,要根据业务来进行选择

    12.9 Set 接口和常用方法

    12.9.1  Set 接口基本介绍

    1)无序(添加和取出的顺序不一致),没有索引
    2)不允许重复元素,所以最多包含一个null

    12.9.2 Set接口的常用方法

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

    12.9.3  Set接口的遍历方式

    同Collection的遍历方式一样,因为Set接口是Collection接口的子接口。
    1. 可以使用迭代器
    2. 增强for
    3. 不能使用索引的方式来获取.

    12.10 Set 接口实现类-HashSet

    12.10.1 HashSet 的全面说明

    1) HashSet实现了Set接口
    2) HashSet实际上是HashMap,看下源码.
            public Hashset( ) { 
                    map = new HashMap<>( ); }
    3) 可以存放null值,但是只能有一个null
    4) HashSet不保证元素是有序的,取决于hash后,再确定索引的结果.(即,不保证存放元素的顺序和取出顺序一致)
    5) 不能有重复元素/对象.

    12.11 Map 接口和常用方法

    12.11.1 Map 接口实现类的特点 [很实用]

    注意:这里讲的是JDK8的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
    8) Map存放数据的key-value示意图,一对k-v是放在一个HashMap$Node中的,有因为Node 实现了Entry 接口,有些书上也说一对k-v就是一个Entry(如图)

    12.11.2  Map 接口遍历方法

    Map遍历的示意图(比List,和Set复杂点,但是基本原理一样)
     Map遍历方式案例演示
    1. containsKey:查找键是否存在
    2. keySet:获取所有的键
    3. entrySet:获取所有关系k-v
    4. values:获取所有的值

    12.11.3 HashMap 小结

    1) Map接口的常用实现类:HashMap、Hashtable和Properties。
    2) HashMap是 Map接口使用频率最高的实现类。
    3) HashMap 是以 key-val对的方式来存储数据(HashMap$Node类型)
    4) key不能重复,但是值可以重复,允许使用null键和null值。
    5) 如果添加相同的key,则会覆盖原来的key-val ,等同于修改.(key不会替换,val会替换)
    6) 与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的.(jdk8的hashMap底层数组+链表+红黑树)
    7) HashMap没有实现同步,因此是线程不安全的,方法没有做同步互斥的操作,没有synchronized

    12.12 Map接口实现类-Hashtable

    12.12.1 HashTable的基本介绍

    1. 存放的元素是键值对:即K-V
    2. hashtable的键和值都不能为null,否则会抛出NullPointerException
    3. hashTable使用方法基本上和HashMap一样
    4. hashTable是线程安全的(synchronized), hashMap是线程不安全的
    5. 简单看下底层结构

    12.12.2 Hashtable 和 HashMap 对比

    12.13  Map 接口实现类-Properties

    12.13.1  基本介绍

    1. Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存数据。
    2. 他的使用特点和Hashtable类似
    3. Properties还可以用于从 xxox.properties文件中,加载数据到Properties类对象,并进行读取和修改

    12.14 总结-开发中如何选择集合实现类(记住)

    在开发中,选择什么集合实现类,主要取决于业务操作特点,然后根据集合实现类特性进行选择,分析如下:
    1. 先判断存储的类型(一组对象[单列或一组键值对[双列])
    2. 一组对象[单列]:Collection接口
            允许重复:List
                    增删多: LinkedList[底层维护了一个双向链表]
                    改查多:ArrayList[底层维护Object类型的可变数组]
            不允许重复:Set
                    无序:HashSet [底层是HashMap,维护了一个哈希表即(数组+链表+红黑树)]
                    排序:TreeSet[老韩举例说明]
                    插入和职出顺序一致:LinkedHashSet,维护数组+双向链表
    3. 一组键值对[双列]:Map
            键无序:HashMap [底层是:哈希表 jdkT:数组+链表,jdk8:数组+链表+红黑树]
            键排序:TreeMap
            键插入和取出顺序一致:LinkedHashMap
            读取文件Properties

    12.15 Collections工具类

    12.15.1 Collections工具类介绍

    1)  Collections是一个操作 Set、List 和 Map等集合的工具类
    2)  Collections中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作

    12.15.2 排序操作:(均为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处元素进行交换

    12.15.3 查找、替换

    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 对象的所有旧值

    第 十三 章泛型

    13.1 泛型的理解和好处

    13.1.1 泛型的好处

    1) 编译时,检查添加元素的类型,提高了安全性
    2) 减少了类型转换的次数,提高效率
            不使用泛型
                    Dog-加入->Object -取出-> Dog
                    //放入到ArrayList 会先转成Object,在取出时,还需要转换成Dog
            使用泛型
                    Dog -> Dog -> Dog
                    //放入时,和取出时,不需要类型转换,提高效率

    13.2 泛型介绍

    int a = 10;
    理解:泛(广泛)型(类型)=> Integer, String,Dog
    1)泛型又称参数化类型,是Jdk5.0出现的新特性,解决数据类型的安全性问题
    2)在类声明或实例化时只要指定好需要的具体的类型即可。
    3) Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮
    4)泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方
    法的返回值的类型,或者是参数类型。

    13.3 泛型的语法

    13.3.1 泛型的声明

            interface股和class类0
            //比如: List , ArrayList
    说明:
    1) 其中,T,K,V不代表值,而是表示类型。
    2) 任意字母都可以。常用T表示,是Type的缩写

    13.3.2 泛型的实例化

    要在类名后面指定类型参数的值(类型)。如:
    1) List strList = new ArrayList();
    2) lterator iterator = customers.iterator( );

    13.3.3 泛型使用的注意事项和细节

    1. interface List0 , public class HashSet{ }..等等
    说明:T,E只能是引用类型
    看看下面语句是否正确?:
            List list = new ArrayList0;//OK
            List list2 = new ArrayList0;//错误
    2. 在给泛型指定具体类型后,可以传入该类型或者其子类类型
    3.泛型使用形式
            List list1 = new ArrayList();
            List list2 = new ArrayList<>0;
    4. 如果我们这样写List list3 = new ArrayList(); 默认给它的泛型是[E就是Object ]

    13.4 自定义泛型

    13.4.1 自定义泛型类(难度)

    基本语法
    class类名{// ...表示可以有多个泛型
            成员  }
    注意细节
    1) 普通成员可以使用泛型(属性、方法)
    2) 使用泛型的数组,不能初始化
    3) 静态方法中不能使用类的泛型
    4) 泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)
    5) 如果在创建对象时,没有指定类型,默认为Object

    应用案例:

    1. class Tiger{
    2. String name;
    3. R r;
    4. M m;
    5. T t;
    6. }

    13.5  泛型的继承和通配符

    13.5.1 泛型的继承和通配符说明

    1) 泛型不具备继承性
            List list = new ArrayList0;//对吗?
    2) :支持任意泛型类型
    3) :支持A类以及A类的子类,规定了泛型的上限
    4) :支持A类以及A类的父类,不限于直接父类,规定了泛型的下限

  • 相关阅读:
    C++ 友元函数和友元类
    图解BM(Boyer-Moore)字符串匹配算法+代码实现
    循环神经网络的主要特点,循环神经网络应用举例
    COVID疫苗加强针来袭,是否该接种?
    3种方法,关闭win10的IPC共享,怎么关不掉?
    开始使用Filebeat
    配置自己的docker开发环境
    Java项目:SSM图书馆图书管理借阅书籍管理系统
    [CVE-2023-42442]JumpServer 会话录像文件未授权访问漏洞
    vue中的mixin(局部混入、全局混入)
  • 原文地址:https://blog.csdn.net/pythontxt/article/details/137940126