1 内部类
基本概念
当一个类的定义出现在另一个类的类体中时,这个类叫做内部类,而所在类叫做外部类 (只为某一个类服务)
类中的内容
成员变量,成员方法,构造方法,静态成员,构造块和静态代码块,内部类
实际作用
一个类的存在价值仅仅是为某一个类单独服务时, 可以将这个类定义为内部类,隐藏细节, 方便访问外部类的私有成员而不用再提供公有的get/set方法
分类:
普通:直接定义在另一个类中 静态:用static修饰, 隶属于类层级 局部: 放在方法体内部时 匿名: 没有名字的内部类
2 普通(成员)内部类
格式
访问修饰符 class 外部类名 { 访问修饰符 class 内部类的类名 { 内部类的类体; } }
使用方式
和普通类一样可以定义成员变量,成员方法,以及构造方法等 和普通类一样可以使用 final 或者 abstract 修饰 可以使用 private 或 protected 关键字进行修饰 需要使用外部类对象来创建对象
NormalOuter no = new NormalOuter(); //声明NormalOuter类中内部类的引用指向内部类的对象 NormalOuter.NormalInner ni = no.new NormalInner(); //该内部类隶属于对象层级,构造时需要用引用.的方式去构造
访问外部类中与本类内部同名的成员变量或方法时,需要使用 this 关键字(考点,参见代码)
System.out.println("内部类中cnt = " + this.cnt); //3 //下面需要使用外部类的this,代表外部类的一个对象, 不用this,就需要把外部类的cnt提升到类层级,即static修饰 System.out.println("外部类中cnt = " + NormalOuter.this.cnt); //1
代码: 编程实现,普通内部类的定义和使用
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 11:51
* 编程实现,普通内部类的定义和使用 -文档注释
*/
public class NormalOuter {
private int cnt = 1;
//定义普通内部类隶属于外部类的成员,并且是对象层级
//和普通类基本没区别,但内部类只为当前外部类服务,因此需要权限修饰符应该写成private
//以后会使用多个内部类,内部类之间也可以继承,故final有存在意义
/*private*/public /*final*/ class NormalInner {
private int ia = 2;
private int cnt = 3;
public NormalInner() {
System.out.println("普通内部类的构造方法执行到了!");
}
public void show() {
System.out.println("外部类中变量cnt的数值为:" + cnt); //1
System.out.println("ia = " + ia); //2
}
public void show2(int cnt) {
System.out.println("形参变量cnt = " + cnt); //局部优先原则
System.out.println("内部类中cnt = " + this.cnt); //3
//下面需要使用外部类的this,代表外部类的一个对象, 不用this,就需要把外部类的cnt提升到类层级,即static修饰
System.out.println("外部类中cnt = " + NormalOuter.this.cnt); //1
}
}
}
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 11:56
*/
public class NormalOuterTest {
public static void main(String[] args) {
//声明NormalOuter类型的引用,指向该类的对象
NormalOuter no = new NormalOuter();
//声明NormalOuter类中内部类的引用指向内部类的对象
NormalOuter.NormalInner ni = no.new NormalInner(); //该内部类隶属于对象层级,构造时需要用引用.的方式去构造
//调用内部类中的show方法
ni.show();
System.out.println("------------------------------------------------------");
ni.show2(4);
}
}
3 静态内部类
格式
访问修饰符 class 外部类的类名 { 访问修饰符 static class 内部类类名 { 内部类类体; } } (也会生成class文件,并且命名为 外部类$内部类)
使用方式
不能直接访问外部类的非静态成员
可以直接创建对象
外类.内类 引用 = new 外类.内类(); 如果静态内部类访问外部类中与本类内同名的成员变量方法时,需要使用类名.访问
System.out.println("内部类中snt = " + StaticInner.snt); //4 类层级 System.out.println("外部类中snt = " + StaticOuter.snt); //2 类层级
代码: 实现静态内部类的定义和使用
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 12:12
* 实现静态内部类的定义和使用
*/
public class StaticOuter {
private int cnt = 1; //隶属于对象层级
private static int snt = 2; //隶属于类层级
public /*static*/ void show() {
System.out.println("外部类中的show方法!");
}
/**
* 定义静态内部类,有static修饰的属于类层级
*/
public static class StaticInner { //静态,隶属于类层级, 外类.内类 引用 = new 外类.内类();
private int ia = 3;
private static int snt = 4;
public StaticInner() {
System.out.println("静态内部类的构造方法哦!");
}
public void show() {
System.out.println("ia = " + ia); //3
System.out.println("外部类中的snt = " + snt); //2 都是静态,可以直接访问
//System.out.println("外部类的cnt = " + cnt); //Error:静态上下文不能访问非静态成员,此时可能还未创建对象
}
public void show2(int snt) { //就近原则
System.out.println("snt = " + snt); //5
System.out.println("内部类中snt = " + StaticInner.snt); //4 类层级
System.out.println("外部类中snt = " + StaticOuter.snt); //2 类层级
//StaticOuter.show(); //需要把show方法变成静态方法
new StaticOuter().show(); //对象层级, new一个对象.的方式调用
}
}
}
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 12:19
*/
public class StaticOuterTest {
public static void main(String[] args) {
//1.声明StaticInner类型的引用指向该类型的对象
// 此例子中内部类用static修饰,已提升至类层级,不需要new外类对象
StaticOuter.StaticInner si = new StaticOuter.StaticInner();
//2.调用show方法进行测试
si.show();
System.out.println("------------------------------------------------");
si.show2(5);
}
}
4 局部内部类
格式
访问修饰符 class 外部类的类名 { 访问修饰符 返回值类型 成员方法名(形参列表) { class 内部类 类名 { 内部类的类体 } } }
使用方式
只能在方法的内部使用 可以在方法体内部直接创建对象 不能使用访问控制符和static关键字修饰符 可以使用外部方法的局部变量, 但是必须是final的. (由局部内部类和局部变量的声明周期不同所致)
代码: 编程实现局部内部类的定义和使用
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 13:00
* 编程实现局部内部类的定义和使用
*/
public class AreaOuter {
private int cnt = 1;
public void show() {
//定义一个局部变量进行测试,从Java8开始默认理解为final修饰的变量
//虽然可以省略final,但是建议加上,提高代码可读性
int ic = 4; //使用中不改值则默认final, 一旦改值则说明编译器理解错,报错
//定义局部内部类,只在当前方法体的内部好使 拷贝一份拿到内部类里面
/*public*/ class AreaInner { //参考局部变量,不需要写权限修饰符
private int ia = 2;
public AreaInner() {
System.out.println("局部内部类的构造方法!");
}
public void test() {
System.out.println("ia = " + ia); //2
System.out.println("cnt = " + cnt); //1
//ic = 5; //必须理解为final或者写为final
System.out.println("ic = " + ic); //4 可以使用外部的局部变量,但是默认final,值不可改变
}
}
//声明局部内部类的引用指向局部内部类的对象
AreaInner ai = new AreaInner();
ai.test();
}
}
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 13:06
*/
public class AreaOuterTest {
public static void main(String[] args) {
//1.声明外部类类型的引用指向外部类的对象
AreaOuter ao = new AreaOuter();
//2.通过show方法的调用实现局部内部类的对象
ao.show();
}
}
5 回调模式
概念
如果一个方法的参数是接口类型, 则在调用该方法时, 需要创建并传递一个实现此接口类型的对象; 而该方法在运行时会调用到参数对象中所实现的方法(接口中定义的)
6 匿名内部类
语法格式(重点)
接口/父类类型 引用变量名 = new 接口/父类类型() {方法的重写} 接口/父类类型 引用变量名 = () -> {};
代码: 回调模式的概念和编程
代码: 匿名内部类的使用
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 13:35
* 回调模式的概念和编程1
*/
public interface AnonymousInterface {
//自定义抽象方法
public abstract void show();
}
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 13:37
* 回调模式的概念和编程2
* 匿名内部类的使用
*/
public class AnonymousInterfaceTest {
//1.//假设已有下面的方法请问如何调用下面的方法
//4.//接口类型的引用指向实现类的对象,形成了多态
//3.//AnonymousInterface ai = new AnonymousInterfaceImpl();
public static void test(AnonymousInterface ai) { //需要编写实现类将参数实例化,并且用多态的方式传参
ai.show(); //5.//编译阶段调用父类版本,运行调用实现类中的版本
}
public static void main(String[] args) {
//AnonymousInterfaceTest.test(new AnonymousInterface()); //2.//Error:接口不能实例化
//下面传入的参数 ai = new AnonymousInterfaceImpl();
AnonymousInterfaceTest.test(new AnonymousInterfaceImpl()); //6.//只被调用一次,一直存在浪费内存空间
System.out.println("------------------------------------------------------------");
//7.//使用匿名内部类的语法格式来得到接口类型的引用,格式为: 接口/父类类型 引用变量名 = new 接口/父类类型() {方法的重写};
AnonymousInterface ait = new AnonymousInterface() /*public class AnonymousInterfaceImpl implements AnonymousInterface*/ {
@Override //8.//匿名,因此删掉上面的名字
public void show() {
System.out.println/*("这里是接口的实现类")*/("匿名内部类就是这样的");
}
};
//9.从Java8开始提出新特性lamda表达式可以简化上述代码, 格式为(参数列表) -> {方法体}
AnonymousInterface ait2 = () -> System.out.println/*("这里是接口的实现类")*/("lamda表达式是这样的");
AnonymousInterfaceTest.test(ait2);
}
}
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 13:46
* 回调模式的概念和编程3
*/
public class AnonymousInterfaceImpl implements AnonymousInterface{
@Override
public void show() {
System.out.println("这里是接口的实现类");
}
}
7 枚举类
基本概念
取值只有几个明确的固定值,描述这种对象时,可以把所有的值一一列举出来
定义
使用 public static final 表示的常量描述较为繁琐, 使用 enum 关键字来定义枚举类型取代常量, 枚举类型是从Java5开始增加的一种引用数据类型 枚举值就是当前类的类型,也就是指向本类的对象, 默认用 public static final 关键字共同修饰, 因此采用枚举类型.的方式调用 枚举类型中可以自定义构造方法,也可以不写, 写的话,必须用 private 修饰,不加默认私有
8 Enum类的概念和方法
所有的枚举类都默认继承自java.lang.Enum类,常用方法如下 static T[] values() 返回当前枚举类中的所有对象 String toString() 返回当前枚举类对象的名称 int ordinal() 获取枚举类对象在枚举类中的索引位置 static T valueOf(String str) 将参数指定的字符串名转为当前枚举类的对象 int compareTo(E o) 比较两个枚举类对象在定义时的顺序
9 Enum类实现接口的方式
实现接口后需要重写抽象方法,方式有两种,重写一个或者每个都重写
代码: 枚举类的概念和自定义实现
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 14:39
* 编程实现所有方向的枚举,所有方向: 向上,向下,向左,向右
* 枚举类的概念和自定义实现1
*/
public class Direction {
private final String desc; //1.//用于描述方向字符串的成员变量
//5.//声明本类类型的引用指向本类类型的对象,每个需要描述的都要声明
//用public修饰为了外类可以调用,static提升至类层级,不用mew对象,final修饰不能改变,共同修饰则变成常量,要大写
public static final Direction UP = new Direction("向上");
public static final Direction DOWN = new Direction("向下");
public static final Direction LEFT = new Direction("向左");
public static final Direction RIGHT = new Direction("向右");
//2.//通过构造方法实现成员变量的初始化,更加灵活
//4.//私有化构造方法,此时该构造方法只能在本类的内部使用,参考单例设计模式
private Direction(String desc) {
this.desc = desc;
}
//3.//通过公有的get方法可以在本类的外部访问该类成员变量的数值
public String getDesc() {
return desc;
}
}
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 14:44
* 枚举类的概念和自定义实现2
* 枚举类型的定义2
*/
public class DirectionTest {
public static void main(String[] args) {
/*2.// //1.//声明Direction类型的引用指向该类型的对象并打印特征
Direction d1 = new Direction("向上");
System.out.println("获取到的字符串是:" + d1.getDesc()); //向上
Direction d2 = new Direction("向下");
System.out.println("获取到的字符串是:" + d1.getDesc()); //向下
Direction d3 = new Direction("向左");
System.out.println("获取到的字符串是:" + d1.getDesc()); //向左
Direction d4 = new Direction("向右");
System.out.println("获取到的字符串是:" + d1.getDesc()); //向右
System.out.println("---------------------------------------------------");
Direction d5 = new Direction("向前");
System.out.println("获取到的字符串是:" + d1.getDesc()); //向前*/
//Direction.UP = 2; //3.//类型不匹配
/* Direction d2 = null;
Direction.UP = d2; //4.//final修饰的值不能改变
*/
Direction d1 = Direction.UP;
System.out.println("获取到的方向是:" + d1.getDesc());
System.out.println("---------------------------------------------------");
//使用一下Java5开始的枚举类型
DirectionEnum de = DirectionEnum.DOWN;
System.out.println("获取到的方向是:" + de.getDesc());
}
}
代码: 枚举类型的定义
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 14:39
* 编程实现所有方向的枚举,所有方向: 向上,向下,向左,向右 //6.//枚举类型要求所有枚举值必须放在枚举类型的最前面
* 枚举类型的定义1
* Enum类实现接口的方式2
*/
public enum DirectionEnum implements DirectionInterface{ //枚举类不能继承其他类,但可以实现接口
//7.//匿名内部类的语法格式 接口/父类类型 引用变量名 = new 接口/父类类型() {方法的重写}
// public static final DirectionEnum UP = new DirectionEnum("向上") {方法的重写} ;
UP("向上"){
@Override
public void show() {
System.out.println("贪吃蛇向上移动了一下");
}
},DOWN("向下"){
@Override
public void show() {
System.out.println("贪吃蛇向下移动了一下");
}
},LEFT("向左"){
@Override
public void show() {
System.out.println("贪吃蛇向左移动了一下");
}
},RIGHT("向右"){
@Override
public void show() {
System.out.println("贪吃蛇向右移动了一下");
}
};
private final String desc; //1.//用于描述方向字符串的成员变量
//5.//声明本类类型的引用指向本类类型的对象,每个需要描述的都要声明
//用public修饰为了外类可以调用,static提升至类层级,不用mew对象,final修饰不能改变,共同修饰则变成常量,要大写
/* public static final DirectionEnum UP = new DirectionEnum("向上");
public static final DirectionEnum DOWN = new DirectionEnum("向下");
public static final DirectionEnum LEFT = new DirectionEnum("向左");
public static final DirectionEnum RIGHT = new DirectionEnum("向右");*/
//2.//通过构造方法实现成员变量的初始化,更加灵活
//4.//私有化构造方法,此时该构造方法只能在本类的内部使用,参考单例设计模式
private DirectionEnum(String desc) {
this.desc = desc;
}
//3.//通过公有的get方法可以在本类的外部访问该类成员变量的数值
public String getDesc() {
return desc;
}
//6.//整个枚举类型只重写一次,所有对象调用同一个
/*@Override
public void show() {
System.out.println("现在可以实现接口中抽象方法的重写了!");
}*/
}
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 14:44
* 枚举类的概念和自定义实现2
* 枚举类型的定义2
*/
public class DirectionTest {
public static void main(String[] args) {
/*2.// //1.//声明Direction类型的引用指向该类型的对象并打印特征
Direction d1 = new Direction("向上");
System.out.println("获取到的字符串是:" + d1.getDesc()); //向上
Direction d2 = new Direction("向下");
System.out.println("获取到的字符串是:" + d1.getDesc()); //向下
Direction d3 = new Direction("向左");
System.out.println("获取到的字符串是:" + d1.getDesc()); //向左
Direction d4 = new Direction("向右");
System.out.println("获取到的字符串是:" + d1.getDesc()); //向右
System.out.println("---------------------------------------------------");
Direction d5 = new Direction("向前");
System.out.println("获取到的字符串是:" + d1.getDesc()); //向前*/
//Direction.UP = 2; //3.//类型不匹配
/* Direction d2 = null;
Direction.UP = d2; //4.//final修饰的值不能改变
*/
Direction d1 = Direction.UP;
System.out.println("获取到的方向是:" + d1.getDesc());
System.out.println("---------------------------------------------------");
//使用一下Java5开始的枚举类型
DirectionEnum de = DirectionEnum.DOWN;
System.out.println("获取到的方向是:" + de.getDesc());
}
}
代码: Enum类实现接口的方式
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 16:47
* Enum类实现接口的方式1
*/
public interface DirectionInterface {
//自定义抽象方法
public abstract void show();
}
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 14:39
* 编程实现所有方向的枚举,所有方向: 向上,向下,向左,向右 //6.//枚举类型要求所有枚举值必须放在枚举类型的最前面
* 枚举类型的定义1
* Enum类实现接口的方式2
*/
public enum DirectionEnum implements DirectionInterface{ //枚举类不能继承其他类,但可以实现接口
//7.//匿名内部类的语法格式 接口/父类类型 引用变量名 = new 接口/父类类型() {方法的重写}
// public static final DirectionEnum UP = new DirectionEnum("向上") {方法的重写} ;
UP("向上"){
@Override
public void show() {
System.out.println("贪吃蛇向上移动了一下");
}
},DOWN("向下"){
@Override
public void show() {
System.out.println("贪吃蛇向下移动了一下");
}
},LEFT("向左"){
@Override
public void show() {
System.out.println("贪吃蛇向左移动了一下");
}
},RIGHT("向右"){
@Override
public void show() {
System.out.println("贪吃蛇向右移动了一下");
}
};
private final String desc; //1.//用于描述方向字符串的成员变量
//5.//声明本类类型的引用指向本类类型的对象,每个需要描述的都要声明
//用public修饰为了外类可以调用,static提升至类层级,不用mew对象,final修饰不能改变,共同修饰则变成常量,要大写
/* public static final DirectionEnum UP = new DirectionEnum("向上");
public static final DirectionEnum DOWN = new DirectionEnum("向下");
public static final DirectionEnum LEFT = new DirectionEnum("向左");
public static final DirectionEnum RIGHT = new DirectionEnum("向右");*/
//2.//通过构造方法实现成员变量的初始化,更加灵活
//4.//私有化构造方法,此时该构造方法只能在本类的内部使用,参考单例设计模式
private DirectionEnum(String desc) {
this.desc = desc;
}
//3.//通过公有的get方法可以在本类的外部访问该类成员变量的数值
public String getDesc() {
return desc;
}
//6.//整个枚举类型只重写一次,所有对象调用同一个
/*@Override
public void show() {
System.out.println("现在可以实现接口中抽象方法的重写了!");
}*/
}
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 15:52
* 编程实现方向枚举类的测试
* Enum类实现接口的方式3
*/
public class DirectionEnumTest {
public static void main(String[] args) {
//1.//获取DirectionEnum类型中所有的枚举对象
DirectionEnum[] arr = DirectionEnum.values();
//2.//打印每个枚举对象在枚举类型中的名称和索引位置
for(int i = 0; i < arr.length; i++) {
System.out.println("获取到的枚举对象名称是: " + arr[i].toString());
System.out.println("获取到的枚举对象对应的索引位置是:" + arr[i].ordinal()); //和数组一样下标从0开始
}
System.out.println("------------------------------------------------");
//3.//根据参数指定的字符串得到枚举类型的对象,也就是将字符串转换为对象
//DirectionEnum de = DirectionEnum.valueOf("向下"); //编译OK, 运行发生IllegalArgumentException 非法参数异常
DirectionEnum de = DirectionEnum.valueOf("DOWN"); //给一个字符串类型的DOWN,返回一个枚举类型的DOWN
//DirectionEnum de = DirectionEnum.valueOf("UP LEFT"); //要求字符串名称必须在枚举对象中存在
//System.out.println("转换出来的枚举对象名称是:" + de.toString());
System.out.println("转换出来的枚举对象的名称是:" + de); //当打印引用变量时,会自动调用toString方法
System.out.println("------------------------------------------------");
//4.//使用获取到的枚举对象与枚举类中已有的对象比较先后顺序
for(int i = 0; i < arr.length; i++) {
//当调用对象在参数对象之后时, 获取到的比较结果为 正数
//当调用对象在参数对象相同位置, 获取到的比较结果为 零
//当调用对象在参数对象之前时, 获取到的比较结果为 负数
System.out.println("调用对象与数组中对象比较的先后顺序结果是: " + de.compareTo(arr[i]));
}
System.out.println("------------------------------------------------");
//5.//使用数组中每个DirectionEnum对象都去调用show方法测试
for(int i = 0; i < arr.length; i++) {
arr[i].show();
}
}
}
代码: 自定义类和枚举类型在switch结构中的使用
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 15:11
* 自定义类和枚举类型在switch结构中的使用
*/
public class DirectionUseTest {
//1.//自定义静态方法实现根据参数指定的字符串内容打印具体的方向信息
public static void test1(String str) {
switch(str) {
case "向上":
System.out.println("抬头望明月");break;
case "向下":
System.out.println("低头思故乡");break;
case "向左":
System.out.println("左牵黄");break;
case "向右":
System.out.println("右擎苍");break;
default:
System.out.println("没有这样的方法哦!");break;
}
}
//2.//自定义静态方法实现根据参数指定的枚举类型打印具体的方向信息
public static void test2(DirectionEnum de) {
switch(de) {
case UP:
System.out.println("抬头望明月");break;
case DOWN:
System.out.println("低头思故乡");break;
case LEFT:
System.out.println("左牵黄");break;
case RIGHT:
System.out.println("右擎苍");break;
default:
System.out.println("没有这样的方向哦!");break;
}
}
public static void main(String[] args) {
DirectionUseTest.test1(Direction.UP.getDesc());
DirectionUseTest.test1("今天是个好日子");
System.out.println("---------------------------------------");
DirectionUseTest.test2(DirectionEnum.DOWN);
//DirectionUseTest.test2("今天是个好日子"); //3.// Error:类型不匹配,减少了出错的可能性
}
}
10 注解(Annotation)
基本概念
又叫标注,是从Java5开始增加的一种引用数据类型 本质上是代码中的特殊标记,通过这些标记可以再编译,类加载 以及运行时执行指定的处理
语法格式
访问修饰符 @interface 注解名称 { 注解成员; } 自定义注解自动继承java.lang..annotation.Annotation接口
使用方法
@注解名称 注解中只有成员变量无成员方法, 成员变量的声明是"无参的方法"形式, 方法名是成员变量名,返回值则定义了该成员变量的类型 如果注解中只有一个参数成员,建议使用参数名为value, 类型只能是8种基本以及String类型Class类型enum类型以及Annotation类型
11 元注解
概念
可以注解到注解上的注解 @Retention @Documented @Target @Inherited @Repeatable
@Retention
应用到一个注解上用于说明该注解的生命周期,取值如下: RetentionPolicy.SOURCE 只在源码阶段保留,在编译器进行编译时它将被丢弃忽视 RetentionPolicy.CLASS 保留到编译进行的时候,不会被加载到JVM中,默认方式 RetentionPolicy.RUNTIME 保留到运行时,会被加载进JVM中,故程序运行时可以获取到
@Documented
用于指定 该注解将被javadoc工具提取成文档 定义为@Documented的注解鼻血设置Retention值为RUNTIME javadoc工具可以从程序源代码中抽取类,方法,成员等形成一个和源代码配套的 API(Application Programming Interface)帮助文档,而该工具抽取时默认不包括注解内容
@Target
用于指定被修饰的注解, 可以修饰哪些元素 取值如下: Element.ANNOTATION_TYPE 注解注解 Element.CONSTRUCTOR 注解构造方法 Element.FIELD 注解属性 Element.LOCAL_VARIABLE 注解局部变量 Element.METHOD 注解方法 Element.PACKAGE 注解包 Element.PARAMETER 注解参数 Element.TYPE 注解类型
@Inherited
不是说注解本身可以被继承,而是说如果一个父类/超类被该注解标记过的注解进行注解时, 如果子类没有被任何任何注解应用时,则子类就继承父类/超类的注解
代码: 注解的定义和使用
代码: 元注解的概念和Retention的使用
代码: Documented的使用
代码: Target
代码: Inherited
package com.lagou.task10;
import javax.swing.text.html.parser.Element;
import java.lang.annotation.*; //*是通配符,表示导入所有
/**
* @author CH
* @date 2020/9/26 17:03
* 注解的定义和使用1
* 元注解的概念和@Retention的使用1
* Documented的使用1
*/
//2.//元注解的使用
//@Retention(RetentionPolicy.SOURCE) //表示下面的注解在源代码中有效
//@Retention(RetentionPolicy.CLASS) //表示下面的注解在字节码中有效, 默认方式
@Retention(RetentionPolicy.RUNTIME) //表示下面的注解在运行时有效
@Documented //表示下面的注解信息可以被javadoc工具提取到API文档中,很少使用
//3.//表示下面的注解可以用于类型,构造方法,成员变量,成员方法,参数的修饰
@Target({/*ElementType.TYPE,*/ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.METHOD, ElementType.PARAMETER})
@Inherited //表示下面的注解所修饰的类中的注解可以被子类继承
//1.//若一个注解中没有任何成员,则这样的注解叫做标记/标识注解
public @interface MyAnnotation {
//public Direction value(); //声明一个Srting类型的成员变量,名字为value 类型有要求
public String value()default "123"; //声明一个String类型的成员变量,名字为value
public String value2();
}
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 17:03
* 注解的定义和使用2
*/
//1.//表示将Annotation贴在Person类的代码中, 使用注解时,采用 成员参数名 = 成员参数值,...
//@MyAnnotation(value = "hello",value2 = "world")
//@MyAnnotation(value2 = "world") //value给值就改,不给就默认值
public class Person {
/**
* name是用于描述姓名的成员变量
*/
@MyAnnotation(value2 = "1")
private String name;
/**
* age是描述年龄的成员变量
*/
private int age;
@MyAnnotation(value2 = "2")
public Person() {
}
/**
* 编程实现有参构造方法
* @param name
* @param age
*/
public Person(@MyAnnotation(value2 = "4") String name, int age) {
this.name = name;
this.age = age;
}
/**
* 自定义成员方法实现特征的获取和修改
* @return
*/
@MyAnnotation(value2 = "3")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 17:49
* Inherited的使用
*/
//也就是可以继承Person的注解
public class Student extends Person { //
}
@Repeatable
表示自然可重复的含义, 从Java8开始增加的新特性 Java8开始,对元注解@Target的参数类型ElementType枚举值增加了两个 其中ElementType.TYPE_PARAMETER表示该注解能写在类型变量的声明语句中 ElementType.TYPE_USE表示该注解能写在使用类型的任何语句中
12 常见的预制注解
@author 标明作者,多个作者之间使用逗号隔开 @version 标明该类模块的版本 @see 参考转向,也就是相关主题(比如参考了什么代码) @since 从哪个版本开始增加的(比如从哪个版本开始增加了视频功能) @param 对方法中某参数的说明,如果没有参数就不能写 @return 对方法返回值的说明,如果方法的返回值类型是void就不能写 @exception 对方法可能抛出的异常进行说明 @Override 限定重写父类方法,该注解只能用于方法 @Deprecated 用于表示所修饰的元素(类,方法等)已过时 @SuppressWarnings 抑制编译器警告
代码: Repeatable
代码:Deprecated
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 17:54
*/
@ManType(value= "职工")
@ManType(value= "超人") //这就是重复的注解
//@ManTypes({@ManType(value= "职工"),@ManType(value= "超人")}) //在Java8以前处理多个注解的方式
public class Man {
@Deprecated //表示该方法已经过时,不建议使用
public void show() {
System.out.println("这个方法马上过时了!");
}
public static void main(String[] args) {
int ia = 97;
char c1 = (@ManType char)ia;
}
}
package com.lagou.task10;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Target;
/**
* @author CH
* @date 2020/9/26 17:52
* 自定义注解用于描述人物的角色
*/
@Repeatable(value= ManTypes.class) //在Java8以后处理多个注解的方式
@Target(ElementType.TYPE_USE)
public @interface ManType {
String value()default"";
}
package com.lagou.task10;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
/**
* @author CH
* @date 2020/9/26 17:56
*/
@Target(ElementType.TYPE_USE)
public @interface ManTypes {
ManType[] value();
}
package com.lagou.task10;
/**
* @author CH
* @date 2020/9/26 18:14
*/
public class ManTest {
public static void main(String[] args) {
Man man = new Man();
man.show();
}
}