Java进阶篇

这篇博客主要记录在写Java过程中遇到的一系列问题

问题的解答会引用大牛们的解答或者博客,同样会一直更新下去...


1.如果在一个方法类里定义了一个内部类(比如匿名类),那么该内部类不能引用该方法里的非final型变量

关于这个问题的根本性解答还是比较难的。从表面上来说,我们知道变量会在方法调用完就直接销毁,而内部类呢,在方法调用完后并不一定销毁了,因此会出现内部类引用已销毁的变量,这个问题是很麻烦的,因此用final来限定,实际上变量还是会在方法结束后被销毁,但唯一不同的是内部类会有一个该变量的副本,因为final变量的值是不变的,所以存个副本是可以的,这样内部类就可以访问这个副本了。

这个只是表面解释,如果还想深入研究的话,可以看看以下这篇博客:

Java中final局部变量的生命周期   其实我也没怎么看懂里面链接的文章,实力还远远不够。


2.static不能修饰局部变量,当我们在函数中定义局部变量时,如果局部变量被static修饰,则编译器会报错。至于原因,可以这么认为:static应该是用来修饰类的成员变量和方法的,并且JVM会在程序运行前,将这些变量和方法加载到内存仅一次,这些变量和方法是独立于对象的,因此直接可以使用类.变量或者类.方法来调用。所以从生命周期来看,这些变量和方法维持了整个程序,而局部变量应该是在函数被调用时生成出来,而函数调用结束就应该立刻被销毁。所以说这两者的生命周期是冲突的。


3.Java多线程编程中的一些问题:

notify是通知哪一个等待的线程,这个取决于JVM,因此是不定的。

notify后该线程是否立即释放锁给等待的线程,答案是否定的,如果notify后面还有代码,那么该线程会继续执行下去,直到run方法结束,不妨可以在notify后加sleep代码,观察解锁时机。

这里有几篇很好的博客:notify 锁竞争


4.Java里的<>是什么?

类似C++中的模板类,Java从JDK1.5之后引入了“泛型”思想,是为了将原先强制类型转换消除掉,并将运行时错误提早到了编译时错误,因为 <>中的参数在编译时,编译器就提早知道了,所以可以类型检查。

具体参考:

http://www.cnblogs.com/yinhaiming/articles/1749738.html

http://blog.csdn.net/jinuxwu/article/details/6771121


5.Java中数组是协变的,例如可以把Integer数组变量赋给Number数组变量,因为Integer继承了Number,数组也就协同算继承过来了。但是泛型不是协变的,也就是无法将List<Integer>变量赋给List<Number>变量,否则List<Number>如果add一个Double型变量,那就会出错,这样就违背了引入泛型的初衷(类型安全)。于是Java引入通配符?,这样List<?>是一切List<T>的父类,因为编译器不知道?代表什么类型,这样就可以赋值了。但是不可以对List<?>使用add(),因为编译器并不知道?代表什么类型,因此为了类型安全,不允许增加元素(可以增加null),但可以删除或者使用元素。


6.Java里接口有三种,第一种是最正常的,有常量和抽象方法,第二种只是为了定义常量,第三种最奇葩的,里面什么也没有,仅用于标识作用

对于第三种,比如我们熟知的Serializable接口,所谓序列化接口,如果一个类不实现这个接口(也就是没获得这个标识),那么这个类就无法被序列化,然而因为这个接口仅仅是一个标识,所以序列化过程全部都得由自己实现 。

可以参考:http://blog.csdn.net/w627782664/article/details/7064338


7.final型对象不能被赋值(修改),定义的那次算初始化。但是final型对象的属性 (成员变量)是允许被修改的。这一点非常神奇。在工程里有些时候会在函数里实现内部类,这个时候对象需要被定义为final(原因见上面的第1条),但是我们却需要修改该对象的属性,所以有这条规则,那么我们就可以如愿以偿了。


猜你喜欢

转载自blog.csdn.net/u012866104/article/details/50366012