面试必备八股文第一篇(JAVA基础篇)
- == 和 equals() 的区别
- 为什么要有 hashCode?
- 为什么jdk要同时提供equlas和hashcode呢?
- 那为什么不只提供 hashCode() 方法呢?
- 那为什么两个对象有相同的 hashCode 值,它们也不一定是相等的?
- 为什么重写 equals() 时必须重写 hashCode() 方法?
- 重写 equals() 时没有重写 hashCode() 方法的话,使用 HashMap 可能会出现什么问题?
- String、StringBuffer、StringBuilder 的区别?
- 为什么java9要把String底层char[]改成byte[]
- 你知道底层使用常量池的有哪些?
- static存在的意义
- static使用场景(静态只能访问静态,非静态访问两者都OK)
- static变量会被序列化吗?
- 谈谈这四种访问权限修饰符public/protected/default/private
- this和super的区别
- 面向对象五大基本原则是什么
- 静态变量和实例变量区别
- 局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final?
- Java 序列化中如果有些字段不想进行序列化 怎么办
- 元注解Annotation
- 内部类概念与使用
- NoClassDefFoundError 和 ClassNotFoundException 区别?
- try-catch-finally 中,如果 catch 中 return 了, finally 还会执行吗?
- 什么是反射?优缺点?应用场景?
- 谈谈对静态代理的了解?
- 什么是动态代理?底层源码了解过吗?
== 和 equals() 的区别
基本数据类型是比较字面量值,引用数据类型是比较地址值
equals比较两个对象内容是否相等,如果未重写equals方法比较的也是对象的地址值
为什么要有 hashCode?
key-value根据key快速检索值,散列码
比如HashMap插入时,先根据hashCode来判重,无则添加,有则再次判断equals方法。减少equals比较次数,提高效率
为什么jdk要同时提供equlas和hashcode呢?
减少equals比较次数,提高效率
那为什么不只提供 hashCode() 方法呢?
hashCode值相等并不代表两个对象就相等,因为存在hash冲突
那为什么两个对象有相同的 hashCode 值,它们也不一定是相等的?
如果两个对象的hashCode 值相等,那这两个对象不一定相等(哈希碰撞)。
如果两个对象的hashCode 值相等并且equals()方法也返回 true,我们才认为这两个对象相等。
如果两个对象的hashCode 值不相等,我们就可以直接认为这两个对象不相等。
为什么重写 equals() 时必须重写 hashCode() 方法?
因为两个相等的对象的 hashCode 值必须是相等。也就是说如果 equals 方法判断两个对象是相等的,那这两个对象的 hashCode 值也要相等。
如果重写 equals() 时没有重写 hashCode() 方法的话就可能会导致 equals 方法判断是相等的两个对象,hashCode 值却不相等。
重写 equals() 时没有重写 hashCode() 方法的话,使用 HashMap 可能会出现什么问题?
Key对象没有重写hashcode方法,equals相等的对象却有不同的hashcode值,所以会当成不同的key处理,相当于没有去重,数量多容易出现OOM内存溢出。
String、StringBuffer、StringBuilder 的区别?
相同点:jdk1.8及以前底层是char[],jdk1.8以后底层使用byte[]
String:final,不可变(通过反射可以改变),少量数据适用
StringBuilder: 单线程适用,线程不安全
StringBuffer:多线程适用,线程安全,底层sync同步锁
为什么java9要把String底层char[]改成byte[]
节约内存,英文还需要配合Latin-1编码方式,中文配合UTF-16,byte1个字节,char2个字节
你知道底层使用常量池的有哪些?
除Long之外,还有Byte,Short,Integer,Long,Character都实现了常量池,除Character外,范围都是(-128~127);Character的范围是(0-127)。
static存在的意义
1、static的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法(也就是优先于对象存在)
2、静态代码块优化代码性能(因为只在类加载时候执行,分配空间,有且只有一次,后面可以赋值)
3、被static修饰的属性和方法被所有实例共享
static使用场景(静态只能访问静态,非静态访问两者都OK)
1、修饰成员变量
2、修饰成员方法
3、静态代码块
4、修饰类【只能修饰内部类也就是静态内部类】
5、静态导包
static变量会被序列化吗?
static 变量因为不属于任何对象(Object),所以无论有没有 transient 关键字修饰,均不会被序列化。
谈谈这四种访问权限修饰符public/protected/default/private
修饰符 | 当前类 | 同包 | 子类 | 其他包 |
---|---|---|---|---|
private | √ | × | × | × |
default | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
this和super的区别
this本类调用本类使用,super子类调用父类使用
this()和super()指的都是对象,均不可以在static环境中使用
this相当于一个指针,super是java关键字
面向对象五大基本原则是什么
单一职责原则SRP(Single Responsibility Principle)类的功能要单一,不能包罗万象,跟杂货铺似的。
开放封闭原则OCP(Open-Close Principle):一个模块对于拓展是开放的,对于修改是封闭的,想要增加功能热烈欢迎,想要修改,哼,一万个不乐意。
里式替换原则LSP(the Liskov Substitution Principle LSP)子类可以替换父类出现在父类能够出现的任何地方。比如你能代表你爸去你姥姥家干活。哈哈~~
依赖倒置原则DIP(the Dependency Inversion Principle DIP)高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。就是你出国要说你是中国人,而不能说你是哪个村子的。比如说中国人是抽象的,下面有具体的xx省,xx市,xx县。你要依赖的抽象是中国人,而不是你是xx村的。
接口分离原则ISP(the Interface Segregation Principle ISP)设计时采用多个与特定客户类有关的接口比采用一个通用的接口要好。就比如一个手机拥有
打电话,看视频,玩游戏等功能,把这几个功能拆分成不同的接口,比在一个接口里要好的多。
静态变量和实例变量区别
静态变量: 静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静态变量分配一次内存空间。
实例变量: 每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量。
局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final?
因为生命周期不一致, 局部变量直接存储在 栈中,当方法执行结束后,非final的局部变量就被销毁。而局部内部类对局部变量的引用依然存在,如果局部内部类要调用局部变量时,就会出错。加了final,可以确保局部内部类使用的变量与外层的局部变量区分开,解决了这个问题。
Java 序列化中如果有些字段不想进行序列化 怎么办
transient 关键字的作用是:阻止实例中那些用此关键字修饰的的变量序列化;当对象被反序列化时,被transient 修饰的变量值不会被持久化和恢复。 transient 只能修饰变量,不能修饰类和方法。
元注解Annotation
@Target 修饰的对象范围
@Retention 定义被保留的时间长短
@Documented 描述-javadoc
@Inherited 阐述了某个被标注的类型是被继承的
内部类概念与使用
1、静态内部类
静态内部类可以访问外部类所有的静态变量和方法,即使是private的也可以,因为静态的属性或方法是独立于类存在,在运行时就已经在内存里
其它类使用静态内部类需要使用“外部类.静态内部类”方式
2、成员内部类
定义在类内部的非静态类,就是成员内部类。成员内部类不能定义静态方法和变量。
3、局部内部类(定义在方法中的类)
定义在方法中的类,就是局部类。如果一个类只在某个方法中使用,则可以考虑使用局部类。
4、匿名内部类(要继承一个父类或者实现一个接口、直接使用 new 来生成一个对象的引用)
NoClassDefFoundError 和 ClassNotFoundException 区别?
NoClassDefFoundError:Error错误类型,编译存在,运行找不到,JVM或ClassLoader抛出,可能是编译后该类被删除
ClassNotFoundException:受检异常,编译时候就异常
try-catch-finally 中,如果 catch 中 return 了, finally 还会执行吗?
会执行,在return前执行。
如果finally里面包含return,直接返回
什么是反射?优缺点?应用场景?
对于任意一个类,都能知道这个类的属性和方法,可以获取私有的属性和方法
优点:动态加载类 缺点:反射相当于多了一系列操作,影响性能,所以我们平时都是直接使用new对象,而不是通过反射来获取
场景:1、JDBC链接,Class.forName() 2、Spring的xml配置
谈谈对静态代理的了解?
代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。实际操作由代理类操作被代理类
缺点:改动需要同时改变代理类和被代理类
什么是动态代理?底层源码了解过吗?
动态代理类就是定义代理类的时候可以直接实现 implements InvocationHandler,通过传参区分是哪个类进行动态操作
作用:主要作用,还是在不修改被代理对象的源码上,进行功能的增强。
如何使用:
例子:SellWine dynamicProxy = (SellWine) Proxy.newProxyInstance(MaotaiJiu.class.getClassLoader(),MaotaiJiu.class.getInterfaces(), guitaiA);
Proxy.newProxyInstance源码:
1、newProxyInstance创建了一个实例,先从缓存获取,获取不到从ProxyClassFactory生成
2、指定的 ClassLoader 和 接口数组 用工厂方法生成 proxy class,所以动态生成的代理类名称是 包名 + $Proxy + id序号