带你了解10道java入门面试题
作者:韶光不负
1. 谈谈你对面向对象的了解? (谈谈你对面向对象和面向过程的了解?)
面向对象与面向过程相比较,面向过程注重事件的步骤与顺序,比较直接高效,面向对象注重事件参与的对象与对象各己需要做的事,更易于复用,维护与扩展。(以举例来说明更加形象)
(例:拿常见手机支付来看)
面向过程
:1,手机扫码——>2,输入密码——>3,确认是否支付成功——>4,离开
面向对象
:拆出人与手机二个对象,(人:输入密码,离开,手机:手机扫码,确认是否支付成功)
下面就要谈谈面向对象的三大特征:封装。继承与多态
封装的意义
:明确标识出允许外部使用的属性与方法,内部细节对外部隐藏,外部调用无需修改和关心内部如何实现。
继承
:继承父类(基类)的方法,不包括私有化的部分,引用父类的方法或者按自己需求进行修改与扩展。
多态
:(条件:1,在继承的基础上,2,存在方法重写,3,父类的引用指向子类的对象),基于对象所属类的不同,子类对父类同一个方法的调用,实际执行的逻辑不同。(无法调用调用子类特有的方法)。
2.==与equals的比较(笔试中常见)
==
:比较的是栈中的值,基本上就是比较的变量当中的值,引用类型是堆中的内存对象地址、
equals
:Object默认采用“==”比较,通常继承后会进行重写比较的为对象的内容(例如String)。
例题:
public class Taxi { public static void main(String[] args) { String str1="hello"; String str2=new String("hello"); String str3=str2; System.out.println(str1==str2);//false System.out.println(str1==str3);//false System.out.println(str2==str3);//true System.out.println(str1.equals(str2));//true System.out.println(str1.equals(str3));//true System.out.println(str2.equals(str3));//true } }
解析:在Java中字符串是对象,字符串在生成时其实是在内存常量池当中生成。所以str1指向的“hello”的对象内存地址,str2因为new关键字在堆中开辟内存,但内存指向常量池中的“hello”,str2指向开辟内存的对象地址。str3==str2,所以str3指向str2指向开辟内存的对象地址。因为str1与str2和str1与str3“==”比较内存地址不同返回flase,str2与str3的内存地址相同返回ture,字符串方法中equals重写过,比较的是内容,str1与str2与str3的内容相同为“hello”,所以返回的是ture.
3.fianl关键字
final的作用:
类 | 该类不能被继承 |
方法 | 该方法不能被重写,但可以重载 |
变量 | 变量一旦被赋值就不能修改 |
成员变量(普通) | 在声明的时候就需要赋值,或者静态块中与构造函数中赋值 |
成员变量(静态) | 在声明的时候就需要赋值,或者静态块中赋值 |
局部变量 | 系统不会给变量初始化,必须程序员写入,在初始化时不会报错,但在使用前一定要初始化,不然报错 |
基本数据类型 | 基本数据类型的数值初始化后不能改变 |
引用数据类型 | 初始化后不能指向另一个对象,但引用的值是可以改变的 |
4.为什么局部内部类与匿名内部类只能访问局部的final变量?
首先必须知道,内部类与外部类,内部类不会因为定义在方法中,跟方法执行完一起回收,就会产生一个问题,外部方法结束时,就会回收局部变量,但内部类对象(当没有引用时回收)还存在,就存在了一个问题,内部类访问了一个不存在的变量,所以在jdk当中为了解决这个办法,局部就复制了一份内部类成员变量,当局部变量回收后仍可以访问局部变量,但实际访问的是“copy”过的值。(为了复制的局部变量必须与原局部变量一样,所以使用final修饰)
public class Management { private int id=10; //final修饰局部变量 public void outPrint(final String x){ class InClass{ public void Inprint(){ System.out.println(x); System.out.println(id); } } new InClass().Inprint(); } public static void main(String[] args) { Management m=new Management(); m.outPrint("小罗"); } }
5.String,StringBuffer,StringBuilder 三者的区别与使用场景?
String
:final修饰的,不可变的,每次操作会产生新的对象。
StringBuffer
,StringBuilder
:对原对象进行操作,不产生新对象。
性能上
:StringBuilder (线程不安全)> StringBuffer(线程安全) > String
使用场景
:当需要对字符串内容进行多次改变时,使用StringBuffer,StringBuilder。但因为性能原因优先使用StringBuilder ,需要多线程,共享变量时使用StringBuffer。
6.重载和重写(覆盖)的区别?
重载:发生在类当中,方法名称必须相同,参数的类型,个数顺序不同。方法返回值与修饰符可以不同。(下图:不是重载,方法名称必须相同,参数的类型,个数顺序相同,重载与返回值没有关系)
public void outPrint(String x,int i){ } public int outPrint(String x,int i){ //这个不是重载,编译时会报错 }
重写(覆盖):发生在继承的父类与子类当中,方法名与参数列表必须相同,返回值的范围小于等于父类,如果存在异常,抛出异常范围小于等于父类,修饰符的权限必须大于等于父类。如果父类方法以private修饰则子类不能重写该方法。
7.接口与抽象类的区别?
1,抽象类可以存在普通成员函数,而接口只能存在public abstract 方法,
2,抽象类只能继承一个,而接口可以s实现多个。
3,抽象类中成员变量可以是任何类型,而接口中成员变量只能是public static final 类型的。
(高级:接口设计的目的:是对类行为进行约束,抽象类的目的:提高代码的复用性,抽象类不允许实例化)
使用场景:当你关注的是事务本身时,就用抽象类,当你关注操作时就使用接口。
8.list与set的区别?
list
:有序,可重复的,按对象进入顺序进行存储,允许多个null对象,可以使用迭代器取出所以元素,还可以所以get方法获取指定下标的元素。
set
:无序,不可重复。只允许有一个null对象,只能使用迭代器遍历元素。
9.hashCode与equals
equals
:Object默认采用“==”比较,通常继承后会进行重写比较的为对象的内容(例如String)。
hashCode
:定义在Object中hashCode()会获取哈希码(又称为散列码),确定哈希表表上的索引,并返回int整数。特点“根据键快速找到与之对应的值”
联系与规则:
1,如果二个对象相等,hashCode一定也是相等的
2,如果二个对象相等,二个对象调用equals返回ture。
3,二个对象的hashCode一样,他们不一定相等。
4,equals方法被覆盖,hashCode方法也必须覆盖。
5,hashCode默认行为是堆上的对象独特值,如果没有重写hashCode(),则该类二个对象无论如何都不会相等。
10.ArryList与LinkList的区别?
ArryList:基于动态数组,连续存储,适合下标访问,扩容机制:因为数组长度是固定的,超过固定长度会新建立一个数组,长度扩大原来1.5倍,回收老数组。
LinkList:基于列表,可以存储在分散的内存当中。适合插入,删除,不适合查询。LinkList一般使用迭代器进行遍历。不建议使用for循环遍历,因为每一次遍历都会get方法,消耗性能大,不使用indexOf来返回元素索引,和遍历元素。用indexOf遍历list进行遍历时,当结果为空时还遍历这个列表。
总结
本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注脚本之家的更多内容!