A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 刘学明    高级黑马   /  2013-5-1 22:58  /  1201 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

牛角尖一:
Final类可以有protected属性或方法吗?
这是一个典型的牛角尖,一个类被声明为final,说明该类不可被继承,如果类不能被继承,那么它可以有protected的属性和方法吗?

  答案是可以的,那么,这时的protected到底是什么访问权限叫呢?

  一个protected的属性或方法,它可以被同一包中的类访问,或是可以被子类所访问,但是现在它不能有子类,所以,这时protected其实就和默认的访问权限完全相同,变成了同一包中的类可以访问。

代码如下:
  1. package net.moon.insignificant.finalclass;

  2. final class FinalClassSuper{
  3.         protected void sayHello(){
  4.                 System.out.println("Hello, world");
  5.         }
  6. }

  7. public class FinalClassDemo{
  8.         public static void main(String[] args) {
  9.                 // TODO Auto-generated method stub
  10.                 FinalClassSuper s = new FinalClassSuper();
  11.                 s.sayHello();
  12.         }

  13. }
复制代码
牛角尖二:类初始化时的执行顺序
在初始化一个类时,到底是先执行哪一部分,总体的执行顺序是什么样的呢,同样,当类被释放时,又是怎样一个顺序呢?先来看下面的代码好了。
  1. package net.moon.insignificant.commonclass;

  2. class CommonSubClass extends CommonSupperClass {
  3.         static {
  4.                 System.out.println("Common sub static initial");
  5.         }

  6.         public CommonSubClass() {
  7.                 System.out.println("Common sub construct");
  8.         }

  9.         @Override
  10.         protected void finalize() throws Throwable {
  11.                 // TODO Auto-generated method stub
  12.                 System.out.println("Common sub finalize");
  13.                 super.finalize();

  14.         }
  15. }

  16. abstract class CommonSupperClass {
  17.         public CommonSupperClass() {
  18.                 System.out.println("Common super construct");
  19.         }

  20.         static {
  21.                 System.out.println("Common supper static initial");
  22.         }

  23.         @Override
  24.         protected void finalize() throws Throwable {
  25.                 // TODO Auto-generated method stub
  26.                 System.out.println("Common supper finalize");
  27.                 super.finalize();

  28.         }
  29. }

  30. public class Demo {
  31.         public static void main(String[] args) {
  32.                 // TODO Auto-generated method stub
  33.                 CommonSubClass css = new CommonSubClass();
  34.                 css = null;
  35.                 System.gc();

  36.         }

  37. }
复制代码
只要运行上面的代码,结果如下:
  1. Common supper static initial
  2. Common sub static initial
  3. Common super construct
  4. Common sub construct
  5. Common sub finalize
  6. Common supper finalize
复制代码
其实大家已经清楚,在初始化时,执行的顺序是:

1.  父类的静态代码块

2. 子类的静态代码块

3. 父类的构造方法

4. 子类的构造方法



  释放资料时,执行的顺序是:

1. 子类的finalize方法

2. 父类的finalize方法

只是这里一个意外是:竟然父类为抽象类时也同样会调用父类的构造方法,看来抽象类在虚拟机内部还是被实例化了。


牛角尖三:Java中只支持单继承吗?
又是一个牛角尖,只是语言不够严谨而已,Java中只支持类的单继承,接口之间的继承同样也是使用extends关键字,但是接口之间是支持多继承的,如下面的例子:
  1. interface IP1 {
  2. }

  3. interface IP2 {
  4. }

  5. public interface ISub extends IP1, IP2 {

  6. }
复制代码
很明显,上面的代码是没有问题的。所以标题中的应该是不严谨的,严格的说应该是Java中类的继承只支持单继承。

  当然,这样我们自然会想到多继承的问题,如果两个父接口中有同样的方法,那么子接口中怎么办呢?
  1. interface IP1 {
  2.         public void test();
  3. }

  4. interface IP2 {
  5.         public void test();
  6. }

  7. public interface ISub extends IP1, IP2 {

  8. }
复制代码
其实这个问题不用担心,因为接口只是对方法的一个声明,并没有具体的实现,所以子接口中的方法属于哪个父接口并不重要,重要的是当实现这个接口的时候只需有一个该方法的实现就可以了,这个方法的实现应该同时属于两个父接口。

  很明显,这不是真正的问题,真正的问题是如果在两个父接口中分别定义了名称和参数都相同,而返回结果却不同的方法:
  1. interface IP1 {
  2.         public void test();
  3. }

  4. interface IP2 {
  5.         public String test();
  6. }

  7. public interface ISub extends IP1, IP2 {

  8. }
复制代码
这同已经有问题了,这时会有编译时错误,原因很简单,方法的重载只能是相同的方法名,不同的输入参数;而对于这两个方法,它们具有相同的方法名,相同的输入参数,只是不同的返回参数,是不能作为重载方法的,所以对于编译器来说,这里是一个方法的重复定义,明显是不能通过编译的。

  同样,这样的问题也存在于一个类同时实现多个接口的情况,所以,在这些情况下,我们必须注意一点,就是具有相同方法名,相同输入参数的方法,是不能出现在同一个类或接口中的。

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

3 个回复

倒序浏览
不错!顶一个
回复 使用道具 举报
楼上的太强了。。。。小弟佩服佩服
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马