“三刷”牛客网844道Java题目,易错知识点总结,带你清扫Java基础面试障碍

news2024/11/16 20:45:02

目录

前言

1、子类通过哪些办法,可以调用继承自父类的方法?

2、volatile、Lock、transient 哪个关键字不能用来处理线程安全

3、Hashtable 和 HashMap 的区别是?(容易忽略的两点)

4、如何声明了一个适合于创建50个字符串对象数组的变量?

5、什么是强引用、软引用、弱引用、虚引用?

6、异常有哪两种?分别是干什么的?

7、如何实现多态?

8、集合框架图,你忘记了吗?

9、final、finally、finalize三个关键字的区别

10、重写和重载的区别

11、throw 和throws 的区别

12、谈谈你对Java反射的了解

13、常见的垃圾回收算法有哪些?

14、谈谈类加载的过程?

15、访问修饰符

16、双亲委派模型

17、如何解决HashMap冲突问题 

18、排序算法的时间复杂度&空间都复杂度比较

19、接口和抽象类对比

20、super关键字的作用

21、super与this关键字对比

22、servlet的声明周期

23、Java中异常类的描述

​编辑

24、volatile的作用

25、final关键字使用易错点

26、Java中哪种复制数组效率最高?

27、Object中的方法


前言

        讲实在的,刷了三遍牛客网844道Java题,就是为了检测一下Java的基础,没想到第一遍的时候正确率大概30%~40%左右,第二遍的才差不多稳固在90%左右,第三遍的时候可谓是感悟良多啊~ 于是打算写一篇Java基础题目的易错总结,带你清扫Java基础面试障碍;



1、子类通过哪些办法,可以调用继承自父类的方法?

子类构造函数中调用父类构造函数用super;

若想调用父类中被重写的方法,用super;

未被重写的方法可以直接调用。


2、volatile、Lock、transient 哪个关键字不能用来处理线程安全

        volatile关键字语义是禁用缓存,也就是保证读到的是内存中的值,保证内存的可见性,禁止指令重排序,但是他不具备原子性(满足线程安全需要同时具备:原子性,可见性,有序性);

        Lock接口提供了与synchronized关键字类似的同步功能,但需要在使用时手动获取锁和释放锁,因此可以处理线程安全;

        transient关键字  简单地说,就是让某些被修饰的成员属性变量不被序列化,因此不可以处理线程安全;

补充:什么是序列化?就是将java对象转换为字节序列的过程称为对象的序列化;


3、Hashtable 和 HashMap 的区别是?(容易忽略的两点)

        HashMap 是内部基于哈希表实现,该类继承AbstractMap,实现Map接口;

        Properties 类 继承了 Hashtable 类,而 Hashtable 类则继承Dictionary 类;


4、如何声明了一个适合于创建50个字符串对象数组的变量?

        注意:Java声明一个数组时,不能直接限定数组长度,只有在创建实例化对象时,才能对给定数组长度;

String a[];

String[] a;

Object a[];


5、什么是强引用、软引用、弱引用、虚引用?

强引用:

Object obj = new Object(); //只要obj还指向Object对象,Object对象就不会被回收

只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足时,JVM也会直接抛出OutOfMemoryError,不会去回收。

软引用:

        软引用是用来描述一些非必需但仍有用的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。

弱引用:

        弱引用的引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收。        

虚引用:

        虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,它随时可能会被回收


6、异常有哪两种?分别是干什么的?

        java中的异常通常分为编译时异常和运行异常。编译时异常需要我们手动的进行捕捉处理,也就是我们用try....catch块进行捕捉处理。对于运行时异常只有在编译器在编译运行时才会出现,这些不需要我们手动进行处理。


7、如何实现多态?

Java通过方法重写和方法重载实现多态;

方法重写是指子类重写了父类的同名方法;

方法重载是指在同一个类中,方法的名字相同,但是参数列表不同;


8、集合框架图,你忘记了吗?

 


9、final、finally、finalize三个关键字的区别

final:可用来定义变量、方法传入的参数、类、方法。

finally:只能跟在try/catch语句中,并且附带一个语句块,表示最后执行。

finalize:是垃圾回收器操作的运行机制中的一部分,进行垃圾回收器操作时会调用finalize方法;


10、重写和重载的区别

重载:

        在同一个类中,如果多个方法,方法名相同、参数不同,即称为重载。

        在编译器眼里,方法名称+参数类型+参数个数,组成一个唯一键,称为方法签名,JVM通过这个唯一键决定调用哪个重载的方法。

重写:

        方法重写是存在子父类之间的,子类定义的方法与父类中的方法具有相同的名字、参数、返回类型。


11、throw 和throws 的区别

提示:以下可以按照序号顺序对比着看~

throw:

        throw是用来抛出一个具体的异常类型;

        一般出现在函数体;

        throw只能用于抛出一种异常;

throws:

        throw是用来声明一个方法可能产生的所有异常;

        一般出现在函数头;

        throws可以抛出多个异常;

示例如下:

    //throw使用如下
    private void fun1() {
        Scanner in = new Scanner(System.in);
        int ans = in.nextInt();
        if(ans == 0) {
            throw new NumberFormatException("除数不能是0");
        } else {
            int result = 10 / ans;
            System.out.println(result);
        }
    }
    //throws使用如下
    private void fun2(Runnable task) throws InterruptedException {
        BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
        queue.put(task);
    }

12、谈谈你对Java反射的了解

        1.(从定义的角度)反射就是在程序运行期间动态获取对象的属性和方法的功能叫做反射。

        2.(从功能的角度)在程序运行期间,对任意一个类(除了枚举)能够直到他的方法和属性,对于任意一个对象,都能直到他的方法和属性。

        3.(从用法的角度)获取class对象的三种方式:getClass();  xx. class;  Class.forName("xx");

        4.(从优点及缺点的角度回答)优点:运行期间能够动态的获取类,提高代码的灵活性;缺点:性能上相比较直接通过类或对象获取方法和属性,要慢的多

        5.(从应用场景的角度回答)例如模拟 Spring框架、模拟Spring 加载 XML 配置文件、JDBC操作进行数据库连接。
 


13、常见的垃圾回收算法有哪些?

标记清除法:

        过程:将垃圾标记出来,直接清除;

        分析:缺点就是有可能会造成大量的内存碎片,可能导致当需要申请一块足够大的、连续的的内存空间时申请不了,另外,标记,和清除这两步的效率也不是很高;

复制算法:

        过程:将内存分成两块大小相等的空间,只使用其中的一块空间;一轮GC下来,存活的对象将会被复制到另一个未被使用的空间上,而被GC的那部分空间将被全部清除;

        分析:解决内存碎片问题,但是空间利用率上甚至低于标记清除法,并且如果一轮GC下来,存活下来的对象很多,那么复制的开销也是很大的;

标记整理法:

        过程:GC时跟标记清除法一样,先标记出垃圾,然后将存活的对象向内存的一端覆盖,再将存活对象这端边界以外的空间全部清除;

        分析:不仅解决了内存碎片问题,还解决空间利用率问题,但是搬运操作比较耗时;

分代算法:

        过程:将内存区域化成为两大块,分别是:新生代、老年代;在新生代中继续被划分成三大块,分别是:伊甸区、两个生存区;新的对象被创建好会先来到伊甸区,经历一轮GC后存活下来的对象会通过复制算法来到生存区,生存区也会进行GC,每轮GC下来,都会被复制到另一个生存区(存活对象在两个生存区来回复制),GC到达了一定次数后,存活下来的对象就会被分配到老年代;老年代采用标记整理法进行GC,但是相比于新生代,GC的频率要低;特判:如果创建的一个对象比较大,会直接放入老年代,因为既然创建这么大一个对象,没有理由刚创建好,就被一轮GC释放掉;


14、谈谈类加载的过程?

        加载过程主要可以分为三个阶段,细分可以分为五个阶段:加载、连接(验证、准备、解析)、初始化;

加载:

        找到.class文件,读取文件内容,按照.class文件标准内容规范格式进行解析;

连接:

(1)验证:检查当前.class文件格式是否符合规范格式要求;

(2)准备:给静态变量分配内存空间;例如:int a = 10; 这里就会给 a 变量分配4个字节的内存空间,并初始化为0;

(3)解析:初始化常量字符串,将符号引用替换成直接引用;例如:String str = "hello";在类加载之前没有分配内存空间,只是给str一个占位符,表示这里是"hello"这个字符串的位置,类加载之后给"hello"分配了内存空间,就会把这个占位符去掉,换成"hello"的地址;

初始化:

        就是对类进行初始化; 

        初始化顺序:父类(静态变量、静态代码块)–>子类(静态变量、静态代码块)–>父类(变量、代码块)–> 父类构造器–>子类(变量、初始化块)–>子类构造器。


15、访问修饰符

 


16、双亲委派模型

涉及到的类加载器:

1. Bootstrap ClassLoader :负责加载标准库中的类;

2. Extension ClassLoader:负责加载JVM扩展的库的类(标准库中没有,但JVM自己实现出了);

3. Application ClassLoader :负责加载我们自己的项目中的自定义类;
 

工作过程:(下图)


17、如何解决HashMap冲突问题 

解决哈希冲突两种常见的方法是:闭散列(开放定址法)和开散列(链地址法);

闭散列(开放地址法):

        具体做法:当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以 把key存放到冲突位置中的“下一个” 空位置中去;

开散列(链地址法):

        首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子 集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。

例如下图:开散列每一个桶都放的是冲突元素;

 


18、排序算法的时间复杂度&空间都复杂度比较

 


19、接口和抽象类对比

提示:以下可以按照序号顺序对比着看~

接口:

(1)接口是公开的,里面不能有私有的方法或变量;

(2)接口可以实现多重继承;

(3)接口的一定要实现接口里定义的所有方法;

(4)接口中定义的变量只能是public static final类型,并且默认即为public static final类型,方法定义默认为public abstract类型;

(5)接口中不能包含静态方法;

(6)JDK 1.8时,接口中的方法可以是public的,也可以是default的;

抽象类:

(1)抽象类是可以有私有方法或私有变量的;

(2)一个类只能继承一个超类;

(3)实现抽象类可以有选择地重写需要用到的方法;

(4)抽象类中的方法不一定是abstract;

(5)抽象类中可以包含静态方法;

(6)JDK 1.8时,抽象类的方法默认访问权限为default;

总的来说:


        接口体现的是一种规范和实现分离的设计哲学,代码编写过程中充分利用接口可以很大程度的降低程序各个模块之间的耦合,从而提高系统的可扩展性和可维护性。基于这一原则,很多软件架构更提倡面向接口编程而不是实现类编程。(更提倡使用接口,少用抽象类


20、super关键字的作用

(1)用来访问父类被隐藏的非私有成员变量

(2)用来调用父类中被重写的方法

(3)用来调用父类的构造函数

总的来说,super代表父类对应的对象,所以用super访问在子类中无法直接使用的父类成员和方法;


21、super与this关键字对比

提示:以下可以按照序号顺序对比着看~

super():

(1)super()表示调用父类构造函数,在构造函数中必须出现在第一行;

(2)super()指的是对象,所以,不可以在static环境中使用。包括:static变量,static方法,static语句块

this():

(1)this()调用自己的构造函数,在构造函数中必须出现在第一行;

(2)this()指的是对象,所以,不可以在static环境中使用。包括:static变量,static方法,static语句块

综上分析:super()和this()必须在构造函数第一行,所以这一点也表明他俩不能在一个构造函数中;


22、servlet的声明周期

 

总结

初始阶段,实例化的时候,会调用一次init;

每次收到请求,就会调用service,service根据请求中不同的方法,调用不同的doXXX;

结束销毁之前,调用destroy,用来关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动;
 


23、Java中异常类的描述



 

1.Exception(异常) :

        是程序本身可以处理的异常。

2.Error(错误):

        是程序无法处理的错误。这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执应用时,一般不需要程序处理。

3.检查异常(编译器要求必须处置的异常) :

          除了Error,RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。

4.非检查异常(编译器不要求处置的异常):

包括运行时异常(RuntimeException与其子类)和错误(Error)。


24、volatile的作用

(1)禁止了指令重排序;

(2)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量值,这个新值对其他线程是立即可见的;

(3)不保证原子性(线程不安全);

总的来讲:synchronized保证三大性,原子性,有序性,可见性;volatile保证有序性,可见性,不能保证原子性,所以synchronized可以解决线程安全问题,而volatile不可以;


25、final关键字使用易错点

(1)final 定义的方法里,不是必须要用 final 定义方法内的变量。

(2)final 定义的变量,可以在不是必须要在定义的同时完成初始化,也可以在构造方法中完成初始化

(3)final修饰方法,不能被子类重写,但是可以被重载

(4)final 定义变量,可以用 static 也可以不用。


26、Java中哪种复制数组效率最高?

分析:

        在System类源码中给出了arraycopy的方法,是native方法,也就是本地方法,肯定是最快的。而Arrays.copyOf(注意是Arrays类,不是Array)的实现,在源码中是调用System.copyOf的,多了一个步骤,肯定就不是最快的。       

结论: 

效率 :System.arraycopy   >   clone   >   Arrays.copyOf   >   for循环;


27、Object中的方法

1.clone方法

保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。

主要是JAVA里除了8种基本类型传参数是值传递,其他的类对象传参数都是引用传递,我们有时候不希望在方法里讲参数改变,这是就需要在类中复写clone方法。

2.getClass方法

final方法,获得运行时类型。

3.toString方法

该方法用得比较多,一般子类都有覆盖。

4.finalize方法


该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。

5.equals方法

该方法是非常重要的一个方法。一般equals和==是不一样的,但是在Object中两者是一样的。子类一般都要重写这个方法。

6.hashCode方法

该方法用于哈希查找,可以减少在查找中使用equals的次数,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。

一般必须满足obj1.equals(obj2)==true。可以推出obj1.hash- Code()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。

如果不重写hashcode(),在HashSet中添加两个equals的对象,会将两个对象都加入进去。

7.wait方法

wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。

调用该方法后当前线程进入睡眠状态,直到以下事件发生。

(1)其他线程调用了该对象的notify方法。

(2)其他线程调用了该对象的notifyAll方法。

(3)其他线程调用了interrupt中断该线程。

(4)时间间隔到了。

此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。

8.notify方法

该方法唤醒在该对象上等待的某个线程。

9.notifyAll方法

该方法唤醒在该对象上等待的所有线程


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/125894.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

flask框架实现文件下载接口

方式一&#xff1a; app.route("/download1") def download():# return send_file(test.exe, as_attachmentTrue)return send_file(2.jpg)# return send_file(1.mp3)如果不加as_attachment参数&#xff0c;则会向浏览器发送文件&#xff0c;比如发送一张图片&#x…

Revit技巧:快速隔离一个小构件,拉伸屋顶转折处连接

一、Revit中如何快速单独隔离一个小构件 今天跟大家分享的是一个快速隔离的小技巧&#xff0c;你可以理解为快速用剖面框拉成你需要的构件区域。我就举个例子让大家简单容易理解&#xff0c;如图1所示&#xff0c;假设我只需要编辑那个墙的装饰&#xff0c;但又需要用剖面框&am…

704二分查找法--搜索区间

二分查找法–搜索区间的深入理解 二分查找法是算法学习中很基础的算法&#xff0c;但是其也是很重要的算法&#xff0c;将二分查找法搞明白对后续算法的学习有着事半功倍的作用。 本体难点&#xff1a;二分搜索区间的判断 搜索区间 [left,right] int search(vector<int>…

026_SS_MoFusion A Framework for Denoising-Diffusion-based Motion Synthesis

MoFusion: A Framework for Denoising-Diffusion-based Motion Synthesis 本文提出了一种利用diffusion生成人体motion的方法。这种方法可以将音频和文本作为条件。 损失函数 对于diffusion的损失中&#xff0c;加入了运动损失。 其中第一项 LdaL_{da}Lda​ 是原始的diffusio…

微信公众号如何接入ChatGPT机器人

不难&#xff0c;代码总共也就25行&#xff0c;大致逻辑如下。 总共分为是下面两步 文章目录在云服务器上部署自定义消息处理服务微信公众号配置自己的消息处理服务器在云服务器上部署自定义消息处理服务 这里需要我们自定义来处理用户发送过来的消息 首先导入werobot&#x…

Linux操作系统实验2——进程描述

实验要求&#xff1a; 1.查看task_struct的结构&#xff0c;找到其中的pid&#xff0c;state&#xff0c;prio&#xff0c;parent pid字段 2.在task_struct结构中找到vma相关字段&#xff0c;vm_start,vm_end,vm_next 3.打印指定pid的基本信息&#xff0c;包括基本信息及VMA内存…

分组卷积与dw卷积

分组卷积&#xff08;Group Convolution&#xff09; 分组卷积在ResNext中用到了 首先必须明确&#xff1a; 常规卷积&#xff08;Convolution&#xff09;的参数量是&#xff1a; K*K*C_in*n K是卷积核大小&#xff0c;C_in是input的channel数&#xff0c;n是卷积核个数(outp…

共享模型之管程(一)

1.共享带来的问题 1.1.线程安全问题 例如: 两个线程对初始值为0的静态变量一个做自增,一个做自减,各做5000次,结果是0吗? Slf4j public class TestThread {//静态共享变量static int counter 0;public static void main(String[] args) throws InterruptedException {Threa…

【Axure教程】拖动排序——扣款顺序

随着移动支付的发展&#xff0c;移动支付的途径和方式也越来越多&#xff0c;常见的有钱包余额支付、支付宝支付、微信支付、银行卡支付……随着绑定的账户越来越多&#xff0c;我们需要一个设置扣款顺序的功能页面。 所以今天作者就教大家如果做一个拖动排序的扣款顺序的原型…

机器学习的4种经典模型总结

机器学习&#xff08;Machine Learning&#xff09;是人工智能的一个分支&#xff0c;也是人工智能的一种实现方法。机器学习的核心是“使用算法解析数据&#xff0c;从中学习&#xff0c;然后对新数据做出决定或预测”&#xff0c;机器学习的概念就是通过输入海量训练数据对模…

【财务】FMS财务管理系统---质保金与预付款

在FMS财务管理系统中&#xff0c;如何对质保金和预付款进行管理&#xff0c;笔者做了详细的业务流程拆解。 上一篇主要说了财务应收管理&#xff0c;有一些朋友留言提出了很多建议&#xff0c;在这里必须谢谢。 关于应收分为ToC与ToB两部分&#xff0c;每一部分都与前端业务系…

新一代自动出价范式:在线强化学习SORL框架

丨目录&#xff1a; 摘要 动机&#xff1a;在离线不一致问题 问题建模 方法&#xff1a;SORL框架 实验结果 总结 关于我们 参考文献▐ 摘要近年来&#xff0c;自动出价已成为广告主提升投放效果的重要方式&#xff0c;在真实广告系统&#xff08;RAS&#xff09;中&#xff0c;…

C++ 数学与算法系列之高斯消元法求解线性方程组

1. 前言 什么是消元法&#xff1f; 消元法是指将多个方程式组成的方程组中的若干个变量通过有限次地变换&#xff0c;消去方程式中的变量&#xff0c;通过简化方程式&#xff0c;从而获取结果的一种解题方法。 消元法主要有代入消元法、加减消元法、整体消元法、换元消元法、…

【C/C++ SOCKET编程】实现服务器客户端的简单通信

什么是SOCKET Socket又称"套接字"&#xff0c;应用程序通常通过"套接字"向网络发出请求或者应答网络请求&#xff0c;使主机间或者一台计算机上的进程间可以通讯。 TCP/IP协议 从字面意义上讲&#xff0c;有人可能会认为 TCP/IP 是指 TCP 和 IP 两种协议…

Hive环境安装搭建

目录 Hive安装 MySQL安装 配置Hive元数据库到MySQL Hive安装 软件包 0积分免费下载&#xff1a; hive环境安装所需软件包-Hive文档类资源-CSDN下载 将软件包拖进虚拟机中 将jar包解压到目录 给目录文件夹名改为hive 配置环境变量 输入命令&#xff1a; vim /etc/profile …

数据滚动大屏:Stimulsoft Dashboards.WIN 2023.1.2

Stimulsoft Dashboards.WIN 是一组组件&#xff0c;您可以使用这些组件将分析添加到您的应用程序中。WinForms 和 WPF 的仪表板 Stimulsoft Dashboards.WIN 是一个功能齐全的工具&#xff0c;用于在仪表板上转换、分析、分组、过滤、排序和显示数据。它与 .NET Framework 4.5 及…

科创板智能家居第一股,萤石网络昨日上市

2022年12月28日&#xff0c;杭州萤石网络股份有限公司(以下简称“萤石网络”)成功登陆上海证券交易所科创板&#xff0c;证券代码为688475。值得一提的是&#xff0c;萤石网络是登陆科创板的第500家企业。 在上市仪式上&#xff0c;萤石网络董事长、总经理蒋海青表示&#xff0…

医药信息咨询公司排名TOP10是怎么进行收费的?

随着我国医药行业的飞速发展&#xff0c;市场竞争也是越发的激烈&#xff0c;作为产业链中的医药信息咨询公司作用也愈加明显&#xff0c;医药信息咨询公司以提供医药行业的战略咨询、项目尽调、产品立项评估、行业赛道/细分市场机会评估、专利服务、新产品上市服务、新药产品特…

QA | 关于高级硬件在环(HIL)想要了解的十个问题

HiL&#xff08;Hardware-in-the-Loop&#xff09;硬件在环仿真测试系统是采用实时处理器运行仿真模型来模拟受控对象&#xff08;比如&#xff1a;汽车、航空飞机等设备&#xff09;的运行状态&#xff0c;以此判断电控模块的性能。 Q1&#xff1a;什么是HIL&#xff1f; 硬…

分享20个Javascript中的数组方法,收藏

什么是数组&#xff1f;与其他编程语言中的数组一样&#xff0c;Array对象允许在一个变量名称下存储多个项的集合&#xff0c;并且具有用于执行常见数组操作的成员。 声明数组 我们可以用两种不同的方式声明数组。 使用新阵列 使用new Array&#xff0c;我们可以指定希望存在…