这个系列会长期更新!
如果你想每天和我打卡面试题、交流技术,可以关注一下我的个人博客网站:文客,我会每天在这里更新技术文章和面试题,也会及时收到大家的评论与留言,欢迎各位大佬来交流!
谈谈你对 JVM JDK 和 JRE 的理解(JDK 和 JRE 的区别是什么?)。
JVM是就是Java虚拟机,它可以运行Java字节码,它针对不同的系统有特定的实现,目的就是为了在不同的系统上运行相同的字节码能得到相同的结果。字节码与不同系统下的JVM是实现Java“一次编译,处处运行”的关键。
JDK是Java Development Kit的缩写,它是功能齐全的Java SDK,它包含JRE所拥有的一切,而且还有编译器等工具,可以创建和编译Java程序
JRE是Java运行时环境,它包含运行已编译的Java程序所需的内容,包括JVM、Java类库、Java命令和一些基础构件。
什么是字节码?为什么要采用字节码?
字节码是Java虚拟机能理解的代码,它不面向特定的处理器,而是面向Java虚拟机。Java通过字节码的形式,在一定程度上解决的传统解释型语言效率低的问题,同时还继承了解释型语言可移植性高的优点。由于字节码不面向特定的处理器,只面向Java虚拟机,所以Java代码无需重新编译就可以在不同的操作系统下运行。
重载和重写的区别?
- 重载属于编译时多态,而重写属于运行时多态
- 重载发生在同一个类中,而重写发生在子类或者实现类中
- 重载方法可以修改原方法的参数列表,而重写方法的参数列表必须与原方法一致
- 重载方法可以修改原方法的返回值,而重写方法的返回值必须比原方法更小或者是相等
- 重载方法可以修改访问限制,而重写方法不能提高访问限制
- 重载方法可以修改原方法抛出的异常,而重写方法抛出的异常必须比原方法的更小或者是相等
构造器 Constructor 是否可被 override?
构造器不能被继承,因此不可以被重写,但是可以重载。
谈谈 Java 面向对象编程三大特性: 封装 继承 多态
封装就是将一个对象的属性私有化,并暴露外界可以访问的接口,如果某个属性不想被外界访问,可以不提供这个属性的对外接口。
继承就是使用现有的类为基础来创建一个新类的技术。继承有如下特点:
- 子类拥有父类所有的属性和方法,但是对于父类的私有属性与方法,子类只是拥有,但无法访问(这个特性还是挺重要的,以后设计模式会具体说到)
- 子类可以增加新的属性和方法,也就是可以扩展父类
- 子类可以重写父类中的方法
多态就是我们在程序中定义的引用对象,它所指向的对象的具体类型和发出的方法调用必须在运行时才能确定。多态有如下特点:
- 一般来说,引用类型和对象类型是继承或者是实现的关系,也可能是相同的关系
- 引用对象发出的方法调用到底是哪个类中的方法,必须在运行时才能确定
- 引用对象不能调用只在子类中存在而在父类中不存在的方法
- 如果子类重写了父类中的方法,那么就会执行子类中的方法,反之则是执行父类中的方法
String str="abcd"
与 String str1=new String("abcd")
一样吗?str 和 str1 相等吗?
不一样。
第一种方式会先在字符串常量池中检索是否有“abcd”这个串,如果有的话,直接将str指向它;如果没有的话,那么会在常量池中创建这个“abcd”字符串,然后将str指向它。
第二种方式会在堆中直接创建一个“abcd”字符串对象。
所以他们是不相等的,因为一个存在于字符串常量池中,一个存在于堆内存中。
String、StringBuffer 和 StringBuilder 的区别是什么?String 为什么是不可变的?
从底层数据结构来说,String的底层数据结构是private final修饰的char数组,而StringBuffer和StringBuilder都是private修饰的char数组。
从线程安全性来说,由于String是不可变的,通常被称为常量,所以String是线程安全的。StringBuffer对每个被调用的方法都加了同步锁,所以StringBuffer是线程安全的。StringBuilder是线程不安全的。
从性能上来说, String每次改变时都会创建一个新的字符串,而StringBuffer和StringBuilder是都基于自身改变,但是由于StringBuffer是线程安全的,所以StringBuilder会获得10%-15%的性能提升。
从初始串长度来看,String的初始串长度就是串的长度,而StringBuffer和StringBuilder目前的实现是:初始串长度+16
那么String为什么是不可变的呢?
首先从底层数据结构来说,String的底层数据结构是private final修饰的char数组。在Java中,被final修饰的基本类型数值不可改变,被final修饰的引用类型不能再指向别的对象,所以严格来说的话char数组的内容是可以改变的,但是String并没有对外提供改变char数组内容的方法,而且String类也是被final修饰的,也就是说String是不可被继承的,避免了子类破坏String的不可变性。综上所述,String是不可变的。
为什么说 Java 语言“编译与解释并存”?
因为Java语言既有编译型语言的特征,又有解释型语言的特征。如果要运行Java程序的话,首先要经过编译,生成字节码,字节码的运行需要经过解释器。
字符型常量和字符串常量的区别?
- 字符型常量是基本类型,字符串常量是引用类型
- 从形式上来看,字符型常量用单引号声明,而字符串常量用双引号声明
- 字符型常量的本质其实是整数值,存储对应的ASCII码,而字符串常量代表一个地址
- 字符型常量占两个字节的内存空间,而字符串常量会占用若干个空间
静态方法为什么不能调用非静态成员?
静态方法属于类,在编译时就会分配内存,通过类名就可以调用。而类的非静态成员属于实例对象,必须声明对象才会分配内存,而且必须通过对象才能调用。如果静态方法调用非静态方法时,内存中没有该类的实例对象,那么就属于是非法操作了。
Java 静态变量和成员变量的区别
- 静态变量存在于方法区(JDK8的元空间)中;成员变量存在于堆内存中
- 静态变量属于类,也被称为类变量;成员变量属于对象,也被称为实例变量
- 静态变量与类共存亡,随着类的加载而存在,随着类的销毁而消亡;成员变量属于对象,随着对象的创建而产生,随着对象的销毁而消亡
- 静态变量既可以通过类名调用,又可以通过对象调用;成员变量只能通过对象调用