java基础面试题 适合→【校招】

本文整理了Java面试中常见的知识点,包括面向对象的特征(封装、继承、多态、抽象)、抽象类与接口的区别、常见数据结构(栈、队列、数组、链表)的特性、向上转型与向下转型的概念以及String与StringBuilder的比较。此外,还介绍了泛型通配符、线程状态及其转换,是Java程序员面试复习的重要参考资料。
摘要由CSDN通过智能技术生成

临近秋招,同学们是不是在准备面试的题呢?这里整理了一点,希望可以帮助到你们。

1. 面向对象的特征有哪些方面:

答:面向对象的特征主要有以下几个方面:
1.封装:

封装是把过程和数据包裹起来,外界对于数据的操作仅限于我们提供的方式。我们可以将生活中各种事物进行抽象封装形成类,也可以通过private修饰符来封装属性与方法,不过需要注意的是,封装后需要手动提供对应被封装资源对外公共的操作方式。

2.继承:

继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。我们可以从现有的类中派生出一个新的类,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。

3.多态性:

多态性是指可以尽量屏蔽不同类的差异性,提供通用的解决方案。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。我们所使用的有:
向上造型【将子类对象统一看作父类型,比如花木兰替父从军】
向下造型【将之前看作父类型的子类对象再重新恢复成子类对象,比如花木兰打仗结束回家化妆】

4.抽象:

抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。
 

2. 抽象类与接口的异同:


抽象类:
抽象方法必须用abstract关键字进行修饰。如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。抽象类可以拥有成员变量和普通的成员方法。

抽象类和普通类的主要有三点区别:
1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public。
2)抽象类不能用来创建对象;
3)如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。

接口:
接口中的变量会被隐式地指定为public static final变量,并且只能是public static final变量,用private修饰会报编译错误,而方法会被隐式地指定为public abstract方法且只能是public abstract方法,用其他关键字,比如private、protected、static、 final等修饰会报编译错误,并且接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法。

抽象类和接口的区别:
语法层面上的区别
1)一个类只能继承一个抽象类,而一个类却可以实现多个接口
2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的
3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法
4)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法
5)抽象类的抽象方法可以是public,protected,default类型,而接口的方法只能是public
设计层面上的区别
1)抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象
所以抽象是重构的结果,接口是设计的结果。
2)设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。

3. 简单说一下常见的数据结构:


1.栈Stack:
又称堆栈,它是运算受限的线性表,其限制是仅允许在标的一端进行插入和删除操作,不允许在其他任何位置进行添加、查找、删除等操作。
我们可以简单理解成:栈结构对元素的存取有如下要求:
先进后出(也就是说,栈中越早存进去的元素,就越在最下面)
例如:子弹压进弹夹,先压进去的子弹在下面,后压进去的子弹在上面,当开枪时,先弹出上面的子弹,然后才能弹出下面的子弹。
所以,栈的入口、出口的都是栈的顶端位置。我们需要知道两个名词:
1)压栈:就是存元素。即,把元素存储到栈的顶端位置,栈中已有元素依次向栈底方向移动一个位置。
2)弹栈:就是取元素。即,把栈的顶端位置元素取出,栈中已有元素依次向栈顶方向移动一个位置。

2.队列queue:
又称队,它同堆栈一样,也是一种运算受限的线性表,其限制是仅允许在表的一端进行插入,而在表的另一端进行删除。
我们可以简单理解成:队列结构对元素的存取有如下要求:
先进先出(也就是说,最先存进去的元素,是可以最先取出的)
例如:我们生活中排队买结账,最先到的人最先付款,最后到的人得等前面的人都付款结束后才能付款。
所以:队列的入口、出口各占一侧

3.数组Array:
是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。就像是一列火车,从1号车厢到最后一节车厢,每节车厢都有自己的固定编号,乘坐火车的人可以通过车厢号快速找到自己的位置。
我们可以简单理解成:数组结构对元素的存取有如下要求:
查找元素快:通过索引,可以快速访问指定位置的元素。
增删元素慢:
我们指定一个索引增加元素,不能修改原数组的长度,而是需要创建一个新长度的数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置。
我们指定一个索引删除元素:不能修改原数组的长度,而是需要创建一个新长度的数组,把原数组元素根据索引复制到新数组对应索引的位置,原数组中指定索引位置元素不复制到新数组中。

4.链表LinkedList:
是一系列节点Node(链表中每一个元素称为节点)组成,节点可以在运行时动态生成。每个节点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个节点地址的指针域。我们常说的链表结构有单向链表与双向链表。
我们这里介绍的是单向链表。
我们可以简单理解成:链表结构对元素的存取有如下要求:
多个节点之间,通过地址进行连接。
例如:自行车的链条,就是通过上一个环连接下一个环,这样就形成一个链条了
查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素
增删元素快:
增加元素:只需要修改连接下个元素的地址即可。
删除元素:只需要修改连接下个元素的地址即可。
 

4. 什么是向上转型?什么是向下转型?


在JAVA中,继承是一个重要的特征,通过extends关键字,子类可以复用父类的功能,如果父类不能满足当前子类的需求,则子类可以重写父类中的方法来加以扩展。
那么在这个过程中就存在着多态的应用。存在着两种转型方式,分别是:向上转型和向下转型。
向上转型:可以把不同的子类对象都当作父类来看,进而屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准。
比如:父类Parent,子类Child
父类的引用指向子类对象:Parent p=new Child();
说明:向上转型时,子类对象当成父类对象,只能调用父类的功能,如果子类重写了父类中声明过的方法,方法体执行的就是子类重过后的功能。但是此时对象是把自己看做是父类类型的,所以其他资源使用的还是父类型的。
比如:花木兰替父从军,大家都把花木兰看做她爸,但是实际从军的是花木兰,而且,花木兰只能做她爸能做的事,在军营里是不可以化妆的。

向下转型(较少):子类的引用的指向子类对象,过程中必须要采取到强制转型。这个是之前向上造型过的子类对象仍然想执行子类的特有功能,所以需要重新恢复成子类对象
Parent p = new Child();//向上转型,此时,p是Parent类型
Child c = (Child)p;//此时,把Parent类型的p转成小类型Child
其实,相当于创建了一个子类对象一样,可以用父类的,也可以用自己的
说明:向下转型时,是为了方便使用子类的特殊方法,也就是说当子类方法做了功能拓展,就可以直接使用子类功能。
比如:花木兰打仗结束,就不需要再看做是她爸了,就可以”对镜贴花黄”了

5. 比较一下String与StringBuilder


String
1. 特点:
创建之后长度内容是不可变的,每次拼接字符串,都会产生新的对象

如果是直接“ ” 或者字符串常量拼接产生的,保存在字符串常量池中
如果是直接通过new方式创建的,保存在堆中
2. 创建方式:
String() String(String s) String(char[] c) String(byte[] b) String s = “abc”;

3. 优缺点:
优点:String类提供了丰富的关于操作字符串的方法,比如:拼接、获取对应下标处的字符、截取子串等等
缺点:在进行字符串拼接+=的时候,效率比较低
4. String转StringBuilder:
String s = “abc”; StringBuilder sb = new StringBuilder(s);

StringBuilder
1. 特点:
StringBuilder是一个长度可变的字符串序列,在创建的时候,会有一个长度为16的默认空间
当拼接字符串的时候,实在原对象的基础之上进行拼接,如果长度不够就扩容
所以StringBuilder在创建之后,对应的操作一直是用一个对象

2. 创建方式:
StringBuilder sb = new StringBuilder();//创建一个长度为16的StringBuilder对象
StringBuilder sb = new StringBuilder(“abc”);//以指定字符串内容为“abc”的方式创建一个StringBuilder对象

3. 优缺点:
优点:在拼接的时候,不会产生新的对象,就避免了因为拼接频繁生成对象的问题,提高了程序的效率
缺点:对于字符串的操作,不太方便,所以在使用的时候,如果拼接操作很多的话:
先将String转为StringBuilder进行拼接,拼接完成之后再转回String
4. StringBuilder转String:
StringBuilder sb = new StringBuilder();
sb.append(“abc”);
String s = sb.toString();

6.什么是泛型通配符?什么是泛型的上下限?


当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。

通配符基本使用
泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符。

通配符高级使用----受限泛型
之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限和下限。
泛型的上限:

格式: 类型名称 <? extends 类 > 对象名称
意义: 只能接收该类型及其子类
泛型的下限:

格式: 类型名称 <? super 类 > 对象名称
意义: 只能接收该类型及其父类型


7. 线程有几种状态?它们是怎么切换的?


线程生命周期,主要有五种状态:

新建状态(New) : 当线程对象创建后就进入了新建状态.如:Thread t = new MyThread();
就绪状态(Runnable):当调用线程对象的start()方法,线程即为进入就绪状态.
处于就绪(可运行)状态的线程,只是说明线程已经做好准备,随时等待CPU调度执行,并不是执行了t.start()此线程立即就会执行
运行状态(Running):当CPU调度了处于就绪状态的线程时,此线程才是真正的执行,即进入到运行状态
就绪状态是进入运行状态的唯一入口,也就是线程想要进入运行状态状态执行,先得处于就绪状态
阻塞状态(Blocked):处于运状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入就绪状态才有机会被CPU选中再次执行.
根据阻塞状态产生的原因不同,阻塞状态又可以细分成三种:
等待阻塞:运行状态中的线程执行wait()方法,本线程进入到等待阻塞状态
同步阻塞:线程在获取synchronized同步锁失败(因为锁被其他线程占用),它会进入同步阻塞状态
其他阻塞:调用线程的sleep()或者join()或发出了I/O请求时,线程会进入到阻塞状态.当sleep()状态超时.join()等待线程终止或者超时或者I/O处理完毕时线程重新转入就绪状态
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期
就绪 → 执行:为就绪线程分配CPU即可变为执行状态"
执行 → 就绪:正在执行的线程由于时间片用完被剥夺CPU暂停执行,就变为就绪状态
执行 → 阻塞:由于发生某事件,使正在执行的线程受阻,无法执行,则由执行变为阻塞
(例如线程正在访问临界资源,而资源正在被其他线程访问)
反之,如果获得了之前需要的资源,则由阻塞变为就绪状态,等待分配CPU再次执行。

更多面试题,请参考以下连接:

参考连接:https://blog.csdn.net/weixin_43884234/article/details/119783697

程序员  加油!冲啊!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值