泛型&&枚举
1.枚举类型
JDk1.5中新增了枚举类型,可以使用该功能取代以往定义常量的方式,同时枚举类型还赋予程序在编译时进行检查的功能。
1.1 使用枚举类型设置常量
以往设置常量,通常将常量放在接口中(final static 数据类型 常量名 = 常量值;),这样在程序中就可以直接使用,并且该常量不能被修改,因为在接口中定义常量时,该常量的修饰符为final与static,常规定义如下:
package enumeration.test; public interface RuleConstant {
//接口中声明常量
final static int Constants_A = 1;
final static int Constants_B = 12;
}
在JDK1.5版本新增枚举类型后就逐渐取代了这种常量声明方式,使用枚举类型定义常量的语法如下:
package enumeration.test; public enum Constants {
Constants_A,
Constants_B,
Constants_C
}
下面我们通过一个例子来看一下常规类型和枚举类型的使用:
package enumeration.test; public class EnumTest { //使用接口定义常量
public static void doit(int c){
switch (c) {
case RuleConstant.Constants_A:
System.out.println("接口常量Constants_A : doit()");
break;
case RuleConstant.Constants_B:
System.out.println("接口常量Constants_B : doit()");
break;
default:
System.out.println("default!");
break;
}
} //使用枚举类型定义常量--枚举类型参数约束了只能传入枚举类中的常量
public static void doit2(Constants c){
switch (c) {
case Constants_A:
System.out.println("枚举类型_Constants_A");
break;
case Constants_B:
System.out.println("枚举类型_Constants_B");
break;
case Constants_C:
System.out.println("枚举类型_Constants_C");
break;
default:
System.out.println("default!");
break;
}
} public static void main(String[] args) {
EnumTest.doit(RuleConstant.Constants_A);//接口常量
EnumTest.doit2(Constants.Constants_B);//枚举类型
EnumTest.doit(3);//参数类型不是枚举类型,那么传入参数就没有严格限制,不可以是枚举,可以是接口常量,也可以是变量
// EnumTest.doit(Constants.Constants_C);如果一个函数参数类型没有定义为枚举,那么传入枚举,编译不容过
} }
上面代码doit()函数,即便编译器不接受在接口中定义的常量参数,也不会报错,仍然正常运行;但调用doit2()方法,任意传递参数,编译器就会报错,这个函数定义了只接受枚举常量作为参数;
枚举类型除了可以在类的外部单独进行定义,还可以在类中进行定义,如同内部类一样:
package enumeration.test; public class EnumDemo{
enum Constants{
Constants_A,
Constants_B,
Constatns_C
}
}
1.2 深入理解枚举类型
1.2.1 操作枚举类型成员的方法
package enumeration.test; import org.junit.Test; public class EnumMethodsTest { //values()该方法可以将枚举类型成员实例以数组方式返回;
public static void valuesMethod(){
for (int i = 0; i < Constants.values().length; i++) {
System.out.println("Constants枚举成员:"+Constants.values()[i]);
}
} @Test
public void testValuesMethod(){
valuesMethod();
} //valueOf()将普通字符串转换为枚举实例
public static void valueOfMethod(String str){
//将字符串转换为枚举实例,不代表可以把一个字符串变成枚举类型,只是意味着,参数被设置成了枚举类型,等同于与ccalueOfMethod(Constants c)
Constants constants = Constants.valueOf(str);
switch (constants) {
case Constants_A:
System.out.println("Constants.Constants_A");
break;
case Constants_B:
System.out.println("Constants.Constants_B");
break;
case Constants_C:
System.out.println("Constants.Constants_C");
break;
default:
System.out.println("default");
break;
}
} @Test
public void testValueOfMethod(){
valueOfMethod("Constants_B");
} //campareTo(),正数代表之前,负数代表后,0代表位置相同
public static void compareToMethod(){
System.out.println("Constants_A与Constants_B相比较:"+Constants.Constants_A.compareTo(Constants.Constants_B));
System.out.println("Constants_B与Constants_A相比较:"+Constants.Constants_B.compareTo(Constants.Constants_A));
System.out.println("Constants_A与Constants_A相比较:"+Constants.Constants_A.compareTo(Constants.Constants_A));
} @Test
public void tesCompareToMethod(){
compareToMethod();
} //ordinal()用于获取某个枚举对象的索引位置
public void ordinalMethod(){
System.out.println("Constants_A的索引位置:"+Constants.Constants_A.ordinal());
System.out.println("Constants_B的索引位置:"+Constants.Constants_B.ordinal());
} @Test
public void testordinalMethod(){
ordinalMethod();
}
}
1.2.2 枚举类型中的构造函数
在枚举类型中,可以添加构造方法,但是规定构造函数必须为private修饰符所修饰,枚举类型的构造函数的定义如下:
package enumeration.constructor; import org.junit.Test; public class EnumConstructor {
enum Constants{
Constants_A("我是枚举类型A"),
Constants_B("我是枚举类型B"),
Constants_C("我是枚举类型C"),
Constants_D(3);
private String description;
private int i = 4;
//无参构造函数
private Constants(){ }
//有参构造
private Constants(String description){
this.description = description;
}
//有参构造
private Constants(int i){
this.i = this.i+i;
}
//get(),set()
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
} }
//构造函数方法
public void constructorMethod(){
for (int i = 0; i < Constants.values().length; i++) {
System.out.println(Constants.values()[i]+"调用getDescription()"+Constants.values()[i].getDescription());
}
System.out.println(Constants.valueOf("Constants_D")+"调用getI()"+Constants.valueOf("Constants_D").getI());
} @Test
public void testConstructorMethod(){
constructorMethod();
} }
package enumeration.constructor; public interface Test {
public String getDescription();
public int getI();
}
package enumeration.constructor; public enum AnyEnum implements Test{
Constants_A{
public String getDescription() {
return ("我是枚举类型A");
} public int getI() {
return i;
}
},
Constants_B{
public String getDescription() {
return ("我是枚举类型B");
} public int getI() {
return i;
}
},
Constants_C{
public String getDescription() {
return ("我是枚举类型C");
} public int getI() {
return i;
}
},
Constants_D{
public String getDescription() {
return ("我是枚举类型D");
} public int getI() {
return i;
}
};
private static int i = 5;
//测试
public static void constructorMethod(){
for (int i = 0; i < AnyEnum.values().length; i++) {
System.out.println(AnyEnum.values()[i]+"调用getDescription()"+AnyEnum.values()[i].getDescription());
System.out.println(AnyEnum.values()[i]+"调用getI()"+AnyEnum.values()[i].getI());
}
}
public static void main(String[] args) {
constructorMethod();
}
}
1.3 使用枚举类型的优势
泛型
使用泛型避免了ClassCastException异常;
2.1 回顾"向上转型"和"向下转型"
例如:我们在数组中只能存储同一类型元素,如果存储了其他类型元素,那么编译器会报错,而集合中则可以存储多种类型元素,我们遍历集合时,会把集合中的元素进行转型(众所周知迭代器遍历集合元素返回Object),此时可能会出现ClassCastException异常,此时是运行时报错,那么我们可不可以让集合中也只存储一种类型元素,当存储其他类型元素时编译器报错,将运行时异常转变为编译时异常呢?此时就引出来了泛型,泛型是JDK1.5版本中出现的, 在类或者接口的后面有一对<> , 用来约束元素的数据类型的泛型的表现形式:
* <E>
* <T>
* <QQ>
2.2 定义泛型类
其中T代表一个数据类型的名称;
利用泛型类将上面的例17.9改写:
package genericity.test; import org.junit.Test; //改写例17.9
public class OverClass<T> { private T over; public T getOver() {
return over;
} public void setOver(T over) {
this.over = over;
}
public static void main(String[] args) {
//实例一个Boolean型的对象
OverClass<Boolean> overClass1 = new OverClass<Boolean>();
//实例化一个Float型的对象
OverClass<Float> overClass2 = new OverClass<Float>();
overClass1.setOver(true);//无需进行类型转换
//泛型会自动检验传入的参数是否符合规矩
overClass2.setOver(12.3f);
System.out.println(overClass1.getOver());
System.out.println(overClass2.getOver());
} }
泛型类中可以设置非泛型的成员变量;
泛型将运行时的异常转换为了编译时的异常;
2.3 泛型的常规用法
2.3.1 定义泛型类时声明多个类型
2.3.2 定义泛型类时声明数组类性
定义泛型类时也可以声明数组类型:
package genericity.test; public class ArrayClass<T> {
private T[] array; public T[] getArray() {
return array;
} public void setArray(T[] array) {
this.array = array;
} public static void main(String[] args) {
ArrayClass<String> a = new ArrayClass<String>();
String[] array = {"1","2","3","4","5"};
a.setArray(array);
for (int i = 0; i < array.length; i++) {
System.out.println(a.getArray()[i]);
} } }
1
2
3
4
5
2.3.3 集合类声明容器的元素
2.4 泛型的高级用法
泛型的高级用法包括限制泛型可用类型、使用类型通配符等。
2.4.1 限制泛型可用的类型
2.4.2 使用类型通配符
2.4.3 继承泛型类和实现泛型接口
2.5 泛型总结
* 泛型的好处:
* a: 避免 操作隐患ClassCastException
* b: 把运行时异常 转换为 编译时异常
* c: 避免了 强制转换的操作
2.6 泛型的练习
package collection.List.genericity; import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator; /*
* 用ArrayList 存储 3个字符串,并遍历
*
* 发现当集合中存储多种数据类型的元素的时候, 可能会有操作隐患ClassCastException(转换异常)
* 怎么解决该问题呢?
* 回想以前学习的数组, 数组中存储的都是同一种数据类型的元素,如果存储了 其他类型的数据,会编译错误
* String[] arr = new String[4];
* arr[0] = "JavaSE";
* arr[1] = "JavaEE";
* arr[2] = "Android";
* arr[3] = 20;
*
* 我们也希望,我们可以将集合也只存储同一种数据类型的数据,如果存储了其他类型的数据,给出编译错误,
* 这种技术如何来实现呢? java提供了一个技术, 泛型。
*
* 泛型: 在类或者接口的后面有一对<> , 用来约束元素的数据类型的
*
* 泛型的表现形式:
* <E>
* <T>
* <QQ>
*
* 泛型怎么使用呢?
* 查看API,发现类或者接口有<>, 如果有泛型,那么必须要使用,可以避免 操作隐患ClassCastException
*
* <>里面 用来指定元素的数据类型
*
* 泛型的好处:
* a: 避免 操作隐患ClassCastException
* b: 把运行时异常 转换为 编译时异常
* c: 避免了 强制转换的操作
*/
public class ArrayListDemo { public static void main(String[] args) {
// 创建ArrayList集合,使用泛型约束集合元素类型为String
ArrayList<String> arr = new ArrayList<>();
arr.add("成不成1!");
arr.add("成不成2!");
arr.add("成不成3!");
//arr.add(20);当我们使用泛型后,集合中就只能出现允许的元素,其他类型元素编译时会报错
//通过所以直接获取指定索引元素
/*ListIterator<String> liter = arr.listIterator(0);
Object object = liter.next();
System.out.println(object.toString());*/
//遍历
ListIterator<String> liter = arr.listIterator();
while (liter.hasNext()) {
String string = liter.next();
System.out.println(string);
}
//遍历
// Iterator<String> litera = arr.iterator();
// while (litera.hasNext()) {
// //类型转换
// String str = (String) litera.next();
// System.out.println(str);
// }
} }
package collection.List.genericity; import java.util.Enumeration;
import java.util.Vector; /*
* 使用Vector集合 存储字符串对象,并遍历 (使用泛型)
*/
public class VectorDemo { public static void main(String[] args) {
// 创建Vector集合并遍历集合
Vector<String> vec = new Vector<>();
vec.add("伤不起,");
vec.add("啊");
vec.add("真的真的伤不起");
//将元素添加到指定位置
vec.add(2, "伤不起");
Enumeration<String> enu = vec.elements();
while (enu.hasMoreElements()) {
String string = (String) enu.nextElement();
System.out.println(string);
}
} }
2.7 泛型类与泛型方法
在上面我们看到了jdk提供的一些泛型,那么在现实开发中,我们可不可以进一步对泛型加以利用呢?答案是肯定的
package collection.List.genericity;
/*
* 泛型类: 类上有泛型修饰, 就是泛型类
*/
public class Tool<QQ> { public void show1(){
System.out.println("haha");
} public void show2(String str){
System.out.println(str);
} public void show3(Integer i){
System.out.println(i);
} public void show4(QQ qq){
System.out.println(qq);
}
}
package collection.List.genericity;
/*
* 泛型方法: 把泛型定义在方法上,在Tool类上,我们发现可以把类定义成泛型类,那么可不可以定义泛型方法呢
*/
//public class Tool2<QQ> {
// public void show (QQ qq) {
// System.out.println(qq);
// }
//
// //不想是QQ类型
// public void method(TT tt){
//
// }
//}
public class ToolMethod {
//TT类型
public<TT> void Method(TT tt){
System.out.println(tt.toString());
}
}
package collection.List.genericity; public interface ITool<QQ> {
//接口的方法都是抽象方法,抽象方法没有实现体
public abstract void method(QQ qq);
}
package collection.List.genericity;
//实现 implements
/*
* 泛型接口
*
* 创建实现类的时候,明确泛型的数据类型
* 创建实现类的时候,没有明确泛型的数据类型的时候,需要在类上也给出泛型
*/
//public class Tool3Imlp implements Tool3<String>{
//
// @Override
// public void show(String qq) {
// System.out.println(qq);
// }
//}
public class ToolImple<QQ> implements ITool<QQ>{ @Override
public void method(QQ qq) {
System.out.println(qq.toString()); } }
package collection.List.genericity; public class ToolTest { public static void main(String[] args) {
//泛型类
Tool<String> tool = new Tool<>();
String str = "左宗棠";
tool.show1();
tool.show2(str);
tool.show3(7);
tool.show4(str);
//tool.show4(7);泛型类,约束了参数类型只能是String类型
//tool.show4(tool);
//泛型方法
ToolMethod tm = new ToolMethod();
tm.<String>Method(str);
//tm.<String>Method(7);泛型方法决定了实参类型
//泛型接口
ITool<String> it = new ToolImple<>();
it.method(str);
//it.method(7);泛型决定了传入参数类型
} }
package cn.itcast.demo1; import java.util.ArrayList;
import java.util.List; import org.junit.Test; public class Demo1 {
/*
* 泛型方法有自己的类型变量
* 泛型方法中的类型变量声明,必须在返回值之前!
* * 通常泛型方法的返回值和参数中都会使用类型变量
* * 泛型方法中声明的类型变量只能在当前方法内使用,其他方法不能使用!
* * 通过调用泛型方法时,不用显式的传递类型变量,而是通过参数类型隐式传递
*/
public static <T> T get(T[] array) {
return array[array.length / 2];
} @Test
public void fun3() {
String[] strs = {"hello", "world", "java", "zhangSan", "liSi"};
// 显式为泛型方法的类型变量赋值
String s1 = Demo1.<String>get(strs);
System.out.println(s1);
// 隐式为泛型方法的类型变量赋值
String s = get(strs);//等同与给T赋值了,赋的是String
System.out.println(s);
} @Test
public void fun1() {
List<String> arr = new ArrayList<String>();
arr.add("hello");
String s = arr.get(0);
System.out.println(s);
} @Test
public void fun2() {
A<String> a = new A<String>();
A<Integer> a2 = new A<Integer>();
}
} /*
* 泛型类,又叫参数化类型(A<T>)
*/
class A<T> {
private T t; /*
* 它是泛型类的方法,不是泛型方法
*/
public T getT() {
return t;
} public void setT(T t) {
T bean = t;
this.t = t;
} // 泛型类中,类型变量只有static方法中不能使用
// public static void fun() {
// T bean1;
// }
}
package cn.itcast.demo2; import java.util.Comparator; /*
* 泛型的继承
*/
public class Demo1 {
public void fun1() {
AA1 aa1 = new AA1();
AA2<String> aa2 = new AA2<String>();
AA3<Long> aa3 = new AA3<Long>();
}
} class A<T> {
private T bean; public T getBean() {
return bean;
} public void setBean(T bean) {
this.bean = bean;
}
} /*
* 如果父类是泛型类,那么子类需要在继承时给父类传递变量类型!
*/
class AA1 extends A<String> { } class AA2<T> extends A<Integer> { } class AA3<T> extends A<T> { } class MyComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
return 0;
}
}
泛型&&枚举的更多相关文章
- 关于IEnumerator<T>泛型枚举器 和 IEnumerable<T>
在开发中我们经常会用到 IEnumerable<T> xxx 或者 List<T> xxx 这种集合或者集合接口,实际上就是一个线性表嘛然后结合C#提供的语法糖 foreach ...
- TypeScript Generics(泛型)
软件工程的一个主要部分就是构建组件,构建的组件不仅需要具有明确的定义和统一的接口,同时也需要组件可复用.支持现有的数据类型和将来添加的数据类型的组件为大型软件系统的开发过程提供很好的灵活性. 在C#和 ...
- CLR via C#深解笔记六 - 泛型
面向对象编程一个好处就是“代码重用”,极大提高了开发效率.如是,可以派生出一个类,让它继承基类的所有能力,派生类只需要重写虚方法,或添加一些新的方法,就可以定制派生类的行为,使之满足开发人员的需求. ...
- [CLR via C#]12. 泛型
泛型(generic)是CLR和编程语言提供一种特殊机制,它支持另一种形式的代码重用,即"算法重用". 简单地说,开发人员先定义好一个算法,比如排序.搜索.交换等.但是定义算法的开 ...
- 理解C#泛型
在C# 2.0中引入了泛型,泛型的出现解决了编码中的很多问题.相信大家一定经常用到"System.Collections.Generic"命名空间中的泛型集合类("Gen ...
- CLR类型设计之泛型(一)
在讨论泛型之前,我们先讨论一下在没有泛型的世界里,如果我们想要创建一个独立于被包含类型的类和方法,我们需要定义objece类型,但是使用object就要面对装箱和拆箱的操作,装箱和拆箱会很损耗性能,我 ...
- C#图解教程 第十八章 枚举器和迭代器
枚举器和迭代器 枚举器和可枚举类型 foreach语句 IEnumerator接口 使用IEnumerable和IEnumerator的示例 泛型枚举接口迭代器 迭代器块使用迭代器来创建枚举器使用迭代 ...
- 谈一谈泛型(Generic)
谈一谈泛型 首先,泛型是C#2出现的.这也是C#2一个重要的新特性.泛型的好处之一就是在编译时执行更多的检查. 泛型类型和类型参数 泛型的两种形式:泛型类型( 包括类.接口.委托和结构 没有泛型枚 ...
- 苹果新的编程语言 Swift 语言进阶(十六)--泛型
泛型允许你定义一个宽松.可重用的函数或者类型,使用泛型能够避免代码的重复,也能以更清楚和抽象的方式来表达程序的意图. 泛型是Swift语言提供的强大功能之一,Swift提供的许多标准库都使用了泛型来创 ...
随机推荐
- Lights Out Game
Lights Out Game 在线的游戏:http://www.neok12.com/games/lights-out/lights-out.htm 瞎试一阵子未成之后,终于找到了标准答案:http ...
- 关于老教授之家项目的思考 && 中国互联网+大赛培训
最近在做中国互联网+竞赛相关的项目,有一点思考在这里记录下来,算是一份经历,日后可以再回顾,这也是我真正参加的一个大型比赛,作为技术人员可能更多的是从事技术,但是在其他方面能贡献自己的一份力量也是不错 ...
- 案例53-crm练习修改客户功能实现
1 CustomerAction 完整代码: package www.test.web.action; import java.io.File; import org.apache.commons.l ...
- ubuntu install fonts
sudo apt-get install ttf-wqy-zenhei
- 批量处理标签属性中document.getElementsByName()的替代方案
背景 今天在逛知乎时候,看到一个JavaScript方面的问题: 最近在学习JavaScript DOM,就好奇地查阅资料,以及请教学长,得到下面解答: http://www.w3help.org/z ...
- 使用CSS选择器进行元素定位
在selenium webdriver中,支持使用CSS选择器来进行元素定位,事实在真的投入工作,大量编辑用例和元素定位的时候,使用css 和 xpath才是经常需要用到的. 之前有专门讲过使用xpa ...
- Container&injection(容器与注入思想)
container 为了更好理解JAVA容器,查询了容器的概念以及容器的诞生原因和历史: 容器技术是怎么一个概念呢?其实,IT里的容器技术是英文单词Linux Container的直译.contain ...
- wamp的安装
1.下载wamp. 2.如果安装了apache,先卸载. 进入到你的apache的bin目录,输入指令 httpd.exe -k stop停止服务,再输入httpd.exe -k uninstall. ...
- Java Programming Guidelines
This appendix contains suggestions to help guide you in performing low-level program design and in w ...
- Eclipse Action
Interface IAction package org.eclipse.jface.action; import org.eclipse.core.commands.IHandlerAttribu ...