JAVA语言学习笔记(一)
1 一切都是对象
JAVA中所有代码都必须写在类里面。
方法名和参数列表(它们合起来被称为"方法签名")唯一地标识出某个方法。联想多态。
基本数据类型的"局部变量"相对于类的数据成员不会自动初始化,但会在编译时报错误。
面向对象的程序设计通常可简单的归为"向对象发送消息"。
JAVA中,除了基本数据类型,其它对象传递的是引用。
static域或方法,有特定的存储空间和可以直接用类直接调用(static字段对每个类来说都只有一份存储空间,而非static字段则是对每个对象有一个存储空间)。
2 操作符
观察一下代码,猜测输出的结果。
1 class Tank { 2 int level; 3 } 4 5 public class Think { 6 public static void main(String[] args) { 7 Tank t1 = new Tank(); 8 Tank t2 = new Tank(); 9 t1.level = 9; 10 t2.level = 47; 11 System.out 12 .println("1: t1.level:" + t1.level + ", t2.level:" + t2.level); 13 t1 = t2; 14 System.out 15 .println("2: t1.level:" + t1.level + ", t2.level:" + t2.level); 16 t1.level = 27; 17 System.out 18 .println("3: t1.level:" + t1.level + ", t2.level:" + t2.level); 19 } 20 }
重点在13行,内部做了什么?
结果如下所示:
equals和==号的运用,特别注意String类的特点
1 class Value{ 2 3 String i; 4 } 5 public class EqualsMethods { 6 public static void main(String[] args){ 7 Value v1 = new Value(); 8 Value v2 = new Value(); 9 v1.i = v2.i = "10"; //"10"是一个字符串常量,存储在常量区 10 11 System.out.println(v1.equals(v2)); //false 12 System.out.println(v1.i.equals(v2.i)); //true 13 System.out.println(v1.i == v2.i); //true 14 15 } 16 }
String类打印。 观察下面代码的第9行程序和注释的内容。也可以是(观察下面代码,判断是否发生错误?编译错误还是运行时错误?那类错误?)
1 package thinkJava; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public class InfiniteRecursion { 7 8 public String toString(){ 9 return "InfiniteRecursion address: " + super.toString() + "\n"; //this ---> super.toString() 10 } 11 public static void main(String[] args){ 12 List<InfiniteRecursion> v = new ArrayList<InfiniteRecursion>(); 13 for(int i = 0; i < 10; i++){ 14 v.add(new InfiniteRecursion()); 15 } 16 System.out.println(v); 17 } 18 } 19 //如果你真的想打印出对象的内存地址,而是应该调用Object.toString()方法。 20 //这才是负责此任务的方法。所以。你不该用this,而是应该调用super.toString()方法。
如果用this方法,则发生递归死循环,很快给出运行时错误--
正确的做法是用父类的super.toString()方法。
3 接口
抽象类,枚举、继承、类型、多态、循环、import方式
1 package thinkJava; 2 3 import testzd.Note; //testzd package中的Note.java文件 4 5 abstract class Instrument { 6 private int i; 7 8 public abstract void play(Note n); 9 10 public String what() { 11 return "Instrument"; 12 } 13 14 public abstract void adjust(); 15 16 } 17 18 // 继承抽象类,抽象方法一定要实现。如果不实现父类中的抽象方法,则子类必须也是抽象类,否则编译通不过。 19 class Wind extends Instrument { 20 public void play(Note n) { 21 System.out.println("Wind.pay() " + n); 22 } 23 24 public String what() { 25 return "wind"; 26 } 27 28 public void adjust() { 29 }; 30 } 31 32 class Percussion extends Instrument { 33 public void play(Note n) { 34 System.out.println("Percussion.pay() " + n); 35 } 36 37 public String what() { 38 return "Percussion"; 39 } 40 41 public void adjust() { 42 } 43 } 44 45 class Stringed extends Instrument { 46 public void play(Note n) { 47 System.out.println("Stringed.play() " + n); 48 } 49 50 public String what() { 51 return "Stringed"; 52 } 53 54 public void adjust() { 55 } 56 } 57 58 class Brass extends Wind { 59 public void play(Note n) { 60 System.out.println("Brass.play() " + n); 61 } 62 63 public void adjust() { 64 System.out.println("Brass.adjust()"); 65 } 66 } 67 68 class Woodwind extends Wind { 69 public void play(Note n) { 70 System.out.println("Woodwind.play() " + n); 71 } 72 73 public String what() { 74 return "Woodwind"; 75 } 76 } 77 78 public class Music4 { 79 80 static void tune(Instrument i) { 81 i.play(Note.MIDDLE_C); 82 i.play(Note.C_SHARP); 83 i.play(Note.B_FLAT); 84 } 85 86 static void tuneAll(Instrument[] e) { 87 for (Instrument i : e) { //遍历的方式 88 tune(i); 89 } 90 } 91 92 public static void main(String[] args) { 93 Instrument[] orchestra = { new Wind(), new Percussion(), 94 new Stringed(), new Brass(), new Woodwind() }; //Instrument 类型的,但是放进了好多子类型的。父类是抽象的,不能实例化。保证安全。 95 tuneAll(orchestra); 96 } 97 98 } 99 //猜测下输出的结果,以及为什么这么繁琐的搞这么多的类?
testzd package中的Note.java文件如下所示
package testzd; public enum Note { MIDDLE_C, C_SHARP, B_FLAT; // Etc. }
运行的结果是:
abstract 修饰的类中可以没有抽象方法,即所有的方法全部都有实现体。但是依旧不能为抽象类定义对象。
interface关键字使抽象的概念更向前迈进了一部。interface是一个完全抽象的类。
1 interface中可以有字段和方法
2 字段隐式地是static 和final的
3 方法隐式地是public的
如下是一个接口的定义
1 interface Inst { 2 int VALUE = 5; // static & final 3 4 // cannot have method definitions 5 void play(Note n); // Automaticaly public 6 7 void adjust(); 8 }
foreach迭代,可变参数列表
1 class A{} 2 public class TestObject{ 3 static void printArray(Object...args){ 4 for(Object obj:args){ 5 System.out.print(obj + " "); 6 } 7 System.out.println(); 8 } 9 public static void main(String[] args){ 10 11 printArray(new Integer(47), new Float(12.3F), new Double(23.45)); 12 printArray(47, 3.14F, 11.11); 13 printArray(new A(), new A(), new A()); 14 printArray((Object[])new Integer[]{1, 2, 3, 4}); 15 printArray(); //Empty list is Ok. 16 17 } 18 }
输出结果
1 47 12.3 23.45 2 47 3.14 11.11 3 thinkJava.A@1d1acd3 thinkJava.A@a981ca thinkJava.A@8814e9 4 1 2 3 4
4 构造器与重载
默认构造器只有在没有明确创造构造器时候才会起作用。
下述代码,充分表明了this关键的作用和特点。
1 只可以用this关键字在构造器里调用其它构造器。
2 构造器的调用必须在语句的第一位置。
1 package thinkJava; 2 3 public class Flower { 4 int petalCount = 0; 5 String s = "initial value"; 6 7 Flower(int petals) { 8 petalCount = petals; 9 System.out.println("Constructor w/ int arg only. petalCount = " 10 + petalCount); 11 } 12 13 Flower(String ss) { 14 System.out.println("Constructor w/ String arg only, s = " + ss); 15 s = ss; 16 } 17 18 Flower(String s, int petals) { 19 this(petals); 20 // this(s); //Can't call two! 21 this.s = s; // Another use of "this" 22 System.out.println("petalCount = " + petalCount + " s = " + s); 23 } 24 25 Flower() { 26 this("hi", 47); 27 System.out.println("Default constructor(no args)"); 28 } 29 30 void printPetalCount() { 31 // this(11); //Not inside non-Constructor 32 System.out.println("petalCount = " + petalCount + " s = " + s); 33 } 34 35 public static void main(String[] args) { 36 Flower x = new Flower(); 37 x.printPetalCount(); 38 } 39 }
猜猜输出是什么?
Constructor w/ int arg only. petalCount = 47
petalCount = 47 s = hi
Default constructor(no args)
petalCount = 47 s = hi
变量的初始化顺序
1 package javaTest; 2 3 class Windows { 4 Windows(int marker) { 5 System.out.println("Windows(" + marker + ")"); 6 } 7 } 8 9 class House { 10 Windows w1 = new Windows(1); 11 12 House() { 13 System.out.println("House()"); 14 w3 = new Windows(33); 15 } 16 17 Windows w2 = new Windows(2); 18 19 void f() { 20 System.out.println("f()"); 21 } 22 23 Windows w3 = new Windows(3); 24 } 25 26 public class OrderOfInitialzation { 27 public static void main(String[] args) { 28 House h = new House(); 29 h.f(); 30 } 31 }
输出的结果是:
Windows(1)
Windows(2)
Windows(3)
House()
Windows(33)
f()
添加静态变量后的初始化情况
1 package thinkJava; 2 3 class Bowl { 4 Bowl(int maker) { 5 System.out.println("Bowl(" + maker + ")"); 6 } 7 8 void f1(int maker) { 9 System.out.println("f1(" + maker + ")"); 10 } 11 } 12 13 class Table { 14 static Bowl bowl1 = new Bowl(1); 15 16 Table() { 17 System.out.println("Table()"); 18 bowl2.f1(1); 19 } 20 21 void f2(int marker) { 22 System.out.println("f2(" + marker + ")"); 23 } 24 25 static Bowl bowl2 = new Bowl(2); 26 } 27 28 class Cupboard { 29 Bowl bowl3 = new Bowl(3); 30 static Bowl bowl4 = new Bowl(4); 31 32 Cupboard() { 33 System.out.println("Cupboard()"); 34 bowl4.f1(2); 35 } 36 37 void f3(int maker) { 38 System.out.println("f3(" + maker + ")"); 39 } 40 41 static Bowl bowl5 = new Bowl(5); 42 } 43 44 public class StaticInitialzation { 45 public static void main(String[] args) { 46 System.out.println("Creating new Cupboard() in main"); 47 new Cupboard(); 48 System.out.println("Creating new Cupboard() in main"); 49 new Cupboard(); 50 table.f2(1); 51 cupboard.f3(1); 52 } 53 54 static Table table = new Table(); 55 static Cupboard cupboard = new Cupboard(); 56 }
猜测结果是什么?
1 Bowl(1) 2 Bowl(2) 3 Table() 4 f1(1) 5 Bowl(4) 6 Bowl(5) 7 Bowl(3) 8 Cupboard() 9 f1(2) 10 Creating new Cupboard() in main 11 Bowl(3) 12 Cupboard() 13 f1(2) 14 Creating new Cupboard() in main 15 Bowl(3) 16 Cupboard() 17 f1(2) 18 f2(1) 19 f3(1)
4.1 static方法的特性
有些人认为static方法不是"面向对象"的,因为它们的确具有全局函数的语义;使用static方法时,
由于不存在this,所以不是通过"向对象发送消息"的方式完成的。的确,要是在代码中出现了大量的static方法,就该重新考虑自己的设计了。
static是可以修饰属性 方法 内部类 自由块,不能修改方法的局部变量。
5 异常抛出
异常可以直接抛出,也可以循环自恢复。
1 package exceptions; 2 3 public class Ex5 { 4 private static int[] ia = new int[2]; 5 private static int x = 5; 6 7 public static void main(String[] args) { 8 while (true) { 9 try { 10 ia[x] = 1; 11 System.out.println("ia[" + x + "]= " + ia[x]); 12 break; 13 } catch (Exception e) { 14 x--; 15 System.err.println("Caught ArrayIndexOutOfBoundsExceptions"); 16 e.printStackTrace(); 17 } finally { 18 System.out.println("Are we done yet?"); 19 } 20 } 21 System.out.println("Now, we are done."); 22 23 } 24 }
结果是:
自定义异常
1 package exceptions; 2 3 class MyExceptions extends Exception { 4 5 private static final long serialVersionUID = 1L; 6 private int x; 7 8 public MyExceptions() { 9 } 10 11 public MyExceptions(String msg) { 12 super(msg); 13 } 14 15 public MyExceptions(String msg, int x) { 16 super(msg); 17 this.x = x; 18 } 19 20 public int val() { 21 return x; 22 } 23 24 public String getMessage() { 25 return "Detial Message: " + x + " " + super.getMessage(); 26 } 27 } 28 29 public class ExtraFeatures { 30 public static void f() throws MyExceptions { 31 System.out.println("Throwing MyException from f()"); 32 throw new MyExceptions(); 33 } 34 35 public static void g() throws MyExceptions { 36 System.out.println("Throwing MyException from g()"); 37 throw new MyExceptions("Originated in g()"); 38 } 39 40 public static void h() throws MyExceptions { 41 System.out.println("Throwing MyException from h()"); 42 throw new MyExceptions("Originated in g()", 47); 43 } 44 45 public static void main(String[] args) { 46 try { 47 f(); 48 } catch (MyExceptions e) { 49 e.printStackTrace(System.out); 50 } 51 try { 52 g(); 53 } catch (MyExceptions e) { 54 e.printStackTrace(System.out); 55 } 56 try { 57 h(); 58 } catch (MyExceptions e) { 59 e.printStackTrace(System.out); 60 System.out.println("e.val() = " + e.val()); 61 } 62 } 63 }
运行的结果:
5.1 异常列表/异常说明
1 package exceptions; 2 3 class ExceptionA extends Exception { 4 5 private static final long serialVersionUID = 1L; 6 7 public ExceptionA(String msg) { 8 super(msg); 9 } 10 } 11 12 class ExceptionB extends Exception { 13 14 private static final long serialVersionUID = 1L; 15 16 public ExceptionB(String msg) { 17 super(msg); 18 } 19 } 20 21 class ExceptionC extends Exception { 22 23 private static final long serialVersionUID = 1L; 24 25 public ExceptionC(String msg) { 26 super(msg); 27 } 28 } 29 30 public class Ex9 { 31 /* 32 * 异常说明使用了附加关键字throws,后面紧接着一个所有潜在异常类型的列表 33 */ 34 public static void f(int x) throws ExceptionA, ExceptionB, ExceptionC { 35 if (x > 0) 36 throw new ExceptionA("Exception A"); 37 if (x == 0) 38 throw new ExceptionB("Exception B"); 39 if (x < 0) 40 throw new ExceptionC("Exception C"); 41 } 42 43 public static void main(String[] args) { 44 try { 45 f(-1); 46 f(0); 47 f(1); 48 } catch (Exception e) { 49 System.out.println("Caught Exception"); 50 e.printStackTrace(System.out); 51 } 52 } 53 }
输出的结果是
6 继承
构造器的初始化
1 package reusing; 2 /* 3 * 对于基类的正确初始化是至关重要的。 4 * 在构造器中调用基类构造器来执行初始化。 5 * 基类构造器具有执行基类初始化方法所需要的知识和能力。 6 * 导出类构造器会自动调用基类的默认构造器,但是如果基类明确定义了带参数的构造器, 7 * 就必须在导出类构造器中明确的调用。 8 */ 9 10 class Game{ 11 Game(int i){ 12 System.out.println("Game Constructor"); 13 } 14 } 15 class BoardGame extends Game{ 16 BoardGame(int i) { 17 super(i); 18 System.out.println("BoardGame Constructor"); 19 } 20 } 21 public class Chess extends BoardGame{ 22 Chess(int i){ 23 super(i); 24 System.out.println("Chess Constructor"); 25 } 26 public static void main(String[] args){ 27 new Chess(1); 28 } 29 }
运行结果
1 Game Constructor 2 BoardGame Constructor 3 Chess Constructor
手动清理以及清理顺序例子
1 package reusing; 2 class Shape{ 3 Shape(int i){ 4 System.out.println("Shape Constructor."); 5 } 6 void dispose(){ 7 System.out.println("Shape dispose."); 8 } 9 } 10 11 class Circle extends Shape{ 12 Circle(int i) { 13 super(i); 14 System.out.println("Drawing Circle"); 15 } 16 void dispose(){ 17 System.out.println("Erasing Circle"); 18 super.dispose(); 19 } 20 } 21 22 class Triangle extends Shape{ 23 Triangle(int i) { 24 super(i); 25 System.out.println("Drawing Triangle"); 26 } 27 void dispose(){ 28 System.out.println("Erasing Triangle"); 29 super.dispose(); 30 } 31 } 32 class Line extends Shape{ 33 private int start, end; 34 Line(int start, int end){ 35 super(start); 36 this.start = start; 37 this.end = end; 38 System.out.println("Drawing Line"); 39 } 40 void dispose(){ 41 System.out.println("Erasing Line" + start + ", " + end); 42 super.dispose(); 43 } 44 } 45 public class CADSystem extends Shape{ 46 private Circle c; 47 private Triangle t; 48 private Line[] lines = new Line[3]; 49 public CADSystem(int i){ 50 super(i + 1); 51 for(int j = 0; j < lines.length; j++){ 52 lines[j] = new Line(j, j*j); 53 } 54 c = new Circle(1); 55 t = new Triangle(1); 56 System.out.println("Combined constructor"); 57 } 58 public void dispose(){ 59 System.out.println("CADSystem.dispose()"); 60 //The order of cleanup is the reverse 61 //of the order of initialization; 62 t.dispose(); 63 c.dispose(); 64 for(int i = lines.length - 1; i >= 0; i--){ 65 lines[i].dispose(); 66 } 67 } 68 69 public static void main(String[] args){ 70 CADSystem x = new CADSystem(47); 71 try{ 72 73 }finally{ 74 x.dispose(); 75 } 76 } 77 78 /* 79 * Shape Constructor. 80 * Shape Constructor. 81 * Drawing Line 82 * Shape Constructor. 83 * Drawing Line 84 * Shape Constructor. 85 * Drawing Line 86 * Shape Constructor. 87 * Drawing Circle 88 * Shape Constructor. 89 * Drawing Triangle 90 * Combined constructor 91 * CADSystem.dispose() 92 * Erasing Triangle 93 * Shape dispose. 94 * Erasing Circle 95 * Shape dispose. 96 * Erasing Line2,4 97 * Shape dispose. 98 * Erasing Line1,1 99 * Shape dispose. 100 * Erasing Line0,0 101 * Shape dispose. 102 * 103 */ 104 105 }
7 多态
私有方法有多态吗?
1 package ploymorphism; 2 3 class Derived extends PrivateOverride{ 4 public void f(){ 5 System.out.println("public f()"); 6 } 7 } 8 9 /* 10 * 多态不能覆盖父类的私有方法,尽量避免子类和父类的私有方法名字一致,从而避免引起混淆。 11 * 下面的代码输出是什么?把f()的权限公开,结果又怎样? 12 */ 13 public class PrivateOverride { 14 private void f(){ 15 System.out.println("private f()"); 16 } 17 public static void main(String[] args){ 18 PrivateOverride po = new Derived(); 19 po.f(); 20 } 21 } 22 23 /* 24 * private f() 25 */
公开域有多态吗?
1 package ploymorphism; 2 3 class Super { 4 public int field = 0; 5 6 public int getField() { 7 return field; 8 } 9 } 10 11 class Sub extends Super { 12 public int field = 1; 13 14 public int getField() { 15 return field; 16 } 17 18 public int getSuperField() { 19 return super.field; 20 } 21 } 22 23 public class FieldAccess { 24 public static void main(String[] args) { 25 Super sup = new Sub(); // Up casting 26 System.out.println("sup.field = " + sup.field + ", sup.getField() = " 27 + sup.getField()); 28 Sub sub = new Sub(); 29 System.out.println("sub.field = " + sub.field + ", sub.getField() = " 30 + sub.getField() + ", sub.getSuperField = " 31 + sub.getSuperField()); 32 } 33 34 } 35 36 /* 37 * 任何域的访问操作都将有编译器解析,因此不是多态的。 38 * Sub实际上有两个field的域。它自己的和从Super处得到的。 39 * 引用Sub中的域field时所产生的默认域并非Super版本的域。 40 * 41 */ 42 43 /* 44 * Output: 45 * sup.field = 0, sup.getField() = 1 46 * sub.field = 1, sub.getField() = 1, sub.getSuperField = 0 47 * 48 */
静态方法有多态吗?
1 package ploymorphism; 2 class StaticSuper{ 3 public static String staticGet(){ 4 return "Base staticGet"; 5 } 6 public String dynamicGet(){ 7 return "Base dynamicGet()"; 8 } 9 } 10 class StaitcSub extends StaticSuper{ 11 public static String staticGet(){ 12 return "Derived staticGet()"; 13 } 14 public String dynamicGet(){ 15 return "Derived dynamicGet()"; 16 } 17 } 18 public class StaticPolymorphism { 19 public static void main(String[] args){ 20 StaticSuper sup = new StaitcSub(); 21 System.out.println(sup.staticGet()); 22 System.out.println(sup.dynamicGet()); 23 } 24 } 25 26 /* 27 * 如果某个方法是静态的,它的行为就不具有多态性。 28 * 静态方法是与类,而非单个对象相关联的。 29 * 30 * Outputs: 31 * 32 * Base staticGet 33 * Derived dynamicGet() 34 */
只有普通的公开方法有多态的特性。
含有构造器,继承,静态域的初始化顺序
1 package ploymorphism; 2 3 class Meal { 4 Meal() { 5 System.out.println("Meal()"); 6 } 7 } 8 9 class Bread { 10 Bread() { 11 System.out.println("Bread()"); 12 } 13 } 14 15 class Chess { 16 Chess() { 17 System.out.println("Chess()"); 18 } 19 } 20 21 class Lettuce { 22 Lettuce() { 23 System.out.println("Lettuce()"); 24 } 25 } 26 27 class Lunch extends Meal { 28 Lunch() { 29 System.out.println("Lunch()"); 30 } 31 } 32 33 class ProtableLunch extends Lunch { 34 ProtableLunch() { 35 System.out.println("ProtableLunch()"); 36 } 37 } 38 39 public class SandWitch extends ProtableLunch{ 40 41 private Bread b = new Bread(); 42 private Chess c = new Chess(); 43 private Lettuce l = new Lettuce(); 44 45 private static ProtableLunch pp = new ProtableLunch();//1 46 private static Lunch ll = new Lunch();//2 47 48 public SandWitch() { 49 System.out.println("SandWitch()"); 50 } 51 52 public static void main(String[] args) { 53 new SandWitch();//3 54 } 55 } 56 57 /* 58 * 初始化顺序,调用基类构造器 59 * 按声明顺序调用成员初始化的方法 60 * 调用导出类构造器的主体 61 * 先静态域,静态方法,数据域,构造器,普通方法 62 * 63 */ 64 65 /* 66 * Outputs: 67 * 68 * Meal() 69 * Lunch() 70 * ProtableLunch() 71 * Meal() 72 * Lunch() 73 * Meal() 74 * Lunch() 75 * ProtableLunch() 76 * Bread() 77 * Chess() 78 * Lettuce() 79 * SandWitch() 80 * 81 * 82 */
8 数组
类似于C系列的函数求解
1 package arrays; 2 3 import java.util.Arrays; 4 import java.util.Random; 5 6 public class IceCream { 7 private static Random rand = new Random(47); 8 static final String[] FLAVORS = { "Chocolate", "Strawberry", 9 "Vanilla Fudge Swirl", "Mint Chip", "Mocha Almond Fudge", 10 "Rum Raisin", "Praline Cream", "Mud Pie", }; 11 12 public static String[] flavorSet(int n) { 13 if (n > FLAVORS.length) { 14 throw new IllegalArgumentException("Set to big"); 15 } 16 String[] results = new String[n]; 17 boolean[] picked = new boolean[FLAVORS.length]; 18 for (int i = 0; i < n; i++) { 19 int t; 20 do { 21 t = rand.nextInt(FLAVORS.length); 22 } while (picked[t]); 23 results[i] = FLAVORS[t]; 24 picked[t] = true; 25 } 26 return results; 27 } 28 29 public static void main(String[] args) { 30 for (int i = 0; i < 7; i++) { 31 System.out.println(Arrays.toString(flavorSet(4))); 32 } 33 } 34 } 35 36 /* 37 * OutPuts: 38 * 39 * [Rum Raisin, Mint Chip, Mocha Almond Fudge, Chocolate] 40 * [Strawberry, MochaAlmond Fudge, Mint Chip, Rum Raisin] 41 * [Vanilla Fudge Swirl, Mud Pie,Chocolate, Mocha Almond Fudge] 42 * [Praline Cream, Strawberry, Mocha AlmondFudge, Mint Chip] 43 * [Mint Chip, Strawberry, Praline Cream, Chocolate] 44 * [Chocolate, Praline Cream, Mocha Almond Fudge, Mint Chip] 45 * [Mud Pie,Strawberry, Mint Chip, Rum Raisin] 46 * 47 */
9 泛型
Java中的泛型需要与C++进行一番比较,理由有二:首先,了解C++模板的默写方面,有助于理解泛型的基础。
同时,也可以了解Java的局限,以及为什么有这些限制。最终帮你理解,Java泛型的边界在哪里。理解了边界所在,
才能成为程序高手(不必浪费时间在死胡同里乱转)。第二个原因是,在Java社区中,人们普遍对C++模板有一种误解,
而这种误解可能误导你,令你在理解泛型的意图时产生偏差。
10 内部类
package innerclasses; /* * 接口就相当于声明语句 */ interface Selector { public int dex = 0; boolean end(); Object current(); void next(); } public class Sequence { private static Object[] item; private int next; public Sequence(int size) { item = new Object[size]; } public void add(Object x) { if (next < item.length) { item[next++] = x; } } /* * 内部类可以访问外围类的字段和方法, 加static关键字表示嵌套类(静态内部类) */ public static class SequenceSelector implements Selector { private int i = 0; public boolean end() { return i == item.length; } public Object current() { return item[i]; } public void next() { if (i < item.length) { i++; } } } public Selector selector() { return new SequenceSelector(); } public static void main(String[] args) { Sequence sequence = new Sequence(10); for (int i = 0; i < 10; i++) { sequence.add(Integer.toString(i)); } Selector selector = sequence.selector(); while (!selector.end()) { System.out.print(selector.current() + " "); selector.next(); } } } class ABC { /* * 先实例化外围类 */ Sequence aSequence = new Sequence(5); /* * 实例化的外围类生成构造器 */ Sequence.SequenceSelector aSelector = new Sequence.SequenceSelector(); int x = Selector.dex; }
11 容器、迭代器
迭代器能够将遍历的操作与序列底层的结构分离。正由于此,我们有时会说;迭代器统一了对容器的访问方式。