第一题:
   class Something{
        final int f;
      public void doSomething(){
            System.out.println("f="+f)
        }
    }
第二题:
    abstract class Something{
        private abstract void doSomething();
    }
为什么毫无意义?我先给出我最初的答案
1)f=0
2)没有错误
这是我面试的时候写的答案,当时以为没错,因为这完全符合java的语法
1)Something类在实例化的时候,会对成员变量进行初始化,f会被赋值于0,按照语法结果就是f=0,可是实际上不是。Java编译器为了减少人犯低级错误,对final修饰的变量不会再进行默认初始化,而是强制要求你显示的赋一个值。Java编译器考虑的可真周到啊,把它自己的语法都给推翻了。这么低级的程序我是写不出来,所以我答错了。
2)这一题按照语法也没错了,可是为什么会被编译不过去呢,说白了原因也就是Java编译器为我们考虑太周到了,我们为什么要在抽象类中定义一个抽象方法,我们大家都知道抽象类是不能实例化,定义抽象方法就是为了定义一个子类来继承该抽象类并实现它的抽象方法,但是题目中给定的抽象方法是private修饰的,也就是说它是不能被继承的,也就是说我们根本不肯能写出来一个能实现该抽象方法的类,说的更具体一点也就是这个抽象类被定义的毫无意义。Java编译器真是太强了,连这个也被考虑到了,反正我是从来没写过这么低级的程序,更不会去写出来一个毫无意义的抽象类。
一句话,这两道题考得不是final和abstract的语法,因为完全合法,而是语义,也就是Java编程规范。
 PS:关于为什么final修饰的成员变量不能被默认初始化的问题,我想了很久,终于想明白了。我们大家都知道对象初始化分为三步:
1)默认初始化
2)赋值初始化
3)构造方法初始化
如果你在类中定义的是一个普通的成员变量非final成员变量,对该类的对象初始化时,该成员变量会严格按照以上三步进行初始化。如果是该类的成员变量是用final修饰的,该类对象初始化时,对该成员变量的初始化按照常规也应该由这三步组成,但是由于final修饰的变量是常量,不能进行二次赋值,所以对该类型的变量初始化只能由其中一步来完成,不能出现交叉,否则会有编译错误。下面是两个可以正常编译、运行的写法:
/**
 * 
 * 
@author <a href="mailto:flustar2008@163.com">flustar</a>
 * 
@version 1.0 Creation date: Mar 22, 2008 7:18:18 PM
 
*/

public class TestFinal {
    
final int f=1;
    
public void doSomething() {
        System.out.println(
"f=" + f);
    }

    
public static void main(String args[]) {
        TestFinal test 
= new TestFinal();
        test.doSomething();
    }

}

/**
 * 
 * 
@author <a href="mailto:flustar2008@163.com">flustar</a>
 * 
@version 1.0 Creation date: Mar 22, 2008 7:18:18 PM
 
*/

public class TestFinal {
    
final int f;
    
public TestFinal(){
        f
=1;
    }

    
public void doSomething() {
        System.out.println(
"f=" + f);
    }

    
public static void main(String args[]) {
        TestFinal test 
= new TestFinal();
        test.doSomething();
    }

}
下面再让我们回过头来看看下面这个程序它完全符合Java的语法:
class Something{
        
final int f;
      
public void doSomething(){
            System.out.println(
"f="+f)
        }

    }

为什么说它完全符合语法:
1)按照常理会对f默认初始化为0;
2)程序中并没有出现交叉,也就是说并没有进行二次赋值的可能。
但是编译器为什么不放过它呢?
现在让我们来假设一下如果不给f变量不显示的赋一个值,它一定会被初始化为0,按照final的定义一旦被初始化一个值后就不能修改了,也就是说f的值只能是0了。再想想当初我们为什么要定义一个final修饰的常量,难道仅仅就是为了得到一个默认的不能修改的初始值吗,这恐怕有违我们当初定义final变量的真正意愿,那么我定义这个final变量又有何意义呢。所以在对对象进行初始化时,发现对象的成员是用final修饰的就会查看它是否被显示的赋了值,如果没有就会不能正常编译。这也是Java编程规范中为什么要强制对final变量进行显示赋值的真正原因。同样的道理在abstract类里面定义private abstract方法,这个又有何意义呢?Java中把那些符合语法但不符合常规的用法定义成了规范,我想这也是Java为什么会有编程规范的原因吧,呵呵,扯远了。。。

Feedback

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-20 23:56 by
太依赖IDE不是一件好事

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 00:11 by Robin's Java World
这样的题确实没有什么实际意义。
这是在做学究。
如果不是做编译器的开发,我相信这没什么意义!

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 00:36 by Empressement Conduct
对于第一题的"Java编译器为了减少人犯低级错误,对final修饰的变量不会再进行默认初始化,而是强制要求你显示的赋一个值。" 这个可以理解,最起码让你不在犯一些错误,比如有时忘了初始化,如果它的初值并不是0,那样不是有错误出现么

对于第二题,是有些难于理解,但是不变态。
既然任何非该类的成员不能访问该类的任何私有方法,那么Something这个类声明为抽象类,是毫无意义;可是“abstract 类的任何子类必须实现在父类中定义声明的所有abstract 方法,如果子类不去实现,那么子类必须声明为abstract 类。”
所以,这个题是毫无意义,但是不变态。

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 00:41 by Empressement Conduct
他们面试是为了考验你的基础知识是否扎实,出一个毫无意义的题,也肯定是有目的,所以你就要想到他们为什么要给出个毫无意义的题,究竟是什么目的,这个毫无意义的题,究竟从正面和侧面还有反面都能反应出些什么问题来,这些都要去想一想

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 00:42 by xdcsoft
面试是这样的?没什么好讲的
你认为变态吧,他也认为你连这个基础都不知道
我实事论事啊

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 00:48 by apache
虽然没什么意义,但不算变态.
第二题很明显不符合面向对象思想.

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 01:16 by 阿光
第一道题确实觉得很意外,.呵呵,学到知识了.
第二道题就很正常了.abstract嘛,博主基础知识还不行呀,得加强加强.

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 02:31 by 王小二
同学,你真的是学艺不精啊!
final int f;
人家考的是final这个关键字的意义,你连考点都不知道,还对出题的人……
因为final是一个定义编译期常量,所以必须赋值。而且出题的人已经很厚道了,他没有通过考你接口中 定义域可能出现的问题,来测试你对final的理解就已经不错了。
你自己做人要厚道,还有那些不懂装懂的留言者,也附和说什么……
看看《thinking in java》吧

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 08:10 by Matthew Chen
个人做的话都不会出错,ide并不会造成学习上的问题,因为我以前都试过用ide写各种各样的代码,也出过类似的问题,一句话,从语言本身健壮性所赋予的行为,很容易理解的。

# re: 今天遇到的两道比较变态的面试题[未登录]  回复  更多评论   

2008-03-21 09:27 by allenny
很多公司面试喜欢用这样的题,不管面试的是什么职位,好像他们很有水平。

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 09:37 by raof01
@Empressement Conduct
同意你!
第一题的确变态,抠细节~计算机科学里细节多了,要是抠得细的话谁也别想好。第二题就是纯粹的面向对象的东西,答不对只能说明学艺不精,还得再练练。

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 09:37 by yangkun
笨蛋

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 09:40 by 逝者如昔
抽象类是不能定义private方法的啊

# re: 今天遇到的两道比较变态的面试题[未登录]  回复  更多评论   

2008-03-21 09:45 by roy
晕。。。基础知识不过关还说人BT。。。

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 09:52 by 飘然
这个,只能说这两个题比较扣细节,但是如果编程经验比较丰富,应该可以应付过来的。

第一道题我在编程开发中实际遇到过,“Java编译器考虑的可真周到啊,把它自己的语法都给推翻了。”呵呵,能说出这句话的,只能说楼主你对java的认识还远不够,连final的用法都没有理解。

第二道题就不说了,还是那句话,没有编程经验和oo的常识。private + abstract,你让基类怎么实现?

这两个题虽然都不是可以一眼就看出答案的那种,但是稍微细想一下都可以推出来的。

另外:真正变态的题目楼主应该还没有见识过,我只能说上面这两个相比只是小儿科。

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 10:42 by ZelluX
很正常啊,初始化final字段和私有的抽象方法逻辑上都不应该存在的。

可以看看Java Language Specification
8.4.3.1
It is a compile-time error for a private method to be declared abstract.

# re: 今天遇到的两道比较变态的面试题[未登录]  回复  更多评论   

2008-03-21 10:46 by 咖啡
看来你的经验还是不够啊.应该想想没有那么简单才对阿

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 12:22 by ITAX
不是刺激LZ,我觉得这两道题太简单了。简单到其实是白送分的。(第一题我进现在的公司就做过.......)
其实这些问题非常基础的,对于我这个看完Thinking in Java好几年的人都记得书里清楚的写了。建议LZ再好好看看基础为好。

# re: 今天遇到的两道比较变态的面试题  回复  更多评论   

2008-03-21 14:25 by flustar
其实面试回来我就意识到自己太大意了,既然是查错,肯定有错误,我怎么能说它没错呢 哎!~
第二题,定义一个抽象类,里面有个私有的抽象方法,抽象类不能被实例化,子类继承该抽象类也不能实例化,因为它不能实现父类的抽象方法。也就是说这个抽象类被定义的一点意义也没有。我也知道这道题很简单,简单到白送分,可是当你做了长达8页的试卷之后,再来看这个题,我眼睛都花了,头脑发胀,哪还有心思想那么多。
第一题,考察的是final变量的用法,何为final变量也就是常量,一旦被赋值后就不能再赋值的变量。可是题目中并没有对它进行二次赋值啊,第一次赋值应该是该类进行实例化时,成员变量f的值被初始化为0。谁知道final类型的成员变量不能被自动初始化啊。如果你不是以前在哪个地方看到过,你能做出来,这样东西除非你看过或者以前犯过这么低级的错误,才知道。我犯过,现在我就知道了。
可是让我不明白的是为什么用final修饰的成员变量不能被自动初始化,有谁知道,记得告诉我啊!

# re: 今天遇到的两道毫无意义的面试题  回复  更多评论   

2008-03-21 16:21 by ZelluX
@flustar
final被赋值后不是不能修改了吗。。。
那对这个变量的初始化赋值还有什么意义呢?

# re: 今天遇到的两道毫无意义的面试题  回复  更多评论   

2008-03-21 16:38 by 路人乙
@flustar
为什么问得很没意义,规则!

# re: 今天遇到的两道毫无意义的面试题  回复  更多评论   

2008-03-21 20:03 by Empressement Conduct
这位朋友,谢谢了啊!!
呵呵,今天翻阅资料发现自己昨天留言有错误,
final修饰符可应用于类、方法、和变量。final变量的内容不能更改,因此,声明final变量时,必须将其初始化。
准备纠正时发现你的留言已经纠正了,
呵呵,再次感谢啊,本人也是初学Java,希望以后多多交流。
@王小二

# re: 我现在才发现我那天遇到的两道面试题不但不变态而且还很有意义  回复  更多评论   

2008-03-23 15:37 by 王小二
^ _ ^

# re: 我现在才发现我那天遇到的两道面试题不但不变态而且还很有意义  回复  更多评论   

2008-04-09 00:41 by stanleyxu
I think it is nonsense. If it can be compiled or not, is the job of javac.exe.
If I were employer, I might ask:
1. What is the difference between list and array.
2. What is the difference between abstraction and interface.
3. String manipulation etc.

Anyway, you will collect more and more experience while doing real programming. Good luck

只有注册用户登录后才能发表评论。


网站导航:
 

posts - 146, comments - 143, trackbacks - 0, articles - 0

Copyright © flustar