Java 语言基础 (类和对象, 方法和封装, static 关键字和继承, 多态和特殊类)

时间:2022-07-24
本文章向大家介绍Java 语言基础 (类和对象, 方法和封装, static 关键字和继承, 多态和特殊类),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

类和对象

面向对象 -- 指以属性和行为的观点区分析现实生活中的事物
面向对象编程
  1. 指以面向对象的思想进行分析, 然后使用面向对象的编程语言进行表达的过程
  2. 是软件产业化发展的需求
  3. 理解面向对象的思想 (封装, 继承, 多态)
  4. 至少掌握一种对应编程语言
    • C 面向过程语言
    • C++ 面向过程和面向对象语言
    • Java 面向对象语言
类和对象
  1. 对象主要指现实生活中客观存在的实体
    • 在 Java 语言中对象体现为内存空间中的一块存储区域
  2. 类是对具有相同特征和行为的多个对象共性的抽象描述
    • 描述特征/属性 -> 成员变量
    • 描述行为 -> 成员方法
    • 在 Java 语言中体现为一种引用数据类型
  3. 类用于构建对象的模板, 对象的数据结构由定义它的类来决定
类的定义
class MyClassName {
        DataType memberVariableName  = InitialValue;
        ReturnType memberMethodName(ParameterList) {
            MethodBody;
        }
}
  1. 命名规范
    • 多个单词时, 第二个单词起每个单词的首字母大写
    • 多个单词时, 第二个单词起每个单词的首字母大写
    • 多个单词时, 第二个单词起每个单词的首字母大写
    • 多个单词组成时, 要求每个单词首字母都要大写
    • 类名
    • 成员变量
    • 成员方法
    • 引用变量
  2. 成员变量的初始值
    • 基本数值类型 -> 0
    • boolean 类型 -> false
    • 引用类型 -> null
  3. 成员方法 -- 可以实现代码的重用, 简化代码
    • 返回值指从方法体内返回到方法体外的数据内容
    • 形参列表将方法体外的数据内容带入到方法体内
    • 方法体主要用于编写描述该方法功能的语句块
  4. 普通类不允许被声明为staticprivate, 只有内部类才可以
对象的创建
  MyClassName myName = new MyClassName();
  1. 使用 new 关键字来创建该类的对象, 这个过程叫做类的实例化
  2. 本质就是在内存空间的堆申请一块存储区域, 用于存放该对象的独有特征信息
引用的定义
  1. 语法格式 MyClassName myName = new MyClassName(); myName.memberVariableName = value;
  2. 使用引用数据类型定义的变量叫做引用型变量, 简称"引用"
  3. 引用变量主要用于记录对象在堆区中的内存地址信息
  4. 可以给引用类型赋值为 null, 表示不指向任何对象
    • Person p = null;
    • 此时如果通过引用访问成员变量或调用方法, 会产生空指针异常
  5. java 引用内存模型图示:
传参
  1. 参数分为形参和实参
    • 形参 -- 定义方法时的参数
    • 实参 -- 调用方法时传递的参数
  2. 调用方法时采用值传递把实参传递给形参,
    • 方法内部其实在使用形参
  3. 当参数是对象时, 传递的是对象的地址值
    • 对象的值为对象的地址
可变长参数

ReturnType methodName(DataType... args) {}

  1. 方法参数部分指定类型的参数个数是可以改变的, 为 0 ~ n
  2. 一个方法的形参列表最多只能声明一个可变长形参, 并且需要放到参数列表的末尾
变量作为方法的参数传递时
  1. 基本数据类型
    • 两个变量有各自独立的内存空间
    • 形参变量的数值改变通常不会影响到实参变量:
  2. 引用数据类型
    • 通常不会影响到实参变量指向内容的改变
    • 两个变量指向不同的内存空间
    • 两个变量指向同一块内存空间
    • 改变形参变量指向内容会影响到实参变量:
    • 若形参变量改变指向后再改变指定内容:
内存结构之栈区
  1. 栈用于存放程序运行过程当中所有的局部变量
  2. 一个运行的 Java 程序从开始到结束会有多次方法的调用
    • 该空间为该方法的栈帧, 对应一个调用中的方法
    • 栈帧存储了该方法的参数, 局部变量等数据
    • JVM 会为每个方法的调用分配一个对应的空间
    • 当某一个方法调用完成后,其对应的栈帧将被清除

方法和封装

递归 -- recursion
  1. 从最终态向前递推, 然后不断回溯
  2. 在方法体内部直接或间接调用当前方法自身的形式
  3. 注意事项
    • 必须有递归的规律以及退出条件
    • 必须使得问题简单化而不是复杂化
    • 若递归影响到程序的执行性能, 则使用递推取代之
递推 -- induction
  1. 正向递推 - forward induction
    • 从初始态出发, 不断改变自己
  2. 反向递推 - backward induction
    • 与正向逻辑相反, 类似递归
迭代 -- iteration
  1. 重复反馈过程的活动
  2. 目的是去逼近所需目标或结果
构造方法
    class MyClassName {
        MyClassName(ParameterList) {
            Constructor Body;
        }
    }
  1. 构造方法名与类名完全相同并且没有返回值类型
    • 编译器会自动添加一个无参空构造方法: Person() {}
    • 当类中没有定义任何构造方法, 使用默认构造方法
  2. 使用 new 关键字创建对象时会自动调用构造方法
    • 实现成员变量初始化工作
方法重载 -- Method Overloading
  1. 多个方法的方法名相同, 参数列表不同
    • 这样的方法之间构成重载关系
  2. 主要形式:
    • 参数的个数不同
    • 参数的类型不同
    • 参数的顺序不同
    • 与返回值类型和形参变量名无关
    • 建议返回值类型最好相同
  3. 判断方法能否构成重载的核心:
    • 调用方法时能否加以区分
  4. 实际意义
    • 调用各种不同的版本
    • 实现各种不同的功能
    • 调用者只需记住一个方法名就可以
this 关键字 -- 本质上就是当前类类型的引用变量
  1. 可以通过 "this." 的方式调用成员变量和成员方法
  2. 基本概念
    • 若在构造方法中出现, 则代表当前正在构造的对象
    • 若在成员方法中出现, 则代表当前正在调用的对象
  3. 工作原理
    • 在构造方法中和成员方法中访问成员变量时, 编译器会自动加上 this 的前缀
    • 当不同对象调用同一个方法时, 调用对象不同导致 this 不同, 从而 this 访问的结果也不同
  4. 使用方式
    • 在构造方法的第一行可以使用 this() 的方法, 调用本类的其他构造方法
    • 当局部变量名与成员变量名相同时, 在方法中会优先使用局部变量(就近原则)
    • 若希望使用成员变量, 则在成员变量前加上 this 前缀, 明确要求该变量是成员变量
    • this 关键字还可以作为方法的返回值
封装 -- encapsulation
  • 隐藏成员变量的细节以及保证成员变量数值的合理性
    • 对成员变量进行密封包装处理
    • 避免出现与现实不符合的数值
  • 实现流程
    • 私有化成员变量, 使用 private 关键字修饰
    • 提供公有的 getset 方法, 在方法中进行合理值的判断
    • 在构造方法中调用 set 方法进行合理值判断
  • 成员变量和方法什么修饰符都没有叫做默认访问权限
    • 级别介于 privatepublic 之间
JavaBean -- 一种 Java 语言写的可重用组件
  • 其它 Java 类可以通过反射机制, 来发现和操作这些 JavaBean 的属性
  • 本质上是符合以下标准的 Java 类
    • 类是公共的
    • 有一个无参的公共的构造器
    • 有属性,且有对应的 get, set 方法

static 关键字和继承

static 关键字
  1. 使用 static 修饰成员变量表示静态的含义
    • 此时成员变量由对象层级升级为类层级, 整个类只有一份并被所有对象共享
    • 该成员变量随着类的加载准备就绪, 与是否创建对象无关
  2. static 修饰的成员可以使用"引用."的方式访问, 但推荐"类名."的方式
  3. static 修饰内部类可以直接作为一个普通类来使用
  4. 使用方式
    • 开发中只有隶属类层级, 并被所有对象共享的内容, 才可以使用 static 关键字修饰
    • 构造方法不再初始化静态成员变量
    • 用静态成员方法访问静态成员变量
    • 不能使用 thissuper 关键字
    • 只能访问静态成员不能访问非静态成员
    • 因为此时对象可能还未被创建
    • 既能访问非静态成员又能访问静态成员
    • 静态成员被所有对象共享
    • 非静态成员方法
    • 静态成员方法
    • 静态成员变量
    • 不能滥用 static 关键字
final -- 可以修饰类, 成员方法以及成员变量
  1. 修饰类体现在该类不能被继承
    • 主要用于防止滥用继承, 如 java.lang.String
  2. 修饰成员方法体现在该方法不能被重写但可以被继承
    • 主要防止不经意间造成重写, 如 java.text.Dateformat 类中 format 方法
  3. 修饰成员变量体现在该变量必须初始化且不能改变
    • 主要防止不经意间造成改变, 如 java.lang.Thread 类中 MAX_PRIORITY
常量
  • 通常使用 public static final 关键字共同修饰成员变量
  • 命名规范:
    • 要求所有字母都要大写, 不同单词之间采用下划线连接:public static final double PI_CONSTANT = 3.14159
构造块和静态代码块
  • Initialization blocks:
    • Instance blocks / instance initializer
    • Static blocks / static initializer
  • 构造块:
    • 在类体中直接使用 {} 括起来的代码块
    • 每创建一个对象都会执行一次构造块
    • super() 后和目前对象构造方法前执行
    • 可以使用 this 访问成员
    • 用来初始化非静态成员变量, 可以执行非静态成员方法
  • 静态代码块:
    • 使用 static 关键字修饰的构造块
    • 随着类加载时执行一次
    • 在构造块之前执行
    • 不可以使用 thissuper 关键字
    • 用来初始化静态成员变量, 可以执行静态方法
构造块和静态代码块执行顺序
  1. 执行父类的静态代码块, 执行子类的静态代码块
  2. 执行父类的构造块, 执行父类的构造方法体
  3. 执行子类的构造块, 执行子类的构造方法体
Singleton -- 单例类,对外提供且只提供一个对象

三要素:

  • 私有化构造方法, 使用 private 关键字修饰
  • 指向自己实例的私有静态引用, 使用 private static 关键字共同修饰
  • 以自己实例为返回值的静态的公有方法, 使用 public static 关键字共同修饰
类图:
  1. 类图分三部分, 依次为 "类名, 属性, 方法"
  2. << 开头和以 >> 结尾的为注释
  3. 修饰符 + 代表 public, - 代表 private, # 代表 protected, 什么都没有代表包可见
  4. 带下划线的属性或方法代表是静态的
单例设计模式 -- 设计单例类的流程和思想

实现方式:

  • 饿汉模式 (立即加载, 线程安全, 推荐)
    • 类加载慢, 运行时获取对象快private static Singleton sin = new Singleton();
  • 懒汉模式 (延迟加载, 非线程安全)
    • 使用双重检验 (Double-Check Idiom), 保证单例提高运行效率, 必须使用 volatile
    • 使用私有静态内部类, 实现延迟加载和线程安全. 在同一个类加载器下, 一个类只会被初始化一次
    • 多线程环境下:
    • 类加载快, 运行时获取对象慢private static Singleton sin = null;
继承
  • 子类 -- subclass, 父类 -- parent class
  • 让多个类吸收公共类中已有特征和行为, 而在多个类型只需要编写自己独有特征和行为的机制
  • 使用 extends (扩展) 关键字来表示继承
    • public class Worker extends Person
    • Person 类叫超类, 父类, 基类
    • Worker 类叫派生类, 子类, 孩子类
  • 使用继承提高了代码复用性, 可维护性及扩展性, 是多态的前提条件
继承特点
  • 子类不能继承父类的构造方法和私有方法, 但私有成员变量可以被继承, 但不能访问
  • 无论使用何种方式构造子类的对象, 都会自动调用父类的无参构造方法, 来初始化从父类继承的成员变量, 相当于在构造方法第一行写 super().
  • 使用继承必须满足"子类 is a 父类"逻辑关系, 不能滥用继承
  • Java 只支持单继承不支持多继承
    • 一个子类只有一个父类
    • 一个父类可以有多个子类
方法重写 -- Overriding
  • @Override 注解, 若没有构成重写则编译报错
  • 从父类继承下来的方法不满足子类的需求时, 就需要在子类重新写一个和父类一样的方法来覆盖从父类继承下来的版本
方法重写的原则
  • 要求方法名相同, 参数列表相同以及返回值类型相同
    • 从 Java 5 开始允许返回子类类型
  • 要求方法的访问权限不能变小, 可以相同或变大
  • 要求方法不能抛出更大的异常 (异常机制)
访问控制符

修饰符

本类

同一个包中的类

子类

其他类

public

可以访问

可以访问

可以访问

可以访问

protected

可以访问

可以访问

可以访问

-

默认

可以访问

可以访问

-

-

private

可以访问

-

-

-

注意事项

  • public 修饰的成员可以在任意位置使用
  • private 修饰的成员只能在本类内部使用
  • 通常, 成员方法使用 public 关键字修饰, 成员变量使用 private 关键字修饰
包语句 -- package
  • 使用包的概念
    • 实现项目管理, 解决命名冲突以及权限控制的效果
  • 定义一个类时, 除了定义类的名称一般还要指定一个包名
    • package 包名;
    • package 包名1.包名2.包名3...包名n;
定义包的规范
  • org.apache.commons.lang.StringUtil
    • 模块名称信息: lang
    • 项目名称信息: commons
    • 公司或组织的信息: org.apache
    • 类名: StringUtil
    • 多层包名:
包的导入
  • 使用 import 关键字导入包
  • 使用 import 关键字导入静态成员
    • 从 Java 5.0 开始支持
    • import static java.lang.System.out
Java 开发的常用工具
  • 文本编辑器 (TE, Text Editor)
    • 记事本, Notepad++, Edit Plus, UltraEdit...
  • 集成开发环境 (IDE, Integrated Development Environment)
    • IntelliJ IDEA, Eclipse, MyEclipse, JBuilder...

多态和特殊类

多态 -- 同一种事物表现出来的多种形态
  • 比如, 人表现为学生, 教师, 工人, 保安...
  • 语法格式
ParentClass p = new ChildClass();
多态特点
  • 当父类类型引用指向子类类型的对象时, 父类类型的引用:
    • 可以直接调用父类独有的方法
    • 不可以直接调用子类独有的方法
  • 对于父子类都有的非静态方法来说
    • 编译阶段调用父类版本
    • 运行阶段调用子类重写的版本 (动态绑定)
  • 对于父子类都有的静态方法来说
    • 编译和运行阶段都调用父类版本
多态的实际意义
  • 屏蔽不同子类的差异性实现通用的编程带来不同的效果
多态使用场合
  • 通过参数传递形成多态
  • 直接在方法体中使用抽象类的引用指向子类类型的对象
开发经验分享
  • 推荐使用多态的格式, 此时父类类型引用直接调用的方法一定时父类拥有的方法, 以后更换子类时, 只需修改 new 关键字后面的子类类型, 而其它地方无需修改就可以立即生效. 提高了代码的可维护性和可扩展性.
  • 缺点: 父类引用不能直接调用子类独有的方法, 若调用则需要强制类型转换.
引用数据类型之间的转换
  • 必须发生在父子类之间, 否则编译报错
  • 自动类型转换
    • 小类型向大类型的转换: 子类转为父类, 叫做向上转型或隐式类型转换
  • 强制类型转换
    • if (引用变量 instanceof 数据类型)
    • 大类型向小类型的转换: 父类转为子类, 叫做向下转型或显式类型转换
    • 若目标类型并不是该引用真正指向的数据类型则编译通过, 运行阶段发生类型转换异常
    • 应该在强转前进行判断, 判断引用变量指向对象是否为后面的数据类型, 格式如下:
抽象方法
  • 格式如下
    • 访问权限 abstract 返回值类型 方法名(形参列表);
    • public abstract void cry();
  • 不能具体实现的方法并且使用 abstract 关键字修饰, 没有方法体
  • 以下关键字 和 abstract 关键字不能共同修饰一个方法
    • private
    • final
    • static
抽象类 -- public abstract class Account {}
  • final 关键字不能修饰抽象类
  • 不能具体实例化的类并且使用 abstract 关键字修饰, 不能创建对象
  • 当一个类继承抽象类后必须重写抽象方法, 否则该类也变成抽象类
  • 抽象类对子类具有强制性和规范性, 因此叫做模板设计模式
  • 实际意义: 不在于创建对象而在于被继承
抽象类和抽象方法的关系
  • 抽象类可以有成员变量, 构造方法, 成员方法
  • 抽象类可以没有抽象方法, 也可以有抽象方法
  • 拥有抽象方法的类必须是抽象类
  • 真正意义上的抽象类: 具有抽象方法并且使用 abstract 关键字修饰的类
接口 -- 一种比抽象类还抽象的类, 所有方法都为抽象类
  • 内部只能有常量: 默认为 public static final/*public static final*/ int CNT = 1;
  • 内部只能有抽象方法, Java 新特性除外 /*public abstract*/ void show();
  • Java 8 新特性允许默认方法和静态方法
    • 默认方法可以选择重写与否, default 关键字修饰
    • 静态方法不可以被重写
  • Java 9 新特性允许接口中出现私有方法
    • private void show();
    • private static void show();
    • 同样的, interface 的私有方法也不可以为 abstract
    • private 不可以修饰 default, 因为 default 可能会被实现类重写
    • 将私有方法写在接口中, 不让实现类看到, 有很好的安全性
  • 定义类的关键字为 class, 而定义接口的关键字为 interface
  • 类和接口之间的关系:

名称

关键字

关系

类和类的

extends

支持单继承

类和接口

implements

支持多实现

接口和接口

extends

支持多继承

抽象类和接口的主要区别
  • 定义抽象类的关键字是 abstract class, 而接口是 interface
  • 继承抽象类的关键字是 extends, 而实现接口的关键字是 implements
  • 继承抽象类支持单继承, 而实现接口支持多实现
  • 抽象类中可以有构造方法, 而接口不可以有构造方法
  • 抽象类可以有成员变量, 而接口只有常量
  • 抽象类可以有成员方法, 而接口:
    • 接口只有抽象方法 (Java 7)
    • 接口新增支持默认方法和静态方法 (Java 8 新特性)
    • 接口新增支持私有方法 (Java 9 新特性)
  • 抽象类中增加方法时子类可以不用重写,
    • 接口增加方法时实现类需要重写 (Java 8 之前)
    • 接口使用默认方法让实现类选择是否重写 (Java 8)

特殊类

普通类的内容:
  • 成员变量, 成员方法, 构造方法,
  • 静态成员, 构造块, 静态代码块,
  • 内部类
内部类 -- Inner Class
  • 一个类定义出现在另外一个类的类体中, 而这个内部类所在的类叫做外部类
  • 存在价值仅仅为某个类单独服务时, 可以将这个类定义为所服务的内部类
  • 隐藏该类的实现细节, 并且可以方便的访问外部类的私有成员, 而不再需要提供公有的 get 和 set 方法
内部类的分类
  • 普通内部类 -- Nested Inner Class
    • 直接将一个类的定义放在另外一个类的类体中
  • 静态内部类 -- Static Inner Class
    • 使用 static 关键字修饰的内部类, 隶属于类层级
  • 局部内部类 -- Method-local Inner Class
    • 直接将一个类的定义放在方法体的内部
  • 匿名内部类 -- Anonymous Inner Class
    • 指没有名字的内部类
普通(成员)内部类
访问修饰符 class 外部类的类名 {
    访问修饰符 class 内部类的类名 {
        内部类的类体;
    }
}
  • 使用方法: Outer.Inner innerObj = new Outer().new Inner();
    • 编译后: Outer$Inner.class
    • 和普通类一样可以定义成员变量, 成员方法以及构造方法等
    • 和普通类一样可以使用 finalabstract
    • 可以额外使用 privateprotected 进行修饰
    • 需要外部类对象来创建对象
    • 访问外部类中与本类内部同名的成员变量或方法时, 需要使用 this 关键字和"外部类名.this"的方式区分
静态内部类
访问修饰符 class 外部类的类名 {
    访问修饰符 static class 内部类的类名 {
        内部类的类体;
    }
}
  • 使用方式: StaticOuter.StaticInner staticInnerObj = new StaticOuter.StaticInner();
    • 编译后: StaticOuter$StaticInner.class
    • 不能直接访问外部类的非静态成员, 可以通过 new 外部类对象来访问非静态成员
    • 可以直接创建对象
    • 访问外部类中与本类内同名的成员变量或方法时, 需要使用"类名."的方式区分
局部(方法)内部类
访问修饰符 class 外部类的类名 {
    访问修饰符 返回值类型 成员方法名 (形参列表) {
        class 内部类的类名 {
            内部类的类体;
        }
    }
}
  • 使用方式: OuterClass outerObj = new OuterClass; outerObj.outerMethod(args);
    • 编译后: "OuterClass$1InnerClass.class"
    • 只能在该方法的内部使用
    • 可以在方法体内部直接创建对象
    • 不能使用访问控制符和 static 关键字修饰符
    • 可以使用外部方法的局部变量, 但必须是 final 的, 由局部内部类和局部变量的声明周期不同所致
匿名内部类
接口/父类类型 引用变量名 = new 接口/父类类型() {
    方法的重写;
}
  • 使用方式: MyInterface n = new MyInterface() { ... overridedMethod(...) { ... } }; n.overridedMethod(...);
    • 编译后: "MyInterface$1.class"
    • 可以实现接口或者继承父类
    • 类本身没有名字, 其引用对象可以有名字
    • 匿名对象加匿名内部类一起使用时, 编译后不会出现对应的字节码文件
    • 从 Java 8 开始提出新特性 Lambda 表达式可以简化
回调模式
  • 调用一个方法, 其参数是接口类型, 需要创建一个实现此接口类型的对象
    • 该方法在运行时会调用到参数对象所实现的方法
  • "接口/继承类"的引用作为方法形参时, 实参的传递方式:
    • 自定义类实现接口/继承类并重写方法, 然后创建该对象作为实参传递
    • 使用匿名内部类的语法格式得到"接口/继承类"的引用
枚举 -- Enumeration
  • 从 Java 5 开始增加的一种引用数据类型
  • 使用 public static final 表示的常量描述较为繁琐, 使用 enum 关键字来定义枚举类型取代常量
  • 枚举值就是当前类的类型, 也就是指向本类的对象, 默认使用 public static final 关键字共同修饰
    • 因此采用"枚举类型."的方式调用
  • 可以自定义构造方法, 但构造方法修饰符必须是 private
    • 默认也是 private
所有枚举类都自动继承 java.lang.Enum 类, 常用方法如下

常用方法

描述

static T[] values()

返回当前枚举类中的所有对象

String toString()

返回当前枚举类对象的名称

int ordinal()

获取枚举对象在枚举类的索引位置

static T

将参数指定的字符串名转为当前

valueOf(String str)

枚举类的对象

int compareTo(E o)

比较两个枚举对象在定义时的顺序

枚举类实现接口方式
  • 枚举类实现接口后需要重写抽象方法, 而重写方式有两种:
    • 重写一个. 跟普通类一样
    • 每个对象都重写. 利用了匿名内部类功能
  • 例子:
public enum DirectionEnum implements MyInterface {
    UP("上") {
        @Override
        ... overridedMethod(...) {
            ...
        }
    },
    DOWN("下") {...},
    LEFT("左") {...},
    RIGHT("右"){...};
    private final String desc;
    private DirectionEnum(String desc) {
        this.desc = desc;
    }
    public String getDesc() {
        return desc;
    }
    //@Override
    //... overridedMethod(...) {
    //    ...
    //}
}
注解 -- Annotation, 又叫标注
  • 从 Java 5 开始增加的一种引用数据类型
  • 本质上就是代码的特殊标记, 通过这些标记可以在编译, 类加载, 以及运行时执行指定的处理
注解语法格式
访问修饰符 @interface 注解名称 {
    注解成员;
}
  • 自定义注解自动继承 java.lang.annotation.Annotation 接口
  • 通过@注解名称的方式可以修饰包, 类, 成员方法, 成员变量, 构造方法, 参数, 局部变量的声明等
注解使用方式
  • 注解体中只有成员变量, 没有成员方法, 注解成员变量以"无形参的方法"形式来声明
    • 其方法名定义了该成员变量的名字
    • 其返回值定义了该成员变量的类型
  • 如果注解中没有任何成员, 则该注解叫做标记注解/标识注解
  • 如果注解只有一个参数成员, 建议使用参数名为 value, 而类型只能是:
    • 八种基本数据类型,
    • String 类型,
    • Class 类型(泛型, 如: Class<?>Class<T>),
    • enum 类型,
    • Annotation 类型.
  • 注解不支持继承
public @interface MyAnnotation {
    public String value() default "123";
    public String value2();
}
@MyAnnotation(value = "hello", value2 = "456") 
public class Person {
    ...
}
元注解 -- meta-annotation. 可以注解到注解上的注解
  • 元注解是一种基本注解, 但它能够应用到其它注解上
  • 元注解主要有: @Retention, @Documented, @Target, @Inherited, @Repeatable
元注解 @Retention -- 用于说明该注解的生命周期
  • RententionPolicy.SOURCE 只在源码阶段保留, 在编译器进行编译时它将被丢弃忽视
  • RententionPolicy.CLASS 保留到编译进行的时候, 不会被加载到 JVM, 默认方式
  • RententionPolicy.RUNTIME 保留到程序运行的时候, 会被加载到 JVM 中, 程序运行时可以获取
元注解 @Documented -- 注解将被 javadoc 工具提取进文档
  • javadoc 工具从程序源代码中抽取类, 成员等注释, 形成一个和源代码配套的 API 帮助文档, 而该工具抽取时不包括注解本身
  • 必须设置 Retention 值为 RUNTIME
元注解 @Target -- 指定能用于哪些元素的修饰

元注解 @Target 的参数类型枚举值

描述

ElementType.ANNOTATION_TYPE

可以给一个注解进行注解

ElementType.CONSTRUCTOR

可以给构造方法进行注解

ElementType.FIELD

可以给属性进行注解

ElementType.LOCAL_VARIABLE

可以给局部变量进行注解

ElementType.METHOD

可以给方法进行注解

ElementType.PACKAGE

可以给包进行注解

ElementType.PARAMETER

可以给方法内的参数进行注解

ElementType.TYPE

可以给类型进行注解, 如类

  • 从 Java 8 开始 @Target 的参数类型枚举值增加两个:

元注解 @Target 的参数类型枚举值

描述

ElementType.TYPE_PARAMETER

能写在类型变量的声明语句中, 如泛型

ElementType.TYPE_USE

能标注任何类型名称. Use of a type.

元注解 @Inherited -- 子类继承超类的注解
  • 注解本身不可以继承
  • 如果一个超类被该注解标记过的注解进行注解时, 并且子类没有任何注解应用时, 则子类就继承超类的注解
元注解 @Repeatable -- 表示自然可重复的含义
  • 从 Java 8 开始增加的新特性
常见的预制注解
  • 是 Java 语言自身提供的注解, 具体如下:

预制注解

描述

@author

表明类模块的作者, 多个作者用逗号隔开

@version

表明该类模块的版本

@see

参考转向, 也就是相关主题

@since

从哪个版本开始增加的

@param

对方法中某参数的说明, 如果没有参数就不能写

@return

对方法返回值的说明, 类型为 void 就不能写

@Override

限定重写父类方法, 该注解只能用于方法

@exception

对方法可能抛出的异常进行说明

@Deprecated

用于表示所修饰的元素(类, 方法)等已过时

@SuppressWarnings

抑制编译器警告

常见异常
  • IllegalArugumentException 非法参数异常
  • ClassCastException 类型转换异常
  • NullPointException 空指针异常
  • ArithmeticException 算术异常
  • ArrayIndexOutOfBoundsException 数组下标越界异常