目录
1. 枚举
为了体现有限,固定的(事先设置好的)
关键字 enum(一组常量的集合)
1.1 自定义枚举:
方法1.自定义枚举
构造器私有化,防止类外部new
去掉set相关方法,只能读不能修改
在类内部直接创建固定的对象(public static final修饰)
class person{
//成员属性 (私有化)
private String Name;
private int age;
//构造器(私有化)
private person(String name, int age) {
this.Name = name;
this.age = age;
}
//3.实例化 公共属性预加载且不能修改
public static final person student = new person("A",12);
public static final person doc = new person("B",33);
}
1.2 enum关键字枚举
方法2.使用enum关键字(替代class)
- 格式为 对象名(构造器参数),要求写在行首(在成员属性的上面)
- 如果有多个,之间使用逗号间隔,最后一个要有分号
使用enum会默认继承枚举类
如果使用无参构造器创建对象,可以不写括号
使用enum特殊字的类不能再继承于任何类(不能标注extends,即作为子类)(因为隐式继承且Java为单继承机制),但可以实现接口
enum season{
// 对象枚举
Spring("春天",15f),Summer("夏天",30f),Autumn("秋天",8f);
//成员属性
private String Name;
private float AvgT;
//构造器
season(String name, float avgT) {
Name = name;
AvgT = avgT;
}
}
常用方法:name,ordinal(输出枚举编号从0开始),values(返回数组,包含定义的所有枚举对象)
2. 注解
注解不影响程序,但会影响编译和运行,相当于嵌入到代码的补充信息(给计算机看的)
注解的作用一般分为三类:
- 注解生成文档(例如生成doc)
- 代码分析(生成简易框架,使用反射)
- 编译检查(例如Override)
JDK预定义的三种注解
- @Override(重写方法)
- @Deprecated (过时)
- @SuppressWarnings(String[]忽略警告{})
2.1 SuppressWarnings
//抑制所有警告
"all"
//抑制与封装/拆装作业相关的警告
"boxing"
//抑制与强制转型作业相关的警告
"cast"
//抑制与淘汰注释相关的警告
"dep-ann"
//抑制与淘汰的相关警告
"deprecation"
//抑制与switch陈述式中遗漏break相关的警告
"fallthrough"
//抑制与未传回finally区块相关的警告
"finally"
//抑制与隐藏变数的区域变数相关的警告
"hiding"
//抑制与switch陈述式(enum case)中遗漏项目相关的警告
"incomplete-switch"
//抑制与javadoc相关的警告
"javadoc"
//抑制与非nls字串文字相关的警告
"nls"
//抑制与空值分析相关的警告
"null"
//抑制与使用raw类型相关的警告
"rawtypes"
//抑制与使用Closeable类型的资源相关的警告
"resource"
//抑制与使用不建议或禁止参照相关的警告
"restriction"
//抑制与可序列化的类别遗漏serialVersionUID栏位相关的警告
"serial"
//抑制与静态存取不正确相关的警告
"static-access"
//抑制与可能宣告为static的方法相关的警告
"static-method"
//抑制与置换方法相关但不含super呼叫的警告
"super"
//抑制与内部类别的存取未最佳化相关的警告
"synthetic-access"
//抑制因为置换同步方法而遗漏同步化的警告
"sync-override"
//抑制与未检查的作业相关的警告
"unchecked"
//抑制与栏位存取不合格相关的警告
"unqualified-field-access"
//抑制与未用的程式码及停用的程式码相关的警告
"unused"
3. 元注解:
关于描述注释的注释:
3.1. @Target:
指示注释类型适用的上下文。 注释类型可能适用的声明上下文和类型上下文在JLS 9.6.4.1中指定,并以源代码通过枚举常数java.lang.annotation.ElementType表示 。
如果注释类型
T
上不存在@Target
元T
,则可以将类型为T
写为除了类型参数声明之外的任何声明的修饰符。如果存在
@Target
元注释,则编译器将强制使用ElementType
枚举常量指定的使用限制,符合JLS 9.7.4。例如,此
@Target
元注释表示声明的类型本身是元注释类型。 它只能用于注释类型声明:@Target(ElementType.ANNOTATION_TYPE) public @interface MetaAnnotationType { ... }
此
@Target
元注释表示声明的类型仅用于复杂注释类型声明中的成员类型。 它不能直接用于注释任何东西:@Target({}) public @interface MemberType { ... }
这是一个编译时错误
ElementType
不断出现不止一次在@Target
注解。 例如,下面@Target
元注释是非法的:@Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD}) public @interface Bogus { ... }
-
3.1.1 TYPE
public static final ElementType TYPE
放置位置:类,接口(包括注释类型)或枚举 的声明处
自定义注释 @MyAnno_Type:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno_Type {
String value() default "TYPE";
}
-
3.1.2 FIELD
public static final ElementType FIELD
字段声明(包括枚举常数)
自定义注释 @MyAnno_Field:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno_Field {
String value() default "FIELD";
}
1.类中的属性:
2.枚举的常数:
-
3.1.3 METHOD
public static final ElementType METHOD
方法的声明,定义
自定义注释 @MyAnno_Method:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno_Method {
String value() default "METHOD";
}
方法定义:
-
3.1.4 PARAMETER
public static final ElementType PARAMETER
正式参数 声明:(放置在方法 (包括泛型方法)的声明形参中,每一个参数前可以放置一个)
自定义注释 @MyAnno_Parameter:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno_Parameter {
String value() default "PARAMETER";
}
-
3.1.5 CONSTRUCTOR
public static final ElementType CONSTRUCTOR
构造函数的声明处
自定义注释 @MyAnno_Constructor:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno_Constructor {
String value() default "CONSTRUCTOR";
}
-
3.1.6 LOCAL_VARIABLE
public static final ElementType LOCAL_VARIABLE
局部变量声明(方法,代码块定义的变量)
自定义注释 @MyAnno_LocalVariable:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno_LocalVariable {
String value() default "LOCAL_VARIABLE";
}
1.只有在方法、代码块中,局部变量首次声明编译类型才能放置该类型的自定义注解
-
3.1.7 ANNOTATION_TYPE
public static final ElementType ANNOTATION_TYPE
注解类型声明(注解)
自定义注释 @MyAnno_LocalVariable :
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno_LocalVariable {
String value() default "LOCAL_VARIABLE";
}
声明标识符时使用该类型标识符
-
3.1.8 PACKAGE
public static final ElementType PACKAGE
包装声明(包)
-
3.1.9 TYPE_PARAMETER
public static final ElementType TYPE_PARAMETER
键入参数声明(应用于类型变量:放置在泛型修饰符的体内 )
从以下版本开始:
1.8
自定义注解:MyAnno_TypeParameter:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE_PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno_TypeParameter {
String value() default "TYPE_PARAMETER";
}
-
3.1.10 TYPE_USE
public static final ElementType TYPE_USE
1.使用类型(只要 (类,接口,枚举,泛型),属性(编译类型),方法(形参,返回类型,(泛型方法)(泛型内)类型变量(即<T>中的T)),构造器 (形参列表),局部变量(编译类型) 的声明处 出现了基本数据类型,类,接口,枚举类,注释,类型变量..,就可以使用)
2.void前不可使用
从以下版本开始:
1.8
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno_TypeUse {
String value() default "TYPE_USE";
}
类声明处:
局部变量声明处:
属性声明处
方法声明处:
3.2 @Retention :
指示要注释具有注释类型的注释的保留时间。 如果注释类型声明中没有保留注释,则保留策略默认为
RetentionPolicy.CLASS
。保留元注释仅在元注释类型直接用于注释时才起作用。 如果元注释类型用作另一注释类型的成员类型,则它不起作用
-
3.2.1 SOURCE
public static final RetentionPolicy SOURCE
注释将被编译器丢弃。
例如Override注解:只进行编译器检查是否是重写方法,编译之后就没用了
-
3.2.2 CLASS(默认值)
public static final RetentionPolicy CLASS
注释将由编译器记录在类文件中,但VM不需要在运行时保留。 这是默认行为。
-
3.2.3 RUNTIME(自定义泛型一般用这个)
public static final RetentionPolicy RUNTIME
注释将由编译器记录在类文件中,并由VM在运行时保留,因此可以反射读取。
另请参见:
3.3 @Documented:
表示具有类型的注释默认情况下由javadoc和类似工具记录。 应该使用此类型来注释其注释影响其客户端使用注释元素的类型的声明。 如果类型声明使用Documented进行注释,则其注释将成为注释元素的公共API的一部分。
3.4 @Inherited:
使用此注解的自定义注解,所标记的类的子类也会有这个注解
表示注释类型自动继承。 如果在注释类型声明中存在继承的元注释,并且用户在类声明上查询注释类型,并且类声明没有此类型的注释,则该类的超类将自动查询注释类型。 将重复此过程,直到找到此类型的注释,或者达到类层次结构(Object)的顶部。 如果没有超类具有此类型的注释,则查询将指示所讨论的类没有这样的注释。
请注意,如果使用注释类型来注释除类之外的任何内容,则此元注释类型不起作用。 还要注意,这个元注释只会导致从超类继承注释; 已实现的接口上的注释无效。
4.自定义注解(继承自Annotation接口)
注:自定义接口本质上是接口
// 本质:
public interface AnnotationName extends java.lang.annotation.Annovation
// 声明格式
public @interface AnnotationName {
// 允许有字符串,枚举,自定义注解 及他们的数组 ,后面代表的是变量名
String variableName1();
Strings variableName1s();
// 不允许自己嵌套自己!
AnnotationName variableName2();
AnnotationName variableName2s();
enumName variableName3();
enumName[] variableName3();
}
- 定义了属性,在使用时必须要进行赋值,如果在定义时使用了default初始化赋值,则不必进行属性赋值
- 如果方法名为value且只有value要赋值,则value可省略,直接定义值即可(Jdk自带的三种注解就可以直接这样)
- 数组赋值时要使用{}包裹,如果只有一个元素,则可以不使用{}
4.1 简单测试:
(A.利用反射 访问注解的内容 B.利用反射进行框架)
//label.TextLabel 类源码
package label;
import sun.security.x509.OtherName;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Vector;
import static label.TextLabel.Text;
import static label.TextLabel.tab2;
public class TextLabel<E> implements LabelX{
private E Input;
private Class<?> classType;
private String className;
private static int Counts = 1;
//S sType;
public TextLabel(){
}
public TextLabel(E input){
this.Input = input;
this.classType = this.Input.getClass();
this.className = this.classType.getName();
}
public Class<?> getclassType() {
return this.classType;
}
public String getclassName() {
return this.className;
}
public static void Indexend(){
Counts = 1;
}
public static int getCounts(){
return Counts;
}
@Override
public String toString() {
return this.Input.toString();
}
public static<E> TextLabel Text(E Input){
return new TextLabel(Input);
}
//添加
public TextLabel AddText(E Input){
return Text(this.Input.toString() + Input.toString());
}
//String 和 Text 的空格
private static final StringBuffer space(int n){
StringBuffer str = new StringBuffer(n);
for(int i = 0; i < n; i++){
str.append(" ");
}
return str;
}
public final TextLabel Space(int n){
return new TextLabel(this.Input.toString() + space(n));
}
// public static final TextLabel tabf(TextLabel){
//
// return new TextLabel("\n" + space(2) + getCounts() + this.Input.toString() );
// }
//Text Tab操作
public TextLabel Tabf() throws RuntimeException{
return Text(this.Input.toString() + " \n" + space(2) );
}
public static String nextLine(){
Indexend();
System.out.println();
return "\n";
}
//换行并标 序号
public static String tab(){
return ("\n" + space(2) + (Counts++) + ". ");
}
//String 和 Text 冒号操作
public static final String Title(String title){
return title + " : ";
}
public static final String Label(String label,String introduction){
return label + " : " + introduction;
}
//在后面添加一个:
public final TextLabel Colon(){
return Text(this.Input.toString() + " : " );
}
@Override
public final String mark(char c){
String s = this.Input.toString();
switch (c){
case '\'':
s = "\'"+ s + "\'";
break;
case'’':
case'‘':
s = "‘"+ s + "’";
case '"':
s = "\"" +s +"\"";
case '(':
case ')':
s = "("+ s + ")";
break;
case '[':
case ']':
s = "["+ s + "]";
break;
case '{':
case '}':
s = "{"+ s + "}";
case '【':
case '】':
s = "【"+ s + "】'";
case'<':
case'>':
s = "<" + s + ">";
case'《':
case'》':
s = "《" + s + "》";
}
return s +space(1);
}
private static int piles = -1;
private static String priStr = "";
//用于动态存放每层的点数
private static List<Integer> vec = new Vector<>();
//使用此函数后,层数提升
public static final void IndexSort(Boolean state) throws TextXException{
if(!state ){
if(piles != -1){
if(!vec.get(piles).equals(0)){
vec.remove(piles);
piles--;
}
}
else {
throw new TextXException("piles = -1 , Cannot input false ");
}
}else{ //开启或者嵌套多层
piles++; //层数增加
vec.add(piles,0);
}
}
//无序排序
public static final void Non_IndexSort(Boolean state){
if(!state && piles != -1 ){
if(!vec.get(piles).equals(0)){
vec.remove(piles);
piles--;
}
}else{ //开启或者嵌套多层
piles++; //层数增加
vec.add(piles,-1);//标记
}
}
//上一次是无序排序,将重新编号(级数增加或减少将启动)
private static String IndexCode(){
String str = "";
//取最后一次 -1 位置
int Index = vec.lastIndexOf(-1);
//取尾部的序号
int x = vec.size()-1;
//如果有无序排序 上一次是无序排序
if(Index != -1){
if(Index == vec.size()-1){
return "· ";
}else {
//从最尾部开始遍历
while(x > Index){
str = vec.get(x).toString() + "." + str;
x--;
}
}
}
else{
//从最尾部开始遍历
while(x >= 0){
str = vec.get(x).toString() + "." + str;
x--;
}
}
return str;
}
public static String tab2(){
if(vec.get(piles) != -1){
vec.set(piles,vec.get(piles)+1);
}
return ("\n" + space(2* piles) + IndexCode() );
}
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface testA {
String name() default "Tom" ;
}
@testA
class A{
public static void main(String[] args) throws Exception{
Class<A> AClass = A.class;
testA annova = AClass.getAnnotation(testA.class);
//调用注解定义的抽象方法
String className = annova.name();
System.out.println(className);
//加载
//Class<?> cla = Class.forName(className);
//System.out.println(cla);
System.out.println(testA.class);
System.out.println(annova.getClass());
}
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface testB {
//String[] TYPE();
String ClassName() default "java.lang.Object";
String[] Methods() default "hashCode";
String[] ParameterTypes() default " ";
String[] ConstructorsParameterTypes() default "";
String[] Fields();
}
@testB(ClassName = "label.TextLabel",
Methods = {"IndexSort","tab2"},
ParameterTypes = {"java.lang.Boolean"},
ConstructorsParameterTypes = "", //没用上
Fields = "piles")
class B{
public static void main(String[] args)
throws ClassNotFoundException,
NoSuchFieldException,
IllegalAccessException,
NoSuchMethodException,
InvocationTargetException {
Class<B> BClass = B.class;
testB annovaB = BClass.<testB>getAnnotation(testB.class);
//返回内存
Class<?> cla = Class.forName(annovaB.ClassName());
System.out.println(cla);
Field field= cla.getDeclaredField(annovaB.Fields()[0]);
field.setAccessible(true);
Object result = field.get(null);
System.out.println(result);
//读取 sort方法
//取得形参列表
Class[] classes1 = new Class[annovaB.ParameterTypes().length];
for(int index = 0 ;index < annovaB.ParameterTypes().length;index++){
classes1[index] = Class.forName(annovaB.ParameterTypes()[index]);
}
//取得 sort方法
Method method1 = cla.getDeclaredMethod((annovaB.Methods())[0],classes1);
//暴破
method1.setAccessible(true);
//运行方法
method1.invoke(null,(Object) true);
//读取tab2 方法
Method method2 = cla.getDeclaredMethod(annovaB.Methods()[1]);
//暴破
method2.setAccessible(true);
int times = 0;
while(times < 10){
System.out.print(method2.invoke(null).toString()); //运行
times++;
}
}
//框架
}
![](https://img-blog.csdnimg.cn/2fcf40d14c53431bb8c8d5a9e98c7f75.png)
![](https://img-blog.csdnimg.cn/96014732a453407dad4c6982e72de2d4.png)