天天看点

Java枚举类、注解和反射

本文主要介绍的是枚举类,注解和反射。还有一些基础知识:static,基本数据类型,运算符优先级放在文中,以便查阅复习。

其中牵扯到泛型的部分,可参考本人的另一篇博客:(Collection, List, 泛型)JAVA集合框架一

1. static关键字

static可以修饰的有:属性,方法,代码块,内部类。

按是否用static修饰分为静态属性和非静态属性(实例变量)。

非静态属性(实例变量):当创建了类的多个对象,每个对象都独立拥有自己的非静态属性。当修改其中一个对象中的非静态属性时,不会改变其他对象中的非静态属性。

静态属性(静态变量):当创建了类的多个对象,多个对象共享同一个静态对象。通过任一个对象改变静态属性,所有对象的静态属性都会发生改变。

静态变量随着类的加载而加载。可通过class.静态变量进行调用。

静态变量的加载早于对象的创建,在创建对象的过程中,才实现实例属性的加载。

由于类只会加载一次,则静态变量在内存中也只会存在一份。存在方法区的静态域中。

静态方法:

随着类的加载而加载,可以直接通过类.静态方法调用

静态方法中,只能调用静态的方法或属性,因为它们生命周期相同;非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性。

注意点:

在静态的方法内,不能使用this和super关键字,因为静态方法不需要实例化对象,而没有实例化对象this就没有意义。一定要是同级的生命周期才能使用。2. 枚举类

JDK5.0新增enum关键字

理解:

类的对象只有有限个、确定的,称此类为枚举类

当需要定义一组常量时,建议使用枚举类

常用方法:

Java枚举类、注解和反射

重点掌握:toString,values,valueOf

情况一:实现接口,在enum类中实现抽象方法

情况二:让枚举类的对象分别实现接口中的抽象方法

整体demo包含常用方法的使用:

Thread中线程状态利用的就是枚举类,可参考源码。

3. 注释和注解

注解(Annotation)是代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过使用注解,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或进行部署。JDK5.0新增

在JavaSE中注解的使用目的比较简单,比如标记过时功能,忽略警告等。在JavaEE中占据了更重要的角色。后续博客将会继续JavaEE的内容。

在一定程度上,框架 = 注解 + 反射 + 设计模式

Java枚举类、注解和反射

类注释必须放在import语句之后,类定义之前。

除了通用标记之外,还可以使用下面的标记:

@param变量描述,这个标记将对当前方法的参数部分添加一个条目。这个描述可以占据多行,并可以使用HTML标记,一个方法的所有变量描述需要放在一起。

@return描述

@throws类描述,表示这个方法有可能抛出异常。

Java枚举类、注解和反射
注意,一定要用 # 分隔类名和方法名,或类名和变量名。

注解声明为:@interface

内部定义成员,通常用value表示

可以指定成员的默认值,使用default定义

如果自定义注解里没有成员,表明是一个标识作用

具体用途在反射和框架中。自定义注解必须配上注解的信息处理流程(使用反射)才有意义。

Java枚举类、注解和反射

元注解:用于修饰其他注解定义

例:

JDK5.0提供了4个标准的元注解:

Retention, Target, Documented, Inherited

Java枚举类、注解和反射
Java枚举类、注解和反射

自定义注解通常都会使用以上两个元注解Retention, Target。

Java枚举类、注解和反射

Repeatable()

其中,MyAnnotation和MyAnnotations需要保持Retention和Target以及Inherited一致,在这部分只需要注意,在以后用到时再重点讲解。

Java枚举类、注解和反射

4. 反射

Java枚举类、注解和反射

反射机制提供的功能:

运行时判断任意一个对象所属的类

运行时构造任意一个类的对象

运行时判断任意一个类所具有的成员变量和方法

运行时获取泛型信息

运行时调用任意一个对象的成员变量和方法

在运行时处理注解

生成动态代理

关于java.lang.Class类的理解:

类的加载过程:程序经过javac.exe命令后(编译),会生成一个或多个字节码文件(.class文件)。接着使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中,此过程成为类的加载。加载到内存中的类,称为运行时类,此运行时类,作为Class的一个实例。

Class的实例对应着一个运行时类

加载到内存中的运行时类,会缓存一定的时间。在此时间内,可以通过不同方式来获取Class的实例。

Object是所有类的父类,而Class是类的类。

三种Class实例的获取方式:

获取当前对象的类型对象,类型类是指代表一个类型的类,获取class对象的方法有:1.类名.class,所有的引用数据类型和基本数据类型都可以通过这个方式获取。2.通过对象实例.getClass()来获得class对象。3.调用Class的静态方法  Class.forName(String classPath)

此外,还可以使用类的加载器ClassLoader,不再详细赘述。

JDK8中对于自定义类的ClassLoader属于系统类加载器,此外还有扩展类加载器和引导类加载器。

Java枚举类、注解和反射

简述下方的Person类:内部成员变量为public String name, private int age, 有公有构造器和私有构造器,有公有方法show()和私有方法show1(), 重写toString。

基本应用demo:

需要注意的是Class对象并不能指明该类型的实例化,需要在Field或Method这种将实例放入参数中。

通过反射,可以调用Person类的私有结构,如:私有构造器,私有方法,私有属性。

这里和面向对象概念中的封装性可能有冲突,为什么要利用反射呢?

举个例子:反射具有动态性的特征。后台中,服务器的程序一直运行,假如从前端传来信息,后台就可以动态进行调用。动态过程中,可以利用反射进行应用。

获得方法结构:

获取方法的内部结构:

构造器等都类似,不再赘述。构造器的.getConstructors和.getDeclaredConstructors不能获取父类的结构,没有意义。

此外还可获取运行时类的父类和父类的泛型,运行时类的接口,包,注释等,代码比较机械,不再赘述。

调用运行时类的属性:

调用运行时类中指定的方法:

如果调用的运行时类的方法没有返回值,则返回null

调用运行时类中指定的构造器:

需要注意的是即使Class加上泛型声明,下方的Constructor.newInstance仍需强转

接下来是最近刷题时总结了一些基础知识,需要对这些数据保持敏感。

5. 基本数据类型

byte:

1个字节,8位、有符号的,以二进制补码表示的整数;

最小值是 -128(-2^7);

最大值是 127(2^7-1);

默认值是 0;

byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一;

例子:byte a = 100,byte b = -50。

short:

2个字节,16 位、有符号的以二进制补码表示的整数

最小值是 -32768(-2^15);

最大值是 32767(2^15 - 1);

Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一;

例子:short s = 1000,short r = -20000。

int:整数型,4个字节32位,负数以补码形式存在,取值范围如下:

最小值是 -2,147,483,648(-2^31);

最大值是 2,147,483,647(2^31 - 1);

默认值为0

long:

8个字节, 64 位、有符号的以二进制补码表示的整数;

最小值是 -9,223,372,036,854,775,808(-2^63);

最大值是 9,223,372,036,854,775,807(2^63 -1);

这种类型主要使用在需要比较大整数的系统上;

默认值是 0L;

例子: long a = 100000L,Long b = -200000L。

"L"理论上不分大小写,但是若写成"l"容易与数字"1"混淆,不容易分辩。所以最好大写。

float:

float 数据类型是单精度、32位、符合IEEE 754标准的浮点数;

float 在储存大型浮点数组的时候可节省内存空间;

默认值是 0.0f;

浮点数不能用来表示精确的值,如货币;

例子:float f1 = 234.5f。

double:

double 数据类型是双精度、64 位、符合 IEEE 754 标准的浮点数;

浮点数的默认类型为 double 类型;

double类型同样不能表示精确的值,如货币;

默认值是 0.0d;

boolean:

boolean数据类型表示一位的信息;

只有两个取值:true 和 false;

这种类型只作为一种标志来记录 true/false 情况;

默认值是 false;

例子:boolean one = true。

char:

char 类型是一个单一的 16 位 Unicode 字符;

最小值是 \u0000(左方是16进制表示,十进制等效值为 0);

最大值是 \uffff(即为 65535);

char 数据类型可以储存任何字符;

例子:char letter = 'A';。

6. 运算符优先级

Java枚举类、注解和反射

继续阅读