OOP with Java 通知 Project 7 :6 月 14 日晚 9 点 6 月 5 日复习 6 月 12 日考试

Similar documents
OOP with Java 通知 Project 7 :6 月 27 日晚 9 点 6 月 14 日复习 6 月 21 日考试 答疑 6 月 20 日 13 : : 00 理科楼 B911

OOP with Java 通知 Project 7, 6 月 14 日晚 9 点 本周四上机课正常进行 答疑 本周三, 周五下午 1:00 3:00, 理科楼 B911 6 月 12 日考试 ( 随堂 ) 下午 1:00-3:00 教书院 218

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

OOP with Java 通知 Project 6: 5 月 30 日晚 9 点

OOP with Java 通知 Project 6: 5 月 24 日晚 9 点

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 6: 6 月 6 日晚 9 点

chp6.ppt

EJB-Programming-4-cn.doc

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

KillTest 质量更高 服务更好 学习资料 半年免费更新服务


EJB-Programming-3.PDF

Java java.lang.math Java Java.util.Random : ArithmeticException int zero = 0; try { int i= 72 / zero ; }catch (ArithmeticException e ) { // } 0,

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

Java Access 5-1 Server Client Client Server Server Client 5-2 DataInputStream Class java.io.datainptstream (extends) FilterInputStream InputStream Obj

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 4: 推迟至 4 月 25 日晚 9 点

untitled

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

1: public class MyOutputStream implements AutoCloseable { 3: public void close() throws IOException { 4: throw new IOException(); 5: } 6:

untitled

Microsoft Word - 01.DOC

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

untitled

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

软件工程文档编制

D C 93 2

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 6: 5 月 24 日晚 9 点

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit

Guava学习之Resources

无类继承.key

9, : Java 19., [4 ]. 3 Apla2Java Apla PAR,Apla2Java Apla Java.,Apla,,, 1. 1 Apla Apla A[J ] Get elem (set A) A J A B Intersection(set A,set B) A B A B

untitled

Chapter 9: Objects and Classes

JavaIO.PDF

2009年3月全国计算机等级考试二级Java语言程序设计笔试试题

untitled

javaexample-02.pdf

OOP with Java 通知 Project 3 提交时间 3 月 29 日晚 9 点 Piazza Project 2 投票

Chapter 9: Objects and Classes

Java

java2d-4.PDF

3.1 num = 3 ch = 'C' 2

Swing-02.pdf

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6

雲端 Cloud Computing 技術指南 運算 應用 平台與架構 10/04/15 11:55:46 INFO 10/04/15 11:55:53 INFO 10/04/15 11:55:56 INFO 10/04/15 11:56:05 INFO 10/04/15 11:56:07 INFO

Microsoft Word - ch04三校.doc

IoC容器和Dependency Injection模式.doc

内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌

(6) 要 求 付 款 管 理 员 从 预 订 表 中 查 询 距 预 订 的 会 议 时 间 两 周 内 的 预 定, 根 据 客 户 记 录 给 满 足 条 件 的 客 户 发 送 支 付 余 款 要 求 (7) 支 付 余 款 管 理 员 收 到 客 户 余 款 支 付 的 通 知 后, 检

OOP with Java 通知 Project 3: 4 月 19 日晚 9 点

《大话设计模式》第一章

使 用 Java 语 言 模 拟 保 险 箱 容 量 门 板 厚 度 箱 体 厚 度 属 性 锁 具 类 型 开 保 险 箱 关 保 险 箱 动 作 存 取 款

untitled

Learning Java

Microsoft PowerPoint - plan08.ppt

Microsoft Word - 新1-12.doc

2009年9月全国计算机等级考试二级Java真题及答案

untitled

1 Framework.NET Framework Microsoft Windows.NET Framework.NET Framework NOTE.NET NET Framework.NET Framework 2.0 ( 3 ).NET Framework 2.0.NET F

北 风 网 讲 师 原 创 作 品 ---- 仅 供 学 员 内 部 交 流 使 用 前 言 吾 尝 终 日 而 思 矣, 不 如 须 臾 之 所 学 也 ; 吾 尝 跂 而 望 矣, 不 如 登 高 之 博 见 也 登 高 而 招, 臂 非 加 长 也, 而 见

<4D F736F F F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074>

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料

untitled

主程式 : public class Main3Activity extends AppCompatActivity { ListView listview; // 先整理資料來源,listitem.xml 需要傳入三種資料 : 圖片 狗狗名字 狗狗生日 // 狗狗圖片 int[] pic =new

Microsoft Word - Learn Objective-C.doc

RxJava

在 ongodb 中实现强事务

新版 明解C++入門編

FileMaker 16 ODBC 和 JDBC 指南

2. AOP 底层技术实现 小风 Java 实战系列教程 关键词 : 代理模式 代理模型分为两种 : 1) 接口代理 (JDK 动态代理 ) 2) 子类代理 (Cglib 子类代理 ) 需求 :CustomerService 业务类, 有 save,update 方法, 希望在 save,updat

OOP with Java 通知 : Project 2 提交时间 : 3 月 15 日晚 9 点

Microsoft PowerPoint - L17_Inheritance_v4.pptx

OOP with Java 通知 : Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢

使用MapReduce读取XML文件

基于ECO的UML模型驱动的数据库应用开发1.doc

6-1 Table Column Data Type Row Record 1. DBMS 2. DBMS MySQL Microsoft Access SQL Server Oracle 3. ODBC SQL 1. Structured Query Language 2. IBM

Java 1 Java String Date

Microsoft Word - 第6章.doc

untitled

PowerPoint Presentation

JBuilder Weblogic

javac: 负 责 的 是 编 译 的 部 分, 当 执 行 javac 时, 会 启 动 java 的 编 译 器 程 序 对 指 定 扩 展 名 的.java 文 件 进 行 编 译 生 成 了 jvm 可 以 识 别 的 字 节 码 文 件 也 就 是 class 文 件, 也 就 是 ja

基于CDIO一体化理念的课程教学大纲设计

Strings

Microsoft PowerPoint - ch02

INTRODUCTION TO COM.DOC

<4D F736F F F696E74202D20A1B64A617661B8DFBCB6BCBCCAF5A1B7B5DA31312E35BDB220B6AFCCACC0E0D0CDBCECB2E92E707074>

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

Python a p p l e b e a r c Fruit Animal a p p l e b e a r c 2-2

while ((ch = fr.read())!= -1) { System.out.print((char) ch); fr.close(); 例 3: 用 BufferedReader 读 TXT 文件 public class FileReaderDemo3 { public static v

untitled

拦截器(Interceptor)的学习

// 获取并集 // set1.addall(set2); // 获取交集 set1.retainall(set2); // 打印操作结果 set1.foreach(o -> System.out.println(o)); 运行结果如图 6-1 所示 图 6-1 运行结果 三 案例总结 1 Coll

epub83-1

Strings

Transcription:

OOP with Java Yuanbin Wu cs@ecnu

OOP with Java 通知 Project 7 :6 月 14 日晚 9 点 6 月 5 日复习 6 月 12 日考试

复习 I/O 流 InputStream/Reader read() OutputStream/Writer write() 抽象 : 数据的来源 / 数据的目的地 ByteArrayStream, FileStream StringStream ObjectStream

import java.io.fileinputstream; import java.io.fileoutputstream; import java.io.ioexception; public class CopyBytes { public static void main(string[] args) throws IOException { FileInputStream in = null; FileOutputStream out = null; try { in = new FileInputStream("xanadu.txt"); out = new FileOutputStream("outagain.txt"); int c; while ((c = in.read())!= -1) out.write(c); finally { if (in!= null) in.close(); if (out!= null) out.close();

装饰器 FilterInputStream/FilterOutputStream BufferedInputStream DataInputStream FileInputStream fin = new FileInputStream("xanadu.txt"); BufferedInputStream bf = new BufferedInputStream(fin); DataInputStream din = new DataInputStream(bf); din.read(); din.readint(); din.readdouble(); FileOutputStream fout = new FileOutputStream("xanadu.txt"); BufferedOutputStream bf = new BufferedOutputStream(fout); DataOutputStream dout = new DataOutputStream(bf); dout.write(1); dout.writeint(10); dout.writedouble(3.14);

复习 InputStream ByteArrayInputStream FileInputStream StringBufferInputStream FilterInputStream BufferdInputStream DataInputStream 装饰器

OOP with Java 运行时类型信息 泛型

RTTI 运行时类型信息 RunTime Type Information (RTTI) Class 类 每一个类都包含一个 Class 类的对象 该对象包含该类的信息 类名字 类的有哪些方法 类的有哪些成员

RTTI 每个类的静态成员 所有对象共享一个 Class 对象 每个对象调用 getclass() 获得 Class 类的对象 String s = hello ; Class c = s.getclass(); 每个类通过.class 获得 Class 类的对象 Class c = String.class

RTTI Class 类的方法 getname() getinterfaces() getsuperclass() newinstance()

public class ToyTest { interface A { interface B { interface C { class Toy { Toy() { Toy(int i) { class FancyToy extends Toy implements A, B, C { FancyToy() { super(1); static void printinfo(class c) { System.out.println("Class name: " + c.getname() ); System.out.println( Is interface? + c.isinterface()); System.out.println("Simple name: " + c.getsimplename()); System.out.println("Canonical name : " + c.getcanonicalname()); public static void main(string[] args) { Class c = null; try { c = Class.forName("typeinfo.toys.FancyToy"); catch(classnotfoundexception e) { System.out.println("Can t find FancyToy");System.exit(1); printinfo(c); for(class face : c.getinterfaces()) printinfo(face); Class up = c.getsuperclass(); Object obj = null; try { // Requires default constructor: obj = up.newinstance(); catch(instantiationexception e) { System.out.println("Cannot instantiate"); System.exit(1); catch(illegalaccessexception e) { System.out.println("Cannot access"); System.exit(1); printinfo(obj.getclass());

RTTI RTTI 的用途 给定 Object 引用, 判断它的类型 (Downcasting) String s = new String( hello ); Object o = s; String type = o.getclass().getname(); String t = (String)o;

泛型 容器 new ArrayList(); class Apple { private static long counter; private final long id = counter++; public long id() { return id; class Orange { public class ApplesAndOrangesWithoutGenerics { public static void main(string[] args) { ArrayList apples = new ArrayList(); for(int i = 0; i < 3; i++) apples.add(new Apple()); // Not prevented from adding an Orange to apples: apples.add(new Orange()); for(int i = 0; i < apples.size(); i++) ((Apple)apples.get(i)).id(); // Orange is detected only at run time

泛型 类型安全的容器 new ArrayList<Apple>(); public class ApplesAndOrangesWithGenerics { public static void main(string[] args) { ArrayList<Apple> apples = new ArrayList<Apple>(); for(int i = 0; i < 3; i++) apples.add(new Apple()); // Compile error! // apples.add(new Orange()); for(int i = 0; i < apples.size(); i++) apples.get(i).id(); for(apple c: apples) System.out.println(c.id());

泛型 不同类型间的相互替代? Upcasting 与多态 Class A { void f (A arg) { // f(new A()); Class A { Class B { void f (A arg) { // f(new B()); Class A { Class B { Class C extends A { void f (A arg) { // f(new C());

泛型 不同类型间的相互替代? 泛型 : 更灵活的方式

基本概念 泛型 (generics) 在定义类的成员和方法时, 类型为可变参数 class MyType {? member = null; void f (? arg) { //

基本概念 语法 class MyType {? member = null; void f (? arg) { // class MyType<T> { T member = null; <T> void f (T arg) { //

Example: A simple Holder class class Apple { public class Holder { private Apple a; public Holder(Apple a) { this.a = a; public void set(apple a) { this.a = a; public Apple get() { return a; public static void main(string[] args) { Holder h = new Holder(new Apple()); Apple a = h.get(); // h.set("not an Apple"); // Error // h.set(1); // Error

Example: A simple Holder class class Apple { public class Holder<T> { private T a; public Holder(T a) { this.a = a; public void set(t a) { this.a = a; public T get() { return a; public static void main(string[] args) { Holder<String> hs = new Holder<String>(new String( hello )); String s = hs.get(); Holder<Integer> hi = new Holder<Integer>(1); int I = hi.get(); Holder<Apple> h = new Holder<Apple>(new Apple()); Apple a = h.get(); // h.set("not an Apple"); // Error // h.set(1); // Error

Example: A simple Holder class class Apple { public class Holder<T> { private T a; public Holder(T a) { this.a = a; public void set(t a) { this.a = a; public T get() { return a; class Apple { public class Holder { private Object a; public Holder(Object a) { this.a = a; public void set(object a) { this.a = a; public Object get() { return a; public static void main(string[] args) { Holder<Apple> h = new Holder<Apple>( new Apple()); Apple a = h.get(); public static void main(string[] args) { Holder h = new Holder(new Apple()); Apple a = (Apple)h.get();

基本概念 参数化类型 形参 实参 类型参数

Example: A tuple library Tuple 不可变数组 ( 数组元素不可变 ) 用途 : 函数返回多个值 Data transfer object

Example: A tuple library public class TwoTuple<A,B> { public final A first; public final B second; public TwoTuple(A a, B b) { first = a; second = b; public String tostring() { return "(" + first + ", " + second + ")";

Example: A tuple library public class ThreeTuple<A,B,C> extends TwoTuple<A,B> { public final C third; public ThreeTuple(A a, B b, C c) { super(a, b); third = c; public String tostring() { return "(" + first + ", " + second + ", " + third +")"; public class FourTuple<A,B,C,D> extends ThreeTuple<A,B,C> { public final D four; public ThreeTuple(A a, B b, C c, D d) { super(a, b, c); third = d; public String tostring() { return "(" + first + ", " + second + ", " + third + "," + four + ")";

Example: A tuple library class Apple { class Orange { public class TupleTest { static TwoTuple<String,Integer> f() { return new TwoTuple<String,Integer>("hi", 47); // Autoboxing static ThreeTuple<Apple,String,Integer> g() { return new ThreeTuple<Apple, String, Integer>(new Apple(), "hi", 47); static FourTuple<Orange,Apple,String,Integer> h() { return new FourTuple<Orange,Apple,String,Integer>(new Orange(), new Apple(), "hi", 47); public static void main(string[] args) { TwoTuple<String,Integer> ttsi = f(); System.out.println(ttsi); // ttsi.first = "there"; // Compile error: final System.out.println(g()); System.out.println(h());

泛型接口 带有类型参数的接口 public interface Generator<T> { T next(); public class Coffee { private static long counter = 0; private final long id = counter++; public String tostring() { return getclass().getsimplename() + " " + id; public class Latte extends Coffee { public class Mocha extends Coffee { public class Cappuccino extends Coffee { public class Americano extends Coffee { public class Breve extends Coffee {

import java.util.*; public class CoffeeGenerator implements Generator<Coffee> { private Class[] types = { Latte.class, Mocha.class, Cappuccino.class, Americano.class, Breve.class, ; private static Random rand = new Random(47); private int size = 0; public CoffeeGenerator() { public CoffeeGenerator(int sz) { size = sz; public Coffee next() { try { return (Coffee) types[rand.nextint(types.length)].newinstance(); // Report programmer errors at run time: catch(exception e) { throw new RuntimeException(e); public static void main(string[] args) { CoffeeGenerator gen = new CoffeeGenerator(); for(int i = 0; i < 5; i++) System.out.println(gen.next());

// public class CoffeeGenerator implements Generator<Coffee> public class Fibonacci implements Generator<Integer> { private int count = 0; public Integer next() { return fib(count++); private int fib(int n) { if(n < 2) return 1; return fib(n-2) + fib(n-1); public static void main(string[] args) { Fibonacci gen = new Fibonacci(); for(int i = 0; i < 18; i++) System.out.print(gen.next() + " ");

泛型方法 方法的参数, 返回值带有类型参数 语法 public <T> void f(t x) { // <T> 说明该方法带有类型参数 T 需要放在返回值说明之前

泛型方法 public class GenericMethods { public <T> void f(t x) { System.out.println(x.getClass().getName()); public static void main(string[] args) { GenericMethods gm = new GenericMethods(); gm.f(""); gm.f(1); gm.f(1.0); gm.f(1.0f); gm.f( c ); gm.f(gm); 方法的类型参数可以与类的类型参数无关 public class GenericMethods<E> { E member; public <T> void f(t x) { System.out.println(x.getClass().getName());

类型推理 编译器推理出类型变量的值 public class New { public static <K, V> Map<K, V>() { return new HashMap<K, V>(); public static void main(string []args){ Map<String, List<String>> s = New.Map(); 1. 由 Map<String, List<String>> s = New.Map(); 推断出 Map() 方法中的 K=String, V=List<String> 2. 可以通过语法明确泛型方法调用时的类型参数 Map<String, List<String>> s = New.<String, List<String>>Map(); // Diamond ArrayList<String> s = new ArrayList<>(); HashMap<String, Integer> h = new HashMap<>();

小结 泛型类 泛型接口 public class TwoTuple<A, B> { //... 泛型方法 public interface Generator<T> { T next(); public <T> void f(t x) { //

public class Generators { public static <T> Collection<T> fill(collection<t> coll, Generator<T> gen, int n) { for(int i = 0; i < n; i++) coll.add(gen.next()); return coll; public static void main(string[] args) { Collection<Coffee> coffee = fill(new ArrayList<Coffee>(), new CoffeeGenerator(), 4); for(coffee c : coffee) System.out.println(c); Collection<Integer> fnumbers = fill(new ArrayList<Integer>(), new Fibonacci(), 12); for(int i : fnumbers) System.out.print(i + ", ");

Type Erasure 当给定不同的类型参数时, 泛型的类型是否相同? class A { class B extends A{ public class Test { public static void main(string []args){ ArrayList<String> strlist = new ArrayList<>(); ArrayList<Integer> intl = strlist; ArrayList<B> blist = new ArrayList<>(); ArrayList<A> alist = blist; 编译错误! ArrayList<String>, ArrayList<Integer>, ArrayList<B>, ArrayList<A> 是不同类型!

Type Erasure 当给定不同的类型参数时, 泛型的类型是否相同? Class Object import java.util.*; public class ErasedTypeEquivalence { public static void main(string[] args) { Class c1 = new ArrayList<String>().getClass(); Class c2 = new ArrayList<Integer>().getClass(); System.out.println(c1 == c2); 输出 : true!

Type Erasure import java.util.*; class Frob { class Fnorkle { class Quark<Q> { class Particle<POSITION,MOMENTUM> { 输出 : [E] [K, V] [Q] [POSITION, MOMENTUM] public class LostInformation { public static void main(string[] args) { List<Frob> list = new ArrayList<Frob>(); Map<Frob,Fnorkle> map = new HashMap<Frob,Fnorkle>(); Quark<Fnorkle> quark = new Quark<Fnorkle>(); Particle<Long,Double> p = new Particle<Long,Double>(); System.out.println(Arrays.toString(list.getClass().getTypeParameters())); System.out.println(Arrays.toString(map.getClass().getTypeParameters())); System.out.println(Arrays.toString(quark.getClass().getTypeParameters())); System.out.println(Arrays.toString(p.getClass().getTypeParameters()));

Type Erasure 泛型是如何实现的? ArrayList<String> 与 ArrayList <Integer> 的区别在哪里?

Type Erasure 类型擦除 (Type Erasure), T 仅作为占位符, 不包含任何具体类型的信息 所有 T 类型的对象引用最终实现为 Object 对象引用

Type Erasure public class HasF { public void f() { System.out.println("HasF.f()"); class Manipulator<T> { private T obj; public Manipulator(T x) { obj = x; // Error: cannot find symbol: method f(): public void manipulate() { obj.f(); public class Manipulation { public static void main(string[] args) { HasF hf = new HasF(); Manipulator<HasF> manipulator = new Manipulator<HasF>(hf); manipulator.manipulate();

Type Erasure public class Erased<T> { private final int SIZE = 100; public static void f(object arg) { if(arg instanceof T) { T var = new T(); // compile error // compile error T[] array = new T[SIZE]; // compile error

Type Erasure Type Erasure 实现原理 1: 所有引用最后都变为 Object 引用 编译器自动添加 Downcasting 代码 class Apple { public class Holder<T> { private T a; public Holder(T a) { this.a = a; public void set(t a) { this.a = a; public T get() { return a; class Apple { public class Holder { private Object a; public Holder(Object a) { this.a = a; public void set(object a) { this.a = a; public Object get() { return a; public static void main(string[] args) { Holder<Apple> h = new Holder<Apple>( new Apple()); Apple a = h.get(); public static void main(string[] args) { Holder h = new Holder(new Apple()); Apple a = (Apple)h.get(); 生成相同的机器代码编译器在 get() 返回处自动添加了类型转换代码

Type Erasure Type Erasure 的实现原理 2: 编译器只做静态检查 class A { class B extends A{ public class Test { public static void main(string []args){ ArrayList<String> strlist = new ArrayList<>(); ArrayList<Integer> intl = strlist; ArrayList<B> blist = new ArrayList<>(); ArrayList<A> alist = blist; 1. 编译器通过静态检查报错 (ArrayList<String> 与 ArrayList<Integer> 类型不同 ) 2. 但实际存储中, 无论 <String> 还是 <Integer> 都存储的是 Object 类型的引用

Type Erasure Type Erasure 类型变量仅仅对编译器的静态检查有用 当通过静态检查, 所有类型参数被擦除

Type Erasure 如何解决 Type Erasure 带来的问题? Class 对象 public class Erased<T> { private final int SIZE = 100; public static void f() { T var = new T(); // compile error public class TypeCapture<T> { Class<T> kind; public TypeCapture(Class<T> kind){ this.kind = kind; public T f() { T r = null; try{ r = kind.newinstance(); catch (Exception e){ System.out.println("fail"); return r; public static void main(string []args) { TypeCapture<String> c = new TypeCapture<>(String.class); System.out.println(c.f());

Type Erasure 如何解决 Type Erasure 带来的问题? public class HasF { public void f() { System.out.println("HasF.f()"); class Manipulator<T> { private T obj; public Manipulator(T x) { obj = x; // Error: cannot find symbol: method f(): public void manipulate() { obj.f(); class Manipulator<T extends HasF> { private T obj; public Manipulator(T x) { obj = x; public void manipulate() { obj.f(); public class Manipulation { public static void main(string[] args) { HasF hf = new HasF(); Manipulator<HasF> manipulator = new Manipulator<HasF>(hf); manipulator.manipulate();

被限定的类型参数 限定类型参数的范围 语法 : class A <T extends B> { // 表示类型参数 T 只能是 B 类型或者 B 的子类型 作用 : 静态检查时, 可以合法引用 T 的方法 ( 但最终仍然是 Object ) 多个限定类型 class A <T extends B & C> { // 如果有类和接口, 类应该出现在第一个位置

被限定的类型参数 interface HasColor { java.awt.color getcolor(); class Colored<T extends HasColor> { T item; Colored(T item) { this.item = item; T getitem() { return item; // The bound allows you to call a method: java.awt.color color() { return item.getcolor(); class Dimension { public int x, y, z; // Multiple bounds: class ColoredDimension<T extends Dimension & HasColor> { T item; ColoredDimension(T item) { this.item = item; T getitem() { return item; java.awt.color color() { return item.getcolor(); int getx() { return item.x; int gety() { return item.y; int getz() { return item.z;

通配符 class Fruit { class Apple extends Fruit{ class Orange extends Fruit{ public class Test { public static void main(string []args){ List<Apple> alist = new ArrayList<Apple>(); // compile error // List<Fruit> flist = new ArrayList<Apple>(); 如何表达 ArrayList 中的元素是 Fruit 的某个子类?

通配符 class Fruit { class Apple extends Fruit{ class Orange extends Fruit{ public class Test { public static void main(string []args){ List<Apple> alist = new ArrayList<Apple>(); // compile error // List<Fruit> flist = new ArrayList<Apple>(); List<? extends Fruit> flist = new ArrayList<Apple>(); // Compile Error: can t add any type of object: // flist.add(new Apple()); // flist.add(new Fruit()); // flist.add(new Object()); flist.add(null); // Legal but uninteresting // We know that it returns at least Fruit: Fruit f = flist.get(0);

通配符 类型参数为某个 B 的子类型 具体是哪一个无法确定 List<? extends Fruit> 无法 add 任何对象 List 中存储的对象类型无法确定 可以 get 对象 Fruit 类型 <? extends B>

通配符 类型参数为某个 B 的父类型 具体是哪一个无法确定 List<? super Apple> 无法 get 任何对象 无法确定是哪个父类 <? super B> 可以 add Apple 的子类对象

import java.util.*; public class SuperTypeWildcards { static void writeto(list<? super Apple> apples) { apples.add(new Apple()); apples.add(new Jonathan()); // apples.add(new Fruit()); // Error

总结 Type Erasure 类型变量仅仅对编译器的静态检查有用 当通过静态检查, 所有类型参数被擦除 被限制的类型参数 通配符 class A <T extends B & C> { // <? extends B> <? super B>