汉中城乡建设网站,win10 wordpress安装教程视频,沈阳关键词快照优化,网站 科技感本文是我们名为“ 高级Java ”的学院课程的一部分。 本课程旨在帮助您最有效地使用Java。 它讨论了高级主题#xff0c;包括对象创建#xff0c;并发#xff0c;序列化#xff0c;反射等。 它将指导您完成Java掌握的过程#xff01; 在这里查看 #xff01; 目录 1.简… 本文是我们名为“ 高级Java ”的学院课程的一部分。 本课程旨在帮助您最有效地使用Java。 它讨论了高级主题包括对象创建并发序列化反射等。 它将指导您完成Java掌握的过程 在这里查看 目录 1.简介 2.枚举作为特殊类 3.枚举和实例字段 4.枚举和接口 5.枚举和泛型 6.便捷的枚举方法 7.专门的集合EnumSet和EnumMap 8.何时使用枚举 9.注释作为特殊接口 10.注释和保留政策 11.注释和元素类型 12.注释和继承 13.可重复的注释 14.注释处理器 15.约定上的注释和配置 16.何时使用注释 17.接下来 18.下载源代码 1.简介 在本教程的这一部分中我们将介绍Java 5版本中引入到语言中的另外两个重要功能以及泛型枚举或枚举和注释。 枚举可被视为类的特殊类型而注解可被视为接口的特殊类型。 枚举的概念很简单但很方便它表示一组固定的恒定的值。 实际上这意味着通常使用枚举来设计具有恒定可能状态的概念。 例如星期几就是枚举的一个很好的例子它们仅限于星期一星期二星期三星期四星期五星期六和星期日。 另一方面注释是一种特殊的元数据可以与Java语言的不同元素和构造相关联。 有趣的是注释在消除Java生态系统中几乎所有地方都使用的样板XML描述符方面做出了很大贡献。 他们介绍了一种新的类型安全且健壮的配置和自定义技术方法。 2.枚举作为特殊类 在将枚举引入Java语言之前在Java中对固定值集进行建模的常规方法是声明一些常量。 例如 public class DaysOfTheWeekConstants {public static final int MONDAY 0;public static final int TUESDAY 1;public static final int WEDNESDAY 2;public static final int THURSDAY 3;public static final int FRIDAY 4;public static final int SATURDAY 5;public static final int SUNDAY 6;
} 尽管这种方法行之有效但远非理想的解决方案。 主要是因为常量本身只是int类型的值并且代码中应期望这些常量的每个位置而不是任意的int值都应始终明确记录并声明。 从语义上讲它不是该概念的类型安全表示形式如以下方法所示。 public boolean isWeekend( int day ) {return( day SATURDAY || day SUNDAY );
} 从逻辑角度来看day参数应具有在DaysOfTheWeekConstants类中声明的值之一。 但是如果不编写其他文档然后由其他人阅读则无法猜测。 对于Java编译器像isWeekend (100)这样的调用看起来是绝对正确的不会引起任何问题。 枚举在这里进行了救援。 枚举允许用类型化的值替换常量并在各处使用这些类型。 让我们使用枚举重写上面的解决方案。 public enum DaysOfTheWeek {MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY
} 更改的是class成为enum 并且可能的值在枚举定义中列出。 但是区别在于每个值都是在其声明的枚举类的实例在我们的示例中为DaysOfTheWeek 。 这样无论何时使用枚举Java编译器都可以进行类型检查。 例如 public boolean isWeekend( DaysOfTheWeek day ) {return( day SATURDAY || day SUNDAY );
} 请注意枚举中大写命名方案的使用只是一个约定没有什么真正阻止您不这样做的。 3.枚举和实例字段 枚举是专门的类因此是可扩展的。 这意味着它们可以具有实例字段构造函数和方法尽管唯一的限制是不能声明默认的no-args构造函数并且所有构造函数都必须是private 。 让我们使用实例字段和构造函数将属性isWeekend添加到一周的每一天。 public enum DaysOfTheWeekFields {MONDAY( false ),TUESDAY( false ),WEDNESDAY( false ),THURSDAY( false ),FRIDAY( false ),SATURDAY( true ),SUNDAY( true );private final boolean isWeekend;private DaysOfTheWeekFields( final boolean isWeekend ) {this.isWeekend isWeekend;}public boolean isWeekend() {return isWeekend;}
} 如我们所见枚举的值只是构造函数调用简化了不需要new关键字的情况。 isWeekend()属性可用于检测该值代表工作日还是工作日结束。 例如 public boolean isWeekend( DaysOfTheWeek day ) {return day.isWeekend();
} 实例字段是Java枚举中极为有用的功能。 它们经常用于使用常规的类声明规则将一些其他详细信息与每个值相关联。 4.枚举和接口 另一个有趣的功能又一次确认了枚举只是专门的类是它们可以实现接口但是由于枚举和泛型部分稍后说明的原因枚举不能扩展任何其他类。 例如让我们介绍接口DayOfWeek 。 interface DayOfWeek {boolean isWeekend();
} 并使用接口实现而不是常规实例字段重写上一部分中的示例。 public enum DaysOfTheWeekInterfaces implements DayOfWeek {MONDAY() {Overridepublic boolean isWeekend() {return false;}},TUESDAY() {Overridepublic boolean isWeekend() {return false;}},WEDNESDAY() {Overridepublic boolean isWeekend() {return false;}},THURSDAY() {Overridepublic boolean isWeekend() {return false;}},FRIDAY() {Overridepublic boolean isWeekend() {return false;}},SATURDAY() {Overridepublic boolean isWeekend() {return true;}},SUNDAY() {Overridepublic boolean isWeekend() {return true;}};
} 我们实现接口的方式有些冗长但是可以通过将实例字段和接口组合在一起来使其更好。 例如 public enum DaysOfTheWeekFieldsInterfaces implements DayOfWeek {MONDAY( false ),TUESDAY( false ),WEDNESDAY( false ),THURSDAY( false ),FRIDAY( false ),SATURDAY( true ),SUNDAY( true );private final boolean isWeekend;private DaysOfTheWeekFieldsInterfaces( final boolean isWeekend ) {this.isWeekend isWeekend;}Overridepublic boolean isWeekend() {return isWeekend;}
} 通过支持实例字段和接口可以以更加面向对象的方式使用枚举从而带来某种程度的抽象依赖。 5.枚举和泛型 尽管乍看之下看不到它但Java中的枚举和泛型之间存在某种关系。 Java中的每个枚举都自动继承自通用Enum T 类其中T是枚举类型本身。 Java编译器在编译时代表开发人员进行此转换将枚举声明public enum DaysOfTheWeek为如下所示 public class DaysOfTheWeek extends Enum DaysOfTheWeek {// Other declarations here
} 它还解释了为什么枚举可以实现接口但不能扩展其他类的原因它们隐式扩展了Enum T 并且如本教程第2部分所知 使用所有对象通用的方法 Java不支持多重继承。 每个枚举都扩展Enum T 的事实允许定义通用类接口和方法这些类接口和方法期望将枚举类型的实例作为参数或类型参数。 例如 public T extends Enum ? void performAction( final T instance ) {// Perform some action here
} 在上面的方法声明中类型T被约束为任何枚举的实例Java编译器将对此进行验证。 6.便捷的枚举方法 Enum T 类提供了两个有用的方法每个枚举实例都会自动继承这些方法。 方法 描述 String name() 返回此枚举常量的名称该名称与在其枚举声明中声明的完全相同。 int ordinal() 返回此枚举常量的序数其在枚举声明中的位置其中初始常量的序数为零。 表格1 此外Java编译器会针对它遇到的每种枚举类型自动生成两个更有用的static方法让我们将特定的枚举类型称为T 。 方法 描述 T[] values() 返回枚举T的所有声明的枚举常量。 T valueOf(String name) 返回具有指定名称的枚举常量T 表2 由于这些方法的存在和艰苦的编译器工作在代码中使用枚举还有另一个好处它们可以在switch/case语句中使用。 例如 public void performAction( DaysOfTheWeek instance ) {switch( instance ) {case MONDAY:// Do somethingbreak;case TUESDAY:// Do somethingbreak;// Other enum constants here}
}7.专门的集合EnumSet和EnumMap 与所有其他类一样枚举的实例可以与标准Java集合库一起使用。 但是某些收集类型已经专门针对枚举进行了优化并且在大多数情况下建议使用它们来代替通用的对应类型。 我们将研究两种专门的集合类型 EnumSet T 和EnumMap T, ? EnumMap T, ? 。 两者都很容易使用我们将从EnumSet T 。 EnumSet T 是优化以有效存储枚举的常规集。 有趣的是 EnumSet T 不能使用构造函数实例化而是提供了许多有用的工厂方法我们在本教程的第1部分“ 如何创建和销毁对象”中介绍了工厂模式。 例如 allOf工厂方法创建EnumSet T 的实例该实例包含所涉及的枚举类型的所有枚举常量 final Set DaysOfTheWeek enumSetAll EnumSet.allOf( DaysOfTheWeek.class ); 因此 noneOf工厂方法为有问题的枚举类型创建一个空的EnumSet T 的实例 final Set DaysOfTheWeek enumSetNone EnumSet.noneOf( DaysOfTheWeek.class ); 另外也可以指定哪些枚举所讨论的枚举类型的常量应当纳入EnumSet T 使用of工厂方法 final Set DaysOfTheWeek enumSetSome EnumSet.of(DaysOfTheWeek.SUNDAY,DaysOfTheWeek.SATURDAY
); EnumMap T, ? EnumMap T, ? 非常接近于常规映射不同之处在于其键可以是所讨论枚举类型的枚举常量。 例如 final Map DaysOfTheWeek, String enumMap new EnumMap( DaysOfTheWeek.class );
enumMap.put( DaysOfTheWeek.MONDAY, Lundi );
enumMap.put( DaysOfTheWeek.TUESDAY, Mardi ); 请注意作为大多数集合实现 EnumSet T 和EnumMap T, ? EnumMap T, ? 不是线程安全的并且不能在多线程环境中按原样使用我们将在本教程的第9部分“ 并发最佳实践”中讨论线程安全和同步。 8.何时使用枚举 由于Java 5发行版枚举是使用固定的常量集表示和拨号的唯一首选和推荐方法。 它们不仅是强类型的而且是可扩展的并得到任何现代库或框架的支持。 9.注释作为特殊接口 如前所述注释是用于将元数据与Java语言的不同元素相关联的语法糖。 注释本身对所注释的元素没有任何直接影响。 但是根据注释及其定义方式的不同Java编译器可能会使用它们一个很好的例子是Override注释我们在本教程的第3部分“ 如何设计类和接口 注释处理器更多详细信息将在“ 注释处理器”部分中找到以及运行时使用反射和其他自省技术的代码有关本教程的第11部分中的更多内容 反射和动态语言支持 。 让我们看一下最简单的注释声明 public interface SimpleAnnotation {
}The interface keyword introduces new annotation type. That is why annotations could be treated as specialized interfaces. Annotations may declare the attributes with or without default values, for example:
public interface SimpleAnnotationWithAttributes {String name();int order() default 0;
} 如果注释声明的属性没有默认值则应在应用注释的所有位置提供该属性。 例如 SimpleAnnotationWithAttributes( name new annotation ) 按照惯例如果注释具有带有名称value的属性并且它是唯一需要指定的属性则可以省略属性的名称例如 public interface SimpleAnnotationWithValue {String value();
}It could be used like this:SimpleAnnotationWithValue( new annotation ) 在某些用例中有两个限制使使用注释不太方便。 首先注释不支持任何继承一个注释不能扩展另一个注释。 其次不可能使用new运算符以编程方式创建注释的实例我们将参考本教程的第11部分“ 反射和动态语言支持”中的一些变通方法。 第三注释只能声明基本类型的属性即String或Class ? Class ? 这些的类型和数组。 注释中不允许声明任何方法或构造函数。 10.注释和保留政策 每个注释都有一个非常重要的特性称为保留策略 这是一个枚举类型为RetentionPolicy 其中包含有关如何保留注释的策略集。 可以将其设置为以下值之一。 政策 描述 CLASS 注释由编译器记录在类文件中但VM在运行时无需保留 RUNTIME 注释由编译器记录在类文件中并在运行时由VM保留因此可以通过反射方式读取它们。 SOURCE 批注将被编译器丢弃。 表3 保留策略对批注何时可用于处理至关重要。 可以使用Retention批注设置保留策略。 例如 import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;Retention( RetentionPolicy.RUNTIME )
public interface AnnotationWithRetention {
} 将注释保留策略设置为RUNTIME将保证其在编译过程和正在运行的应用程序中的存在。 11.注释和元素类型 每个注释必须具有的另一个特征是可以应用的元素类型。 与保留策略类似它被定义为带有可能元素类型集的枚举 ElementType 。 元素类型 描述 ANNOTATION_TYPE 注释类型声明 CONSTRUCTOR 构造函数声明 FIELD 字段声明包括枚举常量 LOCAL_VARIABLE 局部变量声明 METHOD 方法声明 PACKAGE 包裹申报 PARAMETER 参数声明 TYPE 类接口包括注释类型或枚举声明 表4 除了上述描述的元素外Java 8还引入了两种可以应用注释的新元素类型。 元素类型 描述 TYPE_PARAMETER 类型参数声明 TYPE_USE 使用类型 表5 与保留策略相反注释可以使用Target注释声明可以与之关联的多种元素类型。 例如 import java.lang.annotation.ElementType;
import java.lang.annotation.Target;Target( { ElementType.FIELD, ElementType.METHOD } )
public interface AnnotationWithTarget {
} 通常要创建的所有注释都应同时指定保留策略和元素类型以便使用。 12.注释和继承 在Java中声明注释和继承之间存在重要的关系。 默认情况下子类不继承在父类上声明的注释。 但是有一种方法可以使用Inherited注释在类层次结构中传播特定的注释。 例如 Target( { ElementType.TYPE } )
Retention( RetentionPolicy.RUNTIME )
Inherited
interface InheritableAnnotation {
}InheritableAnnotation
public class Parent {
}public class Child extends Parent {
} 在此示例中在Parent类上声明的InheritableAnnotation注释也将由Child类继承。 13.可重复的注释 在Java 8以前的时代与注释有关的另一个限制尚未讨论同一注释只能在同一位置出现一次不能重复多次。 Java 8通过提供对可重复注释的支持来减轻这种限制。 例如 Target( ElementType.METHOD )
Retention( RetentionPolicy.RUNTIME )
public interface RepeatableAnnotations {RepeatableAnnotation[] value();
}Target( ElementType.METHOD )
Retention( RetentionPolicy.RUNTIME )
Repeatable( RepeatableAnnotations.class )
public interface RepeatableAnnotation {String value();
};
RepeatableAnnotation( repeatition 1 )
RepeatableAnnotation( repeatition 2 )
public void performAction() {// Some code here
} 尽管在Java 8中可重复注释功能需要做一些工作才能使您的注释可重复使用Repeatable 但最终结果还是值得的更干净更紧凑的带注释的代码。 14.注释处理器 Java编译器支持一种称为注释处理器的特殊插件使用–processor命令行参数可以在编译阶段处理注释。 注释处理器可以分析注释的用法执行静态代码分析创建其他Java源文件或资源依次可以对其进行编译和处理或对注释的代码进行更改。 保留策略 请参见注释和保留策略 通过指示编译器哪些注释应可用于注释处理器进行处理而发挥了关键作用。 注解处理器被广泛使用但是要编写注解处理器它需要Java编译器如何工作以及编译过程本身的一些知识。 15.约定上的注释和配置 约定优于配置是一种软件设计范例旨在简化开发人员遵循一组简单规则或约定的开发过程。 例如某些MVC 模型-视图-控制器框架遵循约定将控制器放置在“ controller”文件夹或程序包中。 另一个示例是ORM 对象关系映射器框架该框架通常遵循约定以在“模型”文件夹或程序包中查找类并从相应的类派生关系表名称。 另一方面注释为基于显式配置的其他设计范例打开了道路。 考虑以上示例 Controller Controller批注可以将任何类显式标记为controller而Entity可以引用关系数据库表。 好处还来自以下事实注释是可扩展的可能具有其他属性并且仅限于特定的元素类型。 Java编译器强加了对注释的不正确使用并在早期在编译阶段揭示了配置错误的问题。 16.何时使用注释 注释几乎无处不在Java标准库有很多注释大多数每个Java规范也都包含注释。 每当您需要将其他元数据与代码相关联时批注便是直接简单的方法。 有趣的是Java社区正在不断努力开发通用的语义概念并使几种Java技术之间的注释标准化有关更多信息请参阅JSR-250规范 。 目前标准Java库包含以下注释。 注解 描述 Deprecated 指示已标记的元素已弃用不应再使用。 每当程序使用带有此批注的方法类或字段时编译器都会生成警告。 Override 提示编译器该元素旨在替代超类中声明的元素。 SuppressWarnings 指示编译器禁止以其他方式生成的特定警告。 SafeVarargs 当应用于方法或构造函数时断言该代码不会对其varargs参数执行潜在的不安全操作。 使用此注释类型时将禁止使用与varargs有关的未经检查的警告有关varargs的更多详细信息将在本教程的第6部分“ 如何有效地编写方法”中进行介绍 。 Retention 指定如何保留标记的注释。 Target 指定可以将标记的注释应用于哪种Java元素。 Documented 指示每当使用指定的注释时都应使用Javadoc工具记录这些元素默认情况下Javadoc中不包含注释。 Inherited 指示可以从超类继承注释类型有关更多详细信息请参阅注释和继承部分。 表6 Java 8发行版还添加了一些新的注释。 注解 描述 FunctionalInterface 指示类型声明旨在用作Java语言规范定义的功能接口有关功能接口的更多详细信息在本教程的第3部分“ 如何设计类和接口”中进行了介绍 。 Repeatable 表示标记的注释可以多次应用于同一声明或类型使用有关更多详细信息请参阅“可重复注释”部分。 表7 17.接下来 在本节中我们介绍了用于表示固定常量集的枚举或枚举以及使用元数据装饰Java代码元素的注释。 尽管没有什么联系但这两个概念在Java中已被广泛使用。 尽管在本教程的下一部分中我们将继续研究如何有效地编写方法但注释通常会成为大多数讨论的一部分。 18.下载源代码 这是关于如何设计类和接口的课程。 您可以在此处下载源代码 advanced-java-part-5 翻译自: https://www.javacodegeeks.com/2015/09/how-and-when-to-use-enums-and-annotations.html