java基础面试题
- 一、String、StringBuffer、StringBuilder三者的区别
- 二、==和equals的比较
- 三、String为什么是不可变的
- 四、什么是面向对象编程
- 五、权限修饰符的修饰权限
- 六、HashSet底层原理(jdk1.7和jdk1.8之后对比)
- 七、ArrayList底层原理
- 八、重写equals为什么要重写hascode
- 九、list集合与set集合的特点
- 十、TreeSet中比较器
- 十一、hash值的计算
- 十二、jdk、jvm、jre的联系与区别
- 十三、JDK1.8之前和JDK1.8之后定义接口不同?
- 十四、接口与抽象类的区别
- 十五、局部变量与成员变量的区别
- 十六、值传递和引用传递的区别
- 十七、重写和重载的区别
- 十八、基本数据类型和其包装类的区别
- 十九、为什么要有包装类
- 二十、包装类与基本数据类型怎样进行转换
- 二十一、构造器代码块、局部代码块、静态代码块执⾏顺序和执⾏次数?
- 二十二 、构造器代码块的作用
- 二十三、Integer String 是否可以被继承?为什么?
- 二十四、String str = "abc" 和 String str = new String("abc")区别?
- 二十五、this和super的区别
- 二十六、break、continue、return
- 二十七、抽象类可以被final修饰吗?
- 二十八、java和C++的区别
- 二十九、字符常量和字符串常量的区别
一、String、StringBuffer、StringBuilder三者的区别
- string是只读字符串,其中的值是不可以改变的
- StringBuffer、StringBuilder的字符串的值是可以改变的。
- StringBuilder单线程环境下使用,效率要比StringBuffer高
- StringBuffer加锁了,更加线程安全。
二、==和equals的比较
- == 比较的是两者内存空间的地址值是否相同
- equals比较的是内存空间内容的值是否相同
- 但当没重写equals方法时,由于所有的类都是继承Object类的,所以调用的equals方法依然调用的Object类中的方法,而object中的equals方法返回的是==的判断,所以使用equals比较的时候还是比较的是地址值。
三、String为什么是不可变的
- 只有是不可变的才可以创建字符串常量池
- 只有是不可变的才会保证线程安全问题,被多线程共享数据
- 只有是不可变得在创建的时候就被hashCode缓存,不需要重新计算hash值,所以更适合做map集合的键
- 只有是不可变的,才可以避免很多安全问题
四、什么是面向对象编程
- 面向对象编程相对于而言的是面向过程编程。
- 举个例子来说,我们洗衣服的时候,面向过程讲究的是,每一步洗衣服的步骤,取出衣服,把衣服放到洗衣机,加入洗衣粉等等…着重于每一个步骤的进行。 面向对象会将洗衣服这件事儿,封装成洗衣机和人两个对象,并给洗衣机和人付一定的属性和值,然后执行洗衣机洗衣服等动作,人加水、
- 面向对象具有三大特征:封装、继承、多态。
- 封装:将一些客观的事物抽象成类,每个类都具有自己的属性和方法。该属性和方法只对自己信任的类或对象操作,对不信任的类或方法进行隐藏。
- 继承:子类可以从其父类中继承到一些方法和属性,并且子类也可以修改和新增一些属于自己的方法,增加了代码的复用性
- 多态:允许不同的类的对象对同一个消息作出响应,可以使不同的对象调用相同的方法相同的参数,也可以拿到不同的行为。
五、权限修饰符的修饰权限
-
private 只能在本类中使用
-
protected 本类中以及子类中
-
默认不写 本类中、本包中的子类和无关类
-
public 全部都可以使用
教你用面向对象的思想来记住这两个
假如你作为一个父亲,你的名字是公开的(public),你的双手是私有的(private)
你的房子是默认的的(default),但是你的妻子在你的房子里可以住你的房子,
你的money是受保护的(protected),但是你的子女可以用你的money
六、HashSet底层原理(jdk1.7和jdk1.8之后对比)
jdk1.7是 数组+链表结构 jdk1.8是数组+链表+红黑树
- 当第一次初始化之后,会默认创建一个长度为16,默认因子为0.75的数组
- 存入新值的时候会用哈希值和数组长进行计算存入的位置。
- 当位置为空时,直接将值存入,当位置不为空时,调用equals比较属性值,如果属性值相同则不存,如归属性值不同则以链表的形式存入数据。
- jdk8之后,当存储的链表的长度大于8的时候,则将自动转换为红黑树
- 当存储容量达到阈值时,创建一个长度为原来2倍的数组,将原数组元素使用transfer()方法赋值到新的数组中,新增的元素也增加在新数组中。
补充:为什么扩容因子是 0.75?
- 扩容因子表示 Hash 表中元素的填充程度,扩容因子的值越大,那么触发扩容的元素个数更多,虽然空间利用率比较高,但是 hash 冲突的概率会增加。
七、ArrayList底层原理
- ArrayList底层是基于数组实现的,初始时会创建一个长度为10的数组。
- 随着元素的增加,会触发底层的自动扩容机制,然后会创建一个新的数组,该数组长度会扩容为原来数组的1.5倍。
- 然后使用Arrays.copy 将原数组中的元素复制到新数组中。
- 新增的元素也会增加到新数组中
八、重写equals为什么要重写hascode
- 因为在集合中,hashset等集合底层在加入新值的时,会调用到equals方法
- 当位置不为空时,会使用equals方法判断属性值是否相同,如果相同则不存入,如果不同则将存入。
- 如果不重写equals方法,则调用时候默认比较的是地址值,此时可能将会产生数据的丢失。
- 总结:集合中会使用hash值来判断该值的存储位置,hash值又是由对象地址值或者属性值计算出来的,如果不重写equals方法,将会使用地址值计算出hash值,则同一个对象中的多个值就无法加入。
九、list集合与set集合的特点
- list集合:
- 存储有序 :存入和取出的元素都是有顺序的
- 有索引 : 集合中的元素是带索引值的
- 可重复: 集合中的元素是可以重复的
- list集合中包含的分支
- ArrayList 底层是数组实现的
- LinkedList 底层是链表结构
- set集合的特点
- 存取无序 : 存进去的值的顺序,和拿出来的时候的值得顺序是不一致的
- 无索引: 集合中的元素 没有索引值
- 不可重复: 集合中的元素是不可以重复的
- set集合下的分支结构
- TreeSet 底层是树结构 (使用时需要定义比较规则)
- HashSet 底层也是哈希表结构
十、TreeSet中比较器
- 自然排序
- 使用空参构造TreeSet集合
- 自定义类要实现Comparable接口
- 重写Comparable接口中compareTo方法
- 比较器排序
- 使用带参构造, 创建TreeSet集合
- 比较器排序, 就是让集合构造方法接收Comparator的实现类对象, 重写compare方法
- 重写compare方法要注意, 排序规则必须按照要求的"主要条件"和"次要条件"来写
十一、hash值的计算
hash值为jdk由对象地址值或者属性值计算出来的结果
十二、jdk、jvm、jre的联系与区别
- jvm:java虚拟机,java平台的程序运行在java虚拟机上,每个平台都有自己对应的jvm,所以也实现了java的跨平台开发
- jre:包含了java虚拟机和java程序所需要的核心类库。这些核心类库主要是java.long包:包含了一些基本数据类,基本数学函数,以及线程异常等
- jdk:java开发工具包,里面包含了jvm和jdk。比如编译工具,和打包工具等。
十三、JDK1.8之前和JDK1.8之后定义接口不同?
- jdk1.8之前:
- 只能定义抽象方法和静态常量
- jdk1.8之后:
- 加入了default方法和静态方法
- 使用方法
- 静态常量需要用接口名直接调用
- 抽象方法,必须有实现类的重写,实现类对象可以调用
- default由实现类对象调用
- 静态方法 直接由接口名称调用
十四、接口与抽象类的区别
- 抽象类是被子类继承,接口是子类实现类
- 一个类只能继承一个抽象类但是可以实现多个接口
- 抽象类有构造方法、接口没有构造方法
- 抽象类可以main方法,接口不能有main方法
- 接口中的类的访问权限只能是public 抽象类中的访问权限可以是任何权限。
十五、局部变量与成员变量的区别
- 局部变量:
定义在方法中,随着方法的存在而存在消失而消失,并且只能在本方法中使用,且必须初始化 - 成员变量:
定义在类中且分为两种静态成员变量和非静态成员变量
静态成员变量:随着类的加载而生成,类的停止而消失,其默认初始值为null,或者0
非静态成员变量:随着对象的创建而生成,对象被回收而消失,且只能被非静态方法调用。
十六、值传递和引用传递的区别
- 值传递就是传递的是真实的值
- 引用传递是传递的是对象的地址值
十七、重写和重载的区别
- 重写:子类重写父类的方法。修改父类的行为。
- 重载:类中存在方法名相同,参数列表不相同的方法
十八、基本数据类型和其包装类的区别
- 包装类:是对基本数据类型的封装。
十九、为什么要有包装类
要对基本数据类型进行一些操作,并且使用包装类还可以获取到基本数据类型的最大值范围一集最小值范围
二十、包装类与基本数据类型怎样进行转换
- 在jdk5之后提供了自动装箱拆箱的操作
- 包装类型转换为基本数据类型:自动拆箱操作
- 基本数据类型转换为包装类:自动装箱操作
- 在jdk5之前使用
拆箱:对象.xxxValue()
装箱:包装类.ValueOf()
二十一、构造器代码块、局部代码块、静态代码块执⾏顺序和执⾏次数?
- 执行顺序:
- 静态代码>构造器代码块>局部代码块
- 静态代码块:随着类的加载而加载
- 构造器代码块:对象被创建的时候,任意构造方法被执行之前
- 局部代码块:方法被调用的时候
- 以上三种如果存在多个,则依次按顺序执行
- 执行次数:
- 静态代码块:执行一次
- 构造器代码块:每次创建对象都会执行
- 局部代码块:每次调用方法都会被执行
二十二 、构造器代码块的作用
- 将所有构造方法的公共代码放在构造器代码块中
- 匿名内部类的初始化操作
二十三、Integer String 是否可以被继承?为什么?
不能,因为被fina修饰
二十四、String str = “abc” 和 String str = new String(“abc”)区别?
- String str = “abc” 中的“abc”放在字符串常量池中,src指向字符串常量池
- String str = new String(“abc”) 中的“abc”:
- 如果常量池中没有abc,则将在常量池中创建abc。
- 创建完成之后,将字符串常量池中的abc复制到堆中
- str指向堆中的地址值
二十五、this和super的区别
- this:指代当前对象,谁调用就指向谁
- super:指向父类对象,并且是最近的一个父类对象
- this():调用的是本类中的其他构造方法
- super():调用的是父类的构造方法
二十六、break、continue、return
- break:跳出当前循环
- continue:结束当前循环进入下一循环
- return:结束整个方法,并可以返回响应的数据
二十七、抽象类可以被final修饰吗?
不可以,抽象类就是用来被继承的,final修饰的类无法被继承,两者相悖,所以无法修饰
二十八、java和C++的区别
- c++和java一样都是面向对象编程,且都支持封装继承多态
- c++支持多继承,java只支持单继承。但是java支持接口的多继承
- java不提供指针来直接访问内存,可以使内存更加安全
- java提供自动内存管理机制,不需要程序员手动来清理无用内存
二十九、字符常量和字符串常量的区别
字符常量:
1.字符常量使用的是单引号,字符串常量使用的是双引号。
2.字符常量相当于是一个ASCLL码值,字符串常量相当于一个地址值。
-----持续更新中-----------