java的enum泛型(java 泛型e)

华为云服务器特价优惠火热进行中!

2核2G2兆仅需 38 元;4核4G3兆仅需 79 元。购买时间越长越优惠!更多配置及优惠价格请咨询客服。

合作流程:
1、点击链接注册/关联华为云账号:点击跳转
2、添加客服微信号:cloud7591,确定产品方案、价格方案、服务支持方案等;
3、客服协助购买,并拉微信技术服务群,享受一对一免费技术支持服务;
技术专家在金蝶、华为、腾讯原厂有多年工作经验,并已从事云计算服务8年,可对域名、备案、网站搭建、系统部署、AI人工智能、云资源规划等上云常见问题提供更专业靠谱的服务,对相应产品提供更优惠的报价和方案,欢迎咨询。

本篇文章给大家谈谈java的enum泛型,以及java 泛型e对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

微信号:cloud7591
如需了解更多,欢迎添加客服微信咨询。
复制微信号

本文目录一览:

JAVA list 如何创建一个enum 类的list

ListEnum list = new ArrayListEnum();

请注意指亩枯大小写!

警告唯洞的原因是Enum是一个泛型类,它和ArrayList一样,例如:

ArrayList a = new ArrayList()也会有警告。耐宏

=======================

enum A {a,b,c};

ListEnumA list = new ArrayListEnumA();

这样就没有警告了。

java 的枚举可以用泛型吗

有!

泛型和枚举都是JDK1.5版本之后加入的新特性,泛型将程序代码的类型检查提前到了编译期间进行,枚举类型增强了程序代码的健壮性。

1. 泛型

在JDK1.5版本之前,如果在集合中添加了不同类型的数据,需要在程序的运行期间对类型之间的转换进行检查。

例如:

List arrayList=new arrayList();

在arrayList中添加String类型的对象和Integer对象,但是我们定义如下一个数组

String[] values=new String[arrayList.size()];

如果想要把arrayList转换成数组的话就会出现错误:

arrayList.toArray(values);//运行期间错误

这是因为List中包含了整型封装类型的对象。但是该错误只能在运行期间才能发现,程序能够正常的通过编译,并不会报错。

对于程序中出现的错误,应该尽早的通知程序员。泛型能够很好地解决这个问题。

1.1 泛型在集合中的应用

在JDK1.5版本之后Java提供了对泛型的支持。例如对于一个ArrayList列表来说,如果只想在列表中放入String类型元素,可以用下面的方法来实现:

ArrayListString list=new ArrayListString();

泛型使得编译器能够在编译期间对集合中加入的对象进行检查,如果加入了不同类型的对象,就会报错,而不必等到运行期间再进行相关的类型转换。

和原来没有使用泛型相比,它将原来需要在运行时期才能发现的异常提前到了编译期间,使得程序的安全性也大大提高,泛型一般用于集合类中。

1.2 泛型类和泛型方法

泛型类的定义如下:在类名的后面加上一对尖括号(""),在尖括号内部填入需要的类型。例如:

class Point T{ // 此处可以随便写败搏谨标识符号,T是type的简称

private T var ; // var的类型由T指定,即:由外部指定

public T getVar(){ // 返回值的类型由外部决定 ,泛型方法

return var ;

}

public void setVar(T var){ // 设置的类型也由外部决定

this.var = var ;

}

};

public class GenericsDemo06{

public static void main(String args[]){

Point String p = new Point String() ; // 里面的var类型为String类型

p.setVar("it") ; // 设置字符串

System.out.println(p.getVar().length()) ; // 取得字符串的长度

}

}; 2.枚举

枚举也是JDK1.5之后的版本以后Java新加入的特性。使用枚举可以表示一组常量数据。枚举的本质是一个类,可以使用enum关键字来声明一个枚举类型,其声明方式如下:

[访问控制符] enum 枚举类型名{value1,value2,......}

使用枚举类型需要注意以下几点:

枚举类型可以定义在类的内部也可以定义在类的外部。如果定义在类的内部,那么其访问控制符可以是public,protected,private或者默认的控制符。如果定义在类的外部,其访问控制符只能是public和默认控制符;

枚举类型中定义的value值都默认为public static final的。其值一经定义就不能在被修改了。多个value值之间需要用逗号隔开;

枚举类型中除了可以声明常量之外还可以声明方法。但是方法需要在常量之后,并且常量和方法之间要用分号区分;

枚举类型中的值可以通过枚举类型名直接对他们进察基行访问;

枚举类型不能声明为abstract或者final类型;

例:

public enum Direction{

FORWARD,

BACK,

LEFT;

public void start(){

System.out.println("enum method");

}

}

2.1 枚举类型的常用方法

public final String name()//返回枚举常量的名称;

public final int ordinal()//返回银销枚举常量在枚举类型中的位置,第一个枚举值序号为0,依次类推;

public String toString()//返回枚举常量的名字,可以重写此方法;

public static valueOf(enumType,String name)//返回与name名字相对应的枚举常量;

java:jdk1.4和jdk1.5的有那些区别(越详细越好)?

没多大区别,只要你注意别用那些过时的方法就行,若是新版本加的或有改变的方法,docs里会说的,在方法解释下面

jdk6.0将会有很大变化

增强的for循环

为了迭代集合和数组,增强的for循环提供了一个简单、兼容的语法。有两点值得一提:

Init表达式

在循环中,初始化表达式只计算一次。这意味着您通常可以移除一个变量声明。在这个例子中,我们必须创建一个整型数组来保存computeNumbers()的结果,以防止每一次循环都重新计算该方法。您可以看到,下面的代码要比上面的代码整洁一些,并且没有泄露变量numbers:

未增强的For:

int sum = 0;

Integer[] numbers = computeNumbers();

for (int i=0; i numbers.length ; i++)

sum += numbers[i];

增强后的For:

int sum = 0;

for ( int number: computeNumbers() )

sum += number;

局限性

有时需要在迭代期间访问迭代器或下标,看起来增强的for循环应该允许该操作,但事实上不是这样,请看下面的例子:

for (int i=0; i numbers.length ; i++) {

if (i != 0) System.out.print(",");

System.out.print(numbers[i]);

}

我们希望将数组中的值打印为一个用逗号分隔的清单。我们需要知道目前是否是第一项,以便确定是否应该打印逗号。使用增强的for循环是无法获知这种信息的。我们需要自己保留一个下标或一个布尔值来指示是否经过了第一项。 这是另一个例子:

for (Iteratorinteger it = n.iterator() ; it.hasNext() ; )

if (it.next() 0)

it.remove();

在此例中,我们想从整数集合中删除负数项。为此,需要对迭代器调用一个方法,但是当使用增强的for 循环时,迭代器对我们来说是穗坦则看不到的。因此,我们只能使用Java 5之前版本的迭代方法。 顺便说一下,这里需要注意的是,由于Iterator是泛型,所以其声明是IteratorInteger。许多人都忘记了这一点而使用了Iterator的原始格式。

注释

注释处理是一个很大的话题。因为本文只关注核心的语言特性,所以我们不打算涵盖它所有的可能形式和陷阱。 我们将讨论内置的注释(SuppressWarnings,Deprecated和Override)以及一般注释处理的局限性。

Suppress Warnings

该注释关闭了类或方法级别的编译器警告。有时候您比编译器更清楚地知道,代码必须使用一个被否决的方法或执行一些无法静态确定是否类型安全的动作,而使用:

@SuppressWarnings("deprecation")

public static void selfDestruct() {

Thread.currentThread().stop();

}

这可能是内置注释最有用的地方。遗憾的是,1.5.0_04的javac不支持它。但是1.6支持它,并且Sun正在努力将其向后移植到1.5中。

Eclipse 3.1中支持该注释,其他IDE也可能支持它。这允许您把代码彻底地从警告中解脱出来。如果在编译时出现警告,可以确定是您刚刚把它添加进来——以信圆帮助查看那些可能不安全的代码猜棚。随着泛型的添加,它使用起来将更趁手。

Deprecated

遗憾的是,Deprecated没那么有用。它本来旨在替换@deprecated javadoc标签,但是由于它不包含任何字段,所以也就没有方法来建议deprecated类或方法的用户应该使用什么做为替代品。大多数用法都同时需要javadoc标签和这个注释。

Override

Override表示,它所注释的方法应该重写超类中具有相同签名的方法:

@Override

public int hashCode() {

...

}

看上面的例子,如果没有在hashCode中将“C”大写,在编译时不会出现错误,但是在运行时将无法像期望的那样调用该方法。通过添加Override标签,编译器会提示它是否真正地执行了重写。

在超类发生改变的情况中,这也很有帮助。如果向该方法中添加一个新参数,而且方法本身也被重命名了,那么子类将突然不能编译,因为它不再重写超类的任何东西。

其它注释

注释在其他场景中非常有用。当不是直接修改行为而是增强行为时,特别是在添加样板代码的情况下,注释在诸如EJB和Web services这样的框架中运行得非常好。

注释不能用做预处理器。Sun的设计特别预防了完全因为注释而修改类的字节码。这样可以正确地理解该语言的成果,而且IDE之类的工具也可以执行深入的代码分析和重构之类的功能。

注释不是银弹。第一次遇到的时候,人们试图尝试各种技巧。请看下面这个从别人那里获得的建议:

public class Foo {

@Property

private int bar;

}

其思想是为私有字段bar自动创建getter和setter方法。遗憾的是,这个想法有两个失败之处:1)它不能运行,2)它使代码难以阅读和处理。 它是无法实现的,因为前面已经提到了,Sun特别阻止了对出现注释的类进行修改。

即使是可能的,它也不是一个好主意,因为它使代码可读性差。第一次看到这段代码的人会不知道该注释创建了方法。此外,如果将来您需要在这些方法内部执行一些操作,注释也是没用的。 总之,不要试图用注释去做那些常规代码可以完成的事情。

枚举

enum非常像public static final int声明,后者作为枚举值已经使用了很多年。对int所做的最大也是最明显的改进是类型安全——您不能错误地用枚举的一种类型代替另一种类型,这一点和int不同,所有的int对编译器来说都是一样的。除去极少数例外的情况,通常都应该用enum实例替换全部的枚举风格的int结构。

枚举提供了一些附加的特性。EnumMap和EnumSet这两个实用类是专门为枚举优化的标准集合实现。如果知道集合只包含枚举类型,那么应该使用这些专门的集合来代替HashMap或HashSet。

大部分情况下,可以使用enum对代码中的所有public static final int做插入替换。它们是可比的,并且可以静态导入,所以对它们的引用看起来是等同的,即使是对于内部类(或内部枚举类型)。注意,比较枚举类型的时候,声明它们的指令表明了它们的顺序值。

“隐藏的”静态方法

两个静态方法出现在所有枚举类型声明中。因为它们是枚举子类上的静态方法,而不是Enum本身的方法,所以它们在java.lang.Enum的javadoc中没有出现。

第一个是values(),返回一个枚举类型所有可能值的数组。

第二个是valueOf(),为提供的字符串返回一个枚举类型,该枚举类型必须精确地匹配源代码声明。

方法

关于枚举类型,我们最喜欢的一个方面是它可以有方法。过去您可能需要编写一些代码,对public static final int进行转换,把它从数据库类型转换为JDBC URL。而现在则可以让枚举类型本身带一个整理代码的方法。下面就是一个例子,包括DatabaseType枚举类型的抽象方法以及每个枚举实例中提供的实现:

public enum DatabaseType {

ORACLE {

public String getJdbcUrl() {...}

},

MYSQL {

public String getJdbcUrl() {...}

};

public abstract String getJdbcUrl();

}

现在枚举类型可以直接提供它的实用方法。例如:

DatabaseType dbType = ...;

String jdbcURL = dbType.getJdbcUrl();

要获取URL,必须预先知道该实用方法在哪里。

可变参数(Vararg)

正确地使用可变参数确实可以清理一些垃圾代码。典型的例子是一个带有可变的String参数个数的log方法:

Log.log(String code)

Log.log(String code, String arg)

Log.log(String code, String arg1, String arg2)

Log.log(String code, String[] args)

当讨论可变参数时,比较有趣的是,如果用新的可变参数替换前四个例子,将是兼容的:

Log.log(String code, String... args)

所有的可变参数都是源兼容的——那就是说,如果重新编译log()方法的所有调用程序,可以直接替换全部的四个方法。然而,如果需要向后的二进制兼容性,那么就需要舍去前三个方法。只有最后那个带一个字符串数组参数的方法等效于可变参数版本,因此可以被可变参数版本替换。

类型强制转换

如果希望调用程序了解应该使用哪种类型的参数,那么应该避免用可变参数进行类型强制转换。看下面这个例子,第一项希望是String,第二项希望是Exception:

Log.log(Object... objects) {

String message = (String)objects[0];

if (objects.length 1) {

Exception e = (Exception)objects[1];

// Do something with the exception

}

}

方法签名应该如下所示,相应的可变参数分别使用String和Exception声明:

Log.log(String message, Exception e, Object... objects) {...}

不要使用可变参数破坏类型系统。需要强类型化时才可以使用它。对于这个规则,PrintStream.printf()是一个有趣的例外:它提供类型信息作为自己的第一个参数,以便稍后可以接受那些类型。

协变返回

协变返回的基本用法是用于在已知一个实现的返回类型比API更具体的时候避免进行类型强制转换。在下面这个例子中,有一个返回Animal对象的Zoo接口。我们的实现返回一个AnimalImpl对象,但是在JDK 1.5之前,要返回一个Animal对象就必须声明。:

public interface Zoo {

public Animal getAnimal();

}

public class ZooImpl implements Zoo {

public Animal getAnimal(){

return new AnimalImpl();

}

}

协变返回的使用替换了三个反模式:

直接字段访问。为了规避API限制,一些实现把子类直接暴露为字段:

ZooImpl._animal

另一种形式是,在知道实现的实际上是特定的子类的情况下,在调用程序中执行向下转换:

((AnimalImpl)ZooImpl.getAnimal()).implMethod();

我看到的最后一种形式是一个具体的方法,该方法用来避免由一个完全不同的签名所引发的问题:

ZooImpl._getAnimal();

这三种模式都有它们的问题和局限性。要么是不够整洁,要么就是暴露了不必要的实现细节。

协变

协变返回模式就比较整洁、安全并且易于维护,它也不需要类型强制转换或特定的方法或字段:

public AnimalImpl getAnimal(){

return new AnimalImpl();

}

使用结果:

ZooImpl.getAnimal().implMethod();

使用泛型

我们将从两个角度来了解泛型:使用泛型和构造泛型。我们不讨论List、Set和Map的显而易见的用法。知道泛型集合是强大的并且应该经常使用就足够了。

我们将讨论泛型方法的使用以及编译器推断类型的方法。通常这些都不会出问题,但是当出问题时,错误信息会非常令人费解,所以需要了解如何修复这些问题。

泛型方法

除了泛型类型,Java 5还引入了泛型方法。在这个来自java.util.Collections的例子中,构造了一个单元素列表。新的List的元素类型是根据传入方法的对象的类型来推断的:

static T ListT Collections.singletonList(T o)

示例用法:

public ListInteger getListOfOne() {

return Collections.singletonList(1);

}

在示例用法中,我们传入了一个int。所以方法的返回类型就是ListInteger。编译器把T推断为Integer。这和泛型类型是不同的,因为您通常不需要显式地指定类型参数。

这也显示了自动装箱和泛型的相互作用。类型参数必须是引用类型:这就是为什么我们得到的是ListInteger而不是Listint。

不带参数的泛型方法

emptyList()方法与泛型一起引入,作为java.util.Collections中EMPTY_LIST字段的类型安全置换:

static T ListT Collections.emptyList()

示例用法:

public ListInteger getNoIntegers() {

return Collections.emptyList();

}

与先前的例子不同,这个方法没有参数,那么编译器如何推断T的类型呢?基本上,它将尝试使用一次参数。如果没有起作用,它再次尝试使用返回或赋值类型。在本例中,返回的是ListInteger,所以T被推断为Integer。

如果在返回语句或赋值语句之外的位置调用泛型方法会怎么样呢?那么编译器将无法执行类型推断的第二次传送。在下面这个例子中,emptyList()是从条件运算符内部调用的:

public ListInteger getNoIntegers() {

return x ? Collections.emptyList() : null;

}

因为编译器看不到返回上下文,也不能推断T,所以它放弃并采用Object。您将看到一个错误消息,比如:“无法将ListObject转换为ListInteger。”

为了修复这个错误,应显式地向方法调用传递类型参数。这样,编译器就不会试图推断类型参数,就可以获得正确的结果:

return x ? Collections.IntegeremptyList() : null;

这种情况经常发生的另一个地方是在方法调用中。如果一个方法带一个ListString参数,并且需要为那个参数调用这个传递的emptyList(),那么也需要使用这个语法。

集合之外

这里有三个泛型类型的例子,它们不是集合,而是以一种新颖的方式使用泛型。这三个例子都来自标准的Java库:

ClassT

Class在类的类型上被参数化了。这就使无需类型强制转换而构造一个newInstance成为可能。

ComparableT

Comparable被实际的比较类型参数化。这就在compareTo()调用时提供了更强的类型化。例如,String实现ComparableString。对除String之外的任何东西调用compareTo(),都会在编译时失败。

EnumE extends EnumE

Enum被枚举类型参数化。一个名为Color的枚举类型将扩展EnumColor。getDeclaringClass()方法返回枚举类型的类对象,在这个例子中就是一个Color对象。它与getClass()不同,后者可能返回一个无名类。

通配符

泛型最复杂的部分是对通配符的理解。我们将讨论三种类型的通配符以及它们的用途。

首先让我们了解一下数组是如何工作的。可以从一个Integer[]为一个Number[]赋值。如果尝试把一个Float写到Number[]中,那么可以编译,但在运行时会失败,出现一个ArrayStoreException:

Integer[] ia = new Integer[5];

Number[] na = ia;

na[0] = 0.5; // compiles, but fails at runtime

如果试图把该例直接转换成泛型,那么会在编译时失败,因为赋值是不被允许的:

ListInteger iList = new ArrayListInteger();

ListNumber nList = iList; // not allowed

nList.add(0.5);

如果使用泛型,只要代码在编译时没有出现警告,就不会遇到运行时ClassCastException。

上限通配符

我们想要的是一个确切元素类型未知的列表,这一点与数组是不同的。

ListNumber是一个列表,其元素类型是具体类型Number。

List? extends Number是一个确切元素类型未知的列表。它是Number或其子类型。

上限

如果我们更新初始的例子,并赋值给List? extends Number,那么现在赋值就会成功了:

ListInteger iList = new ArrayListInteger();

List? extends Number nList = iList;

Number n = nList.get(0);

nList.add(0.5); // Not allowed

我们可以从列表中得到Number,因为无论列表的确切元素类型是什么(Float、Integer或Number),我们都可以把它赋值给Number。

我们仍然不能把浮点类型插入列表中。这会在编译时失败,因为我们不能证明这是安全的。如果我们想要向列表中添加浮点类型,它将破坏iList的初始类型安全——它只存储Integer。

通配符给了我们比数组更多的表达能力。

为什么使用通配符

在下面这个例子中,通配符用于向API的用户隐藏类型信息。在内部,Set被存储为CustomerImpl。而API的用户只知道他们正在获取一个Set,从中可以读取Customer。

此处通配符是必需的,因为无法从SetCustomerImpl向SetCustomer赋值:

public class CustomerFactory {

private SetCustomerImpl _customers;

public Set? extends Customer getCustomers() {

return _customers;

}

}

通配符和协变返回

通配符的另一种常见用法是和协变返回一起使用。与赋值相同的规则可以应用到协变返回上。如果希望在重写的方法中返回一个更具体的泛型类型,声明的方法必须使用通配符:

public interface NumberGenerator {

public List? extends Number generate();

}

public class FibonacciGenerator extends NumberGenerator {

public ListInteger generate() {

...

}

}

如果要使用数组,接口可以返回Number[],而实现可以返回Integer[]。

下限

我们所谈的主要是关于上限通配符的。还有一个下限通配符。List? super Number是一个确切“元素类型”未知的列表,但是可能是Mnumber,或者Number的超类型。所以它可能是一个ListNumber或一个ListObject。

下限通配符远没有上限通配符那样常见,但是当需要它们的时候,它们就是必需的。

下限与上限

List? extends Number readList = new ArrayListInteger();

Number n = readList.get(0);

List? super Number writeList = new ArrayListObject();

writeList.add(new Integer(5));

第一个是可以从中读数的列表。

第二个是可以向其写数的列表。

无界通配符

最后,List?列表的内容可以是任何类型,而且它与List? extends Object几乎相同。可以随时读取Object,但是不能向列表中写入内容。

公共API中的通配符

总之,正如前面所说,通配符在向调用程序隐藏实现细节方面是非常重要的,但即使下限通配符看起来是提供只读访问,由于remove(int position)之类的非泛型方法,它们也并非如此。如果您想要一个真正不变的集合,可以使用java.util.Collection上的方法,比如unmodifiableList()。

编写API的时候要记得通配符。通常,在传递泛型类型时,应该尝试使用通配符。它使更多的调用程序可以访问API。

通过接收List? extends Number而不是ListNumber,下面的方法可以由许多不同类型的列表调用:

void removeNegatives(List? extends Number list);

构造泛型类型

现在我们将讨论构造自己的泛型类型。我们将展示一些例子,其中通过使用泛型可以提高类型安全性,我们还将讨论一些实现泛型类型时的常见问题。

集合风格(Collection-like)的函数

第一个泛型类的例子是一个集合风格的例子。Pair有两个类型参数,而且字段是类型的实例:

public final class PairA,B {

public final A first;

public final B second;

public Pair(A first, B second) {

this.first = first;

this.second = second;

}

}

这使从方法返回两个项而无需为每个两种类型的组合编写专用的类成为可能。另一种方法是返回Object[],而这样是类型不安全或者不整洁的。

在下面的用法中,我们从方法返回一个File和一个Boolean。方法的客户端可以直接使用字段而无需类型强制转换:

public PairFile,Boolean getFileAndWriteStatus(String path){

// create file and status

return new PairFile,Boolean(file, status);

}

PairFile,Boolean result = getFileAndWriteStatus("...");

File f = result.first;

boolean writeable = result.second;

集合之外

在下面这个例子中,泛型被用于附加的编译时安全性。通过把DBFactory类参数化为所创建的Peer类型,您实际上是在强制Factory子类返回一个Peer的特定子类型:

public abstract class DBFactoryT extends DBPeer {

protected abstract T createEmptyPeer();

public ListT get(String constraint) {

ListT peers = new ArrayListT();

// database magic

return peers;

}

}

通过实现DBFactoryCustomer,CustomerFactory必须从createEmptyPeer()返回一个Customer:

public class CustomerFactory extends DBFactoryCustomer{

public Customer createEmptyPeer() {

return new Customer();

}

}

泛型方法

不管想要对参数之间还是参数与返回类型之间的泛型类型施加约束,都可以使用泛型方法:

例如,如果编写的反转函数是在位置上反转,那么可能不需要泛型方法。然而,如果希望反转返回一个新的List,那么可能会希望新List的元素类型与传入的List的类型相同。在这种情况下,就需要一个泛型方法:

T ListT reverse(ListT list)

具体化

当实现一个泛型类时,您可能想要构造一个数组T[]。因为泛型是通过擦除(erasure)实现的,所以这是不允许的。

您可以尝试把Object[]强制转换为T[]。但这是不安全的。

具体化解决方案

按照泛型教程的惯例,解决方案使用的是“类型令牌”,通过向构造函数添加一个ClassT参数,可以强制客户端为类的类型参数提供正确的类对象:

public class ArrayExampleT {

private ClassT clazz;

public ArrayExample(ClassT clazz) {

this.clazz = clazz;

}

public T[] getArray(int size) {

return (T[])Array.newInstance(clazz, size);

}

}

为了构造ArrayExampleString,客户端必须把String.class传递给构造函数,因为String.class的类型是ClassString。

拥有类对象使构造一个具有正确元素类型的数组成为可能。

java 怎样限制一个函数允许传入的值仅为枚举类型的?

//定义一个枚举 

enum Color{

    GREEN,RED,BLUE

}

public class _Test{

    public static void main(String args[]){

       燃肆  printColor(Color.GREEN);       

    }

    public static void printColor(Color color){  //这样写就限制了传皮握轿入的参数必须为枚举

        System.out.println(color.name());

   皮罩 }

}

java的enum泛型的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于java 泛型e、java的enum泛型的信息别忘了在本站进行查找喔。

发布于 2023-04-13 10:04:18
收藏
分享
海报
25
目录

    忘记密码?

    图形验证码

    复制成功
    微信号: cloud7591
    如需了解更多,欢迎添加客服微信咨询。
    我知道了