1 泛型(generic)
1.1 说明
增强了java的类型安全,可以在编译期间对容器内的对象进行类型检查,在运行期不必进行类型的转换。而在j2se5之前必须在运行期动态进行容器内对象的检查及转换
减少含糊的容器,可以定义什么类型的数据放入容器
|
arraylist<integer> listofintegers; // <type_name> is new to the syntax integer integerobject; listofintegers = new arraylist<integer>(); // <type_name> is new to the syntax listofintegers.add(new integer(10)); // 只能是integer类型 integerobject = listofintegers.get(0); // 取出对象不需要转换 |
1.2 用法
声明及实例化泛型类:
hashmap<string,float> hm = new hashmap<string,float>(); //不能使用原始类型 genlist<int> nlist = new genlist<int>(); //编译错误
j2se 5.0目前不支持原始类型作为类型参数(type parameter)
定义泛型接口:
public interface geninterface<t> { void func(t t); }
定义泛型类:
public class arraylist<itemtype> { ... } public class genmap<t, v> { ... } 例1: public class mylist<element> extends linkedlist<element> { public void swap(int i, int j) { element temp = this.get(i); this.set(i, this.get(j)); this.set(j, temp); } public static void main(string[] args) { mylist<string> list = new mylist<string>(); list.add("hi"); list.add("andy"); system.out.println(list.get(0) + " " + list.get(1)); list.swap(0,1); system.out.println(list.get(0) + " " + list.get(1)); } }
例2:
|
public class genlist <t>{ private t[] elements; private int size = 0; private int length = 0; public genlist(int size) { elements = (t[])new object[size]; this.size = size; } public t get(int i) { if (i < length) { return elements[i]; } return null; }
public void add(t e) { if (length < size - 1) elements[length++] = e; } } |
泛型方法:
public class testgenerics{ public <t> string getstring(t obj) { //实现了一个泛型方法 return obj.tostring(); } public static void main(string [] args){ testgenerics t = new testgenerics(); string s = "hello"; integer i = 100; system.out.println(t.getstring(s)); system.out.println(t.getstring(i)); } }
1.3 受限泛型
受限泛型是指类型参数的取值范围是受到限制的. extends关键字不仅仅可以用来声明类的继承关系, 也可以用来声明类型参数(type parameter)的受限关系.例如, 我们只需要一个存放数字的列表, 包括整数(long, integer, short), 实数(double, float), 不能用来存放其他类型, 例如字符串(string), 也就是说, 要把类型参数t的取值泛型限制在number极其子类中.在这种情况下, 我们就可以使用extends关键字把类型参数(type parameter)限制为数字
示例
|
public class limited<t extends number> { public static void main(string[] args) { limited<integer> number; //正确 limited<string> str; //编译错误 } } |
1.4 泛型与异常
类型参数在catch块中不允许出现,但是能用在方法的throws之后。例:
|
import java.io.*; interface executor<e extends exception> { void execute() throws e; } public class genericexceptiontest { public static void main(string args[]) { try { executor<ioexception> e = new executor<ioexception>() { public void execute() throws ioexception{ // code here that may throw an // ioexception or a subtype of // ioexception } }; e.execute(); } catch(ioexception ioe) { system.out.println("ioexception: " + ioe); ioe.printstacktrace(); } } } |
1.5 泛型的通配符"?"
"?"可以用来代替任何类型, 例如使用通配符来实现print方法。
public static void print(genlist<?> list) {})
1.6 泛型的一些局限型
不能实例化泛型
t t = new t(); //error
不能实例化泛型类型的数组
t[] ts= new t[10]; //编译错误
不能实例化泛型参数数
pair<string>[] table = new pair<string>(10); // error
类的静态变量不能声明为类型参数类型
public class genclass<t> {
private static t t; //编译错误
}
泛型类不能继承自throwable以及其子类
public genexpection<t> extends exception{} //编译错误
不能用于基础类型int等
pair<double> //error
pair<double> //right
2 增强循环(enhanced for loop)
旧的循环
|
linkedlist list = new linkedlist(); list.add("hi"); list.add("everyone!"); list.add("was"); list.add("the"); list.add("pizza"); list.add("good?"); for (int i = 0; i < list.size(); i++) system.out.println((string) list.get(i)); //或者用以下循环 //for(iterator iter = list.iterator(); iter.hasnext(); ) { //integer stringobject = (string)iter.next(); // ... more statements to use stringobject... //} 新的循环 linkedlist<string> list = new linkedlist<string>(); list.add("hi"); list.add("everyone!"); list.add("was"); list.add("the"); list.add("pizza"); list.add("good?"); for (string s : list) system.out.println(s); |
很清晰、方便,一看便知其用法
3 可变参数(variable arguments)
实现了更灵活的方法参数传入方式,system.out.printf是个很好的例子
用法:void test(object … args)
一个很容易理解的例子
|
public static int add(int ... args){ int total = 0; for (int i = 0; i < args.length; i++) total += args[i]; return total; } public static void main(string[] args){ int a; a = varargs.add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); system.out.println(a); } |
4 自动实现装箱和解箱操作(boxing/unboxing conversions)
说明:实现了基本类型与外覆类之间的隐式转换。基本类型至外覆类的转换称为装箱,外覆类至基本类型的转换为解箱。这些类包括
primitive type reference type
boolean boolean
byte byte
char character
short short
int integer
long long
float float
double double
例如,旧的实现方式
|
integer intobject; int intprimitive; arraylist arraylist = new arraylist(); intprimitive = 11; intobject = new integer(intprimitive); arraylist.put(intobject); // 不能放入int类型,只能使integer |
新的实现方式
|
int intprimitive; arraylist arraylist = new arraylist(); intprimitive = 11; //在这里intprimitive被自动的转换为integer类型 arraylist.put(intprimitive); |
5 静态导入(static imports)
很简单的东西,看一个例子:
没有静态导入
math.sqrt(math.pow(x, 2) + math.pow(y, 2));
有了静态导入
import static java.lang.math.*;
sqrt(pow(x, 2) + pow(y, 2));
其中import static java.lang.math.*;就是静态导入的语法,它的意思是导入math类中的所有static方法和属性。这样我们在使用这些方法和属性时就不必写类名。
需要注意的是默认包无法用静态导入,另外如果导入的类中有重复的方法和属性则需要写出类名,否则编译时无法通过。
6 枚举类(enumeration classes)
用法:public enum name {types, ….}
简单的例子:
|
public enum colors {red, yellow, blue, orange, green, purple, brown, black} public static void main(string[] args){ colors mycolor = colors.red; system.out.println(mycolor); } |
又一个简单例子:
|
import java.util.*; enum operatingsystems {windows, unix, linux, macintosh} public class enumexample1 { public static void main(string args[]) { operatingsystems os; os = operatingsystems.windows; switch(os) { case windows: system.out.println(“you chose windows!”); break; case unix: system.out.println(“you chose unix!”); break; case linux: system.out.println(“you chose linux!”); break; case macintosh: system.out.println(“you chose macintosh!”); break; default: system.out.println(“i don’t know your os.”); break; } } } |
应运enum简写的例子:
|
import java.util.*; public class enumtest { public static void main(string[] args) { scanner in = new scanner(system.in); system.out.print("enter a size: (small, medium, large, extra_large) "); string input = in.next().touppercase(); size size = enum.valueof(size.class, input); system.out.println("size=" + size); system.out.println("abbreviation=" + size.getabbreviation()); if (size == size.extra_large) system.out.println("good job--you paid attention to the _."); } } enum size { small("s"), medium("m"), large("l"), extra_large("xl"); private size(string abbreviation) { this.abbreviation = abbreviation; } public string getabbreviation() { return abbreviation; } private string abbreviation; } |
enum类中拥有方法的一个例子:
|
enum programflags { showerrors(0x01), includefileoutput(0x02), usealternateprocessor(0x04); private int bit; programflags(int bitnumber) { bit = bitnumber; } public int getbitnumber() { return(bit); } } public class enumbitmapexample { public static void main(string args[]) { programflags flag = programflags.showerrors; system.out.println(“flag selected is: “ + flag.ordinal() + “ which is “ + flag.name()); } } |
7 元数据(meta data)
请参考
http://www-900.ibm.com/developerworks/cn/java/j-annotate1/
http://www-900.ibm.com/developerworks/cn/java/j-annotate2.shtml
8 building strings(stringbuilder类)
在jdk5.0中引入了stringbuilder类,该类的方法不是同步(synchronized)的,这使得它比stringbuffer更加轻量级和有效。
9 控制台输入(console input)
在jdk5.0之前我们只能通过joptionpane.showinputdialog进行输入,但在5.0中我们可以通过类scanner在控制台进行输入操作
例如在1.4中的输入
| string input = joptionpane.showinputdialog(prompt); int n = integer.parseint(input); double x = double.parsedouble(input); s = input; |
在5.0中我们可以
|
scanner in = new scanner(system.in); system.out.print(prompt); int n = in.nextint(); double x = in.nextdouble(); string s = in.nextline(); |
jdk5之前我们覆盖一个方法时我们无法改变被方法的返回类型,但在jdk5中我们可以改变它
例如1.4中我们只能
|
public object clone() { ... } ... employee cloned = (employee) e.clone(); |
但是在5.0中我们可以改变返回类型为employee
|
public employee clone() { ... } ... employee cloned = e.clone(); |
增加了类似c的格式化输入输出,简单的例子:
|
public class testformat{ public static void main(string[] args){ int a = 150000, b = 10; float c = system.out.printf("%4d %4d%n", a, b); system.out.printf("%x %x%n", a, b); system.out.printf("% system.out.printf("%1.3e %1.3e%n", c, d*100); } } |
150000 10
5.01 3.1
5.010e+00 3.140e+02
下面是一些格式化参数说明(摘自core java 2 volume i - fundamentals, seventh edition)
table 3-5. conversions for printf
|
conversion character |
type |
example |
|
d |
decimal integer |
159 |
|
x |
hexadecimal integer |
|
|
o |
octal integer |
237 |
|
f |
fixed-point floating-point |
15.9 |
|
e |
exponential floating-point |
1.59e+01 |
|
g |
general floating-point (the shorter of e and f) |
|
|
a |
hexadecimal floating point |
0x1.fccdp3 |
|
s |
string 扫描关注微信公众号 |
闽公网安备 35060202000074号