查看“核心技术:接口、lambda表达式与内部类”的源代码
←
核心技术:接口、lambda表达式与内部类
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:JavaCore]] == 接口 == 接口(interface),是对类的一组需求描述(一组行为定义): # 接口的所有方法自动属于public(不用提供public关键字); # 接口中可以有常量,但是不能有实例域; #: 即,域自动设置为:“public static final” # 接口中可以有实现方法(Java SE 8 之后),但方法中不能引用实例域; #: 默认:“public abstract” 提供实例域和方法实现,应该由实现接口的类来完成。<br/> 实现接口: # 声明实现给定的接口: #: <syntaxhighlight lang="java"> class Employee implements Comparable </syntaxhighlight> # 对接口中的所有方法进行定义; * 所有方法都必须有实现; * 实现方法时,必须把方法声明为“public”; === 接口的特性 === # 接口不是类,不能用“new”进行实例化; # 可以用接口声明变量,变量只能引用接口实现类的对象; # 可以使用“instanceof”检查一个对象是否实现了某个特定接口(类似于检查对象是否属于某个类); # 接口可以被继承,用新的接口扩展旧接口; === 接口与抽象类 === Java不支持多重继承(multiple inheritance):引入抽象类,避免多重继承的复杂性和低效性。 === 静态方法 === Java 8 之后,允许接口中增加静态方法: * 静态方法无法实现多态,形式上重写,实际上是新方法。 === 默认方法 === 可以为接口方法提供一个默认实现(也可以不实现),并用“default”修饰该方法: # 可以不用实现接口所有方法,只关注于需要的某个或某几个方法(可以不再使用伴随类): #: <syntaxhighlight lang="java"> public interface MouseListener { default void mousedieked(MouseEvent event) {} default void mousePressed(MouseEvent event) {} default void mouseReleased(MouseEvent event) {} default void mouseEntered(MouseEvent event) {} default void mouseExited(MouseEvent event) {} } </syntaxhighlight> # 在为旧接口增加方法时,使用默认方法可以保证“源代码兼容”(source compatible); #: (增加非默认方法,会导致接口现有实现类不能正常工作) ==== 关于伴随类 ==== <pre> 在JavaAPI 中,你会看到很多接口都有相应的伴随类,这个伴随类中实现了相应接口的部分或所有方法, 如 Collection/AbstractCollection 或 MouseListener/MouseAdapter。在JavaSE 8 中,这个技术已经过时。现在可以直接在接口中实现方法。 </pre> 使用抽象类(伴随类)对接口进行部分实现,而后用户类并不之间实现接口(需要实现全部方法),而是继承与该抽象类(只重写需要的类即可)。如: # <syntaxhighlight lang="java"> public interface Collection<E> extends Iterable<E> { public abstract class AbstractCollection<E> implements Collection<E> { </syntaxhighlight> # <syntaxhighlight lang="java"> public interface MouseListener extends EventListener { public abstract class MouseAdapter implements MouseListener, MouseWheelListener, MouseMotionListener { </syntaxhighlight> # 又见,SpringMVC 中的拦截器(见[http://wiki.eijux.com/SpringMVC%EF%BC%9A%E9%AB%98%E7%BA%A7%E5%BA%94%E7%94%A8#.E6.8B.A6.E6.88.AA.E5.99.A8.E5.AE.9A.E4.B9.89]): #: <syntaxhighlight lang="java"> public interface HandlerInterceptor { public interface AsyncHandlerInterceptor extends HandlerInterceptor { public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor { </syntaxhighlight> === 解决默认方法冲突 === 冲突:现在接口中将一个方法定义为默认方法,又在超类或另一个接口中定义了同样的方法;<br/> 规则: # 超类优先:接口中的方法(不论是否默认方法)会被忽略; # 接口冲突:一个接口提供默认方法,一个接口提供同名同参数方法(不论是否默认方法),则在实现类必须覆盖这个方法; == 接口示例 == === 接口与回调 === 回调的思想是: # 类A的a()方法调用类B的b()方法 # 类B的b()方法执行完毕主动调用类A的callback()方法 * '''回调的核心就是回调方将本身即this传递给调用方''' 回调与接口: # 将回调方法抽象为接口,用回调方去实现需要的回调接口 '''[[关于Java调用]]''' === Comparator 接口 === * 若需要将对象数组排序,则必须数组的每一个元素都实现了'''Comparable'''接口: *: <syntaxhighlight lang="java"> package java.lang; import java.util.*; public interface Comparable<T> { public int compareTo(T o); } </syntaxhighlight> 然而,如果需要对String数组排序(已经实现了Comparable<String>接口),但又不想按照字典顺序排序(String.compareTo的实现是按字典顺序比较): :首先我们不能使String类实现两种不同的compareTo方法, :其次String类也不应该由我们修改。 即:'''如何使用Comparable.compareTo方法之外的比较方法,来进行对象数组的排序?''' 所以,我们需要用到: # '''Arrays.sort''' 方法 #: <syntaxhighlight lang="java"> public static <T> void sort(T[] a, Comparator<? super T> c) { if (c == null) { sort(a); } else { if (LegacyMergeSort.userRequested) legacyMergeSort(a, c); else TimSort.sort(a, 0, a.length, c, null, 0, 0); } } </syntaxhighlight> # 以及,'''Comparator<T>'''接口 #: <syntaxhighlight lang="java"> package java.util; ... public interface Comparator<T> { int compare(T o1, T o2); ... } </syntaxhighlight> 如: # 定义一个 Comparator<String> 接口的实现类: #: Comparator<T> 接口的方法很多,但并不用全部实现,因为一部分方法有实现,一部分为默认方法; #: <syntaxhighlight lang="java"> class LengthComparator implements Comparator<String> { public int compare(String first, String second) { return first.lengthO - second.lengthO; } } </syntaxhighlight> # 使用Arrays.sort进入数组比较: #: <syntaxhighlight lang="java"> String[] friends = { "Peter", "Paul", "Mary" }; Arrays,sort(friends, new LengthComparatorO): </syntaxhighlight> # 也可以,单独对两个对象或两个数组元素进行比较: #: <syntaxhighlight lang="java"> Comparator<String> comp = new LengthComparator。; if (conp.compare(words[i], words[j]) > 0) </syntaxhighlight> * Comparator.compare 并非静态方法,所以使用时需要 Comparator实例; === 对象克隆 === ==== 拷贝和克隆 ==== [[File:拷贝和克隆.png|400px]] # 为一个包含对象引用的变量建立副本,直接赋值即可,原件副本都是同一个对象的引用; # 若希望为对象也创建一个副本,则应该使用克隆; ==== 浅拷贝(Object.clone()) ==== [[File:浅拷贝.png|400px]] 默认的克隆操作(“Object.clone()”)是“浅拷贝”:如果对象包含子对象的引用,拷贝域会得到相同子对象的另一个引用; * 即,原对象域浅克隆对象会引用相同的子对象; # Object.clone() 是Object的一个protected方法; # 若,子对象属于一个不可变的类,或在生命周期中状态不变,则是安全的;否则不应该使用浅拷贝; ==== 深拷贝(Cloneable 接口) ==== Cloneable 接口时Java提供的一组标记接口(tagging interface,或称记号接口 marker interface): * 标记接口不包含任何方法,它的唯一作用就是允许在类型查询中使用 instanceof; * 即使 clone 的默认实现(浅拷贝)满足要求,还是需要实现 Cloneable 接口,将 clone 重新定义为 public,再调用 super.clone(): <syntaxhighlight lang="java"> class Employee implements Cloneable { // raise visibility level to public, change return type public Employee clone() throws CloneNotSupportedException { return (Employee) super.clone(); } ... } </syntaxhighlight> 深克隆的实现: # 实现 Cloneable 接口,将 clone 重新定义为 public; # 重写 clone 方法,克隆需要的子对象(分别调用子对象的克隆方法); <syntaxhighlight lang="java"> class Employee implements Cloneable { ... public Employee cloneO throws Cl oneNotSupportedExcepti on { try { // call Object, clone0 Employee cloned = (Employee) super.cloneO ; // clone mutable fields cloned.hireDay = (Date) hireDay.clone() ; return cloned; } catch (CloneNotSupportedException e) { return null; } // this won't happen, since we are Cloneable } } </syntaxhighlight> == lambda == == 内部类 == == 代理 ==
返回至“
核心技术:接口、lambda表达式与内部类
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息