前言
只有光头才能变强
Redis目前还在看,今天来分享一下我在秋招看过(遇到)的一些面试题(相对比较常见的)
0、final关键字
简要说一下final关键字,final可以用来修饰什么?
这题我是在真实的面试中遇到的,当时答得不太好,现在来整理一下吧。
final可以修饰类、方法、成员变量
- 当final修饰类的时候,说明该类不能被继承
- 当final修饰方法的时候,说明该方法不能被重写
- 在早期,可能使用final修饰的方法,编译器针对这些方法的所有调用都转成内嵌调用,这样提高效率(但到现在一般我们不会去管这事了,编译器和JVM都越来越聪明了)
- 当final修饰成员变量时,有两种情况:
- 如果修饰的是基本类型,说明这个变量的所代表数值永不能变(不能重新赋值)!
- 如果修饰的是引用类型,该变量所的引用不能变,但引用所代表的对象内容是可变的!
值得一说的是:并不是被final修饰的成员变量就一定是编译期常量了。比如说我们可以写出这样的代码:private final int java3y = new Randon().nextInt(20);
你有没有这样的编程经验,在编译器写代码时,某个场景下一定要将变量声明为final,否则会出现编译不通过的情况。为什么要这样设计?
在编写匿名内部类的时候就可能会出现这种情况,匿名内部类可能会使用到的变量:
- 外部类实例变量
- 方法或作用域内的局部变量
- 方法的参数
class Outer { // string:外部类的实例变量 String string = ""; //ch:方法的参数 void outerTest(final char ch) { // integer:方法内局部变量 final Integer integer = 1; new Inner() { void innerTest() { System.out.println(string); System.out.println(ch); System.out.println(integer); } }; } public static void main(String[] args) { new Outer().outerTest(' '); } class Inner { } } 其中我们可以看到:方法或作用域内的局部变量和方法参数都要显示使用final关键字来修饰(在jdk1.7下)!
如果切换到jdk1.8编译环境下,可以通过编译的~
下面我们首先来说一下显示声明为final的原因:为了保持内部外部数据一致性
- Java只是实现了capture-by-value形式的闭包,也就是匿名函数内部会重新拷贝一份自由变量,然后函数外部和函数内部就有两份数据。
- 要想实现内部外部数据一致性目的,只能要求两处变量不变。JDK8之前要求使用final修饰,JDK8聪明些了,可以使用effectively final的方式
为什么仅仅针对方法中的参数限制final,而访问外部类的属性就可以随意
内部类中是保存着一个指向外部类实例的引用,内部类访问外部类的成员变量都是通过这个引用。
- 在内部类修改了这个引用的数据,外部类再获取时拿到的数据是一致的!
那当你在匿名内部类里面尝试改变外部基本类型的变量的值的时候,或者改变外部引用变量的指向的时候,表面上看起来好像都成功了,但实际上并不会影响到外部的变量。所以,Java为了不让自己看起来那么奇怪,才加了这个final的限制。
参考资料:
- java为什么匿名内部类的参数引用时final?https://www.zhihu.com/question/21395848
一、char和varchar的区别
- char是固定长度,varchar长度可变。varchar:如果原先存储的位置无法满足其存储的需求,就需要一些额外的操作,根据存储引擎的不同,有的会采用拆分机制,有的采用分页机制。
- char的存储方式是:英文字符占1个字节,汉字占用2个字节;varchar的存储方式是:英文和汉字都占用2个字节,两者的存储数据都非unicode的字符数据。
- char是固定长度,长度不够的情况下,用空格代替。varchar表示的是实际长度的数据类型
选用考量:
