Java 面试题 基础

记录一下,每天三道题。。。

1.查看自己电脑jdk版本

终端->java -version

2.编程语言分类

分类方式一

编译型:先将高级语言编译成机器语言,运行时直接运行机器语言(如C、C++、swift)

解释型:在运行过程中,先将语言转换成机器语言,再执行机器语言。(php、javascript)

· 在运行过程中,编译型比解释型快

· Java属于编译解释型语言

   xxx.java--xxx.class属于编译型语言

   运行class字节码文件属于解释型语言

分类方式二

面向过程:C

面向对象:Java、C++等

3.Java程序运行过程

编译阶段: Java源程序生成字节码class文件

(xxx.java ->编译器->xxx.class Java编译器针对Java虚拟机产生class文件)

运行阶段:执行Java程序

class loader(加载代码) ->bytecode verifier(校验代码)->runtime interpreter(执行代码)

JVM(Java虚拟机)读取并处理经编译过的与平台无关的class字节码文件

Java解释器负责将Java虚拟机的代码在特定的平台上运行

Java应用程序 -> JVM -> Windows/Linux...

Java语言具有跨平台型,一次编译到处运行

4.JDK和JRE的区别

JDK(Java Development Kit):Java开发工具包,它不仅提供了Java运行时所需要的JRE,还提供了一系列的编译和运行工具,如javac、java等

JRE(Java Runtime Environment):是Java的运行环境,JRE包含了JVM(Java虚拟机),Java核心类库和一些基础构件

5.循环的区别

(1)while循环和for循环结束没有分号,do-while循环结束有分号

(2)如果初始条件未满足,while循环和for循环不会执行循环体,do-while循环至少会执行一次

6.break和continue的区别

break:跳出当前所在循环,不再执行所在循环

continue:跳出本次循环,本次循环后面的代码不执行,执行下一次循环

break可用于循环和switch语句,continue只能在循环语句中使用

7.成员变量和局部变量的区别

成员变量:

(1)成员变量是在类的范围里定义的变量

(2)成员变量有默认初始值

(3)被static修饰的成员变量也可以叫做类变量,存储于方法区,生命周期与当前类一致

(4)未被static修饰的变量也可以叫做实例变量,存储于对象所在的堆内存中,生命周期与对象相同

局部变量:

(1)局部变量是在方法中定义的变量

(2)局部变量没有默认初始值

(3)局部变量存储于栈内存中,作用的范围结束,局部变量空间就会自动释放

8.Java访问权限修饰符的作用域

(1)修饰成员变量/成员方法时

private:该成员可以被该类内部成员访问

default:该成员可以被该类内部成员访问

               也可以被同一包下的其他类访问

protected:该成员可以被该类内部成员访问

                   也可以被同一包下的其他类访问

                   还可以被他的子类访问

public:该类可以被任意包下,任意的类的成员访问

(2)修饰类时(只有public和default两种访问权限)

default:该类可以被同一包下的其他类访问

public:该类可以被任意包下,任意的类访问

9.介绍一下Java的数据类型

Java的数据类型分为基本数据类型和引用数据类型

基本数据类型:

整型:byte,short,int,long

浮点型:float,double

字符型:char

布尔型:boolean

引用类型:

对一个对象的引用,根据引用的对象不同,又可以分为三种:数组、接口、类。

10.final、finally、finalize的区别

final:最终的、不可变的,可以修饰变量、类以及方法。

          修饰变量时,该变量必须被初始化,所以也称之为常量

finally:是异常处理的一部分,只能用在try/catch语句中,finally会附带一个语句块,无论是否抛出

异常,finally语句块中的代码一定会被执行

finalize:是java.lang.Object中的⽅法,也就是每⼀个对象都有这个⽅法,⼀个对象的finalize⽅法

只会调⽤⼀次,调⽤了不⼀定被回收,因为只有对象需要被回收的时候才会被回收,这样就会导致

前⾯调⽤,后⾯回收的时候出现问题,不推荐使⽤

11.static关键字的作用

只有new了对象之后,数据存储空间才会被分配,方法才能供外接调用,但如果没有想要创建的对

象也想要调用某个方法或想要特定分配存储空间时就可以使用static

12.介绍一下ArrayList

ArrayList 底层就是⼀个 Object[] 数组
ArrayList 底层数组默认初始化容量为 10
1、jdk1.8 中 ArrayList 底层先创建⼀个长度为 0 的数组 
2、当第⼀次添加元素(调⽤ add() ⽅法)时,会初始化为⼀个长度为 10 的数组
当 ArrayList 中的容量使⽤完之后,则需要对容量进⾏扩容:
1、ArrayList 容量使⽤完后,会“⾃动”创建容量更⼤的数组,并将原数组中所有元素拷贝过去,这会导致效率降低
2、优化:可以使⽤构造⽅法 ArrayList (int capacity) 或 ensureCapacity(int capacity) 提供⼀个初始化容量,避免刚开始就⼀直扩容,造成效率较低
ArrayList 构造⽅法:
1. ArrayList():创建⼀个初始化容量为 10 的空列表 
2. ArrayList(int initialCapacity):创建⼀个指定初始化容量为 initialCapacity 的空列表
3. ArrayList(Collection<? extends E> c):创建⼀个包含指定集合中所有元素的列表
ArrayList 特点:
优点:
1. 向 ArrayList 末尾添加元素(add() ⽅法)时,效率较⾼ 
2. 查询效率⾼ 
缺点:
1. 扩容会造成效率较低(可以通过指定初始化容量,在⼀定程度上对其进⾏改善) 
2. 另外数组⽆法存储⼤数据量(因为很难找到⼀块很⼤的连续的内存空间)
3. 向 ArrayList 中间添加元素(add(int index)),需要移动元素,效率较低 
    但是,向 ArrayList 中国位置增/删元素的情况较少时不影响; 
    如果增/删操作较多,可考虑改⽤链表

13.代码执行顺序

父静态 -> 子静态 -> 父自由 -> 父构造 -> 子自由->子构造

14.String、StringBuffer、StringBuilder的区别

String:

(1)String是被final修饰的类,不能被继承;

(2)String实现了Serializable和Comparable接口,表示String支持序列化和可以比较大小;

(3)String底层是通过char类型的数据实现的,并且被final修饰,所以字符串的值创建之后就不可

以被修改,具有不可变性

面试题:String、StringBuffer和StringBuilder的异同?

相同点:底层都是通过char数组实现的


不同点:
String对象一旦创建,其值是不能修改的,如果要修改,会重新开辟内存空间来存储修改之后的对象;而StringBuffer和StringBuilder对象的值是可以被修改的;

StringBuilderStringBuffer通过使用可变的字符序列,避免了频繁的对象创建和内存分配,提高了字符串拼接的效率。
StringBuffer几乎所有的方法都使用synchronized实现了同步,线程比较安全,在多线程系统中可以保证数据同步,但是效率比较低;而StringBuilder 没有实现同步,线程不安全,在多线程系统中不能使用 StringBuilder,但是效率比较高。
如果我们在实际开发过程中需要对字符串进行频繁的修改,不要使用String,否则会造成内存空间的浪费;当需要考虑线程安全的场景下使用 StringBuffer,如果不需要考虑线程安全,追求效率的场景下可以使用 StringBuilder。


原文链接:https://blog.csdn.net/Mr_wxc/article/details/107296135

15.hashCode和equals

hashCode()和equals()都是Object类的方法,hashCode()默认是通过地址来计算hash码,但是可能被重写过的内容来计算hash码,equals()默认通过地址判断两个对象是否相等,但是可能被重写内容来比较两个对象

所以两个对象相等,他们的hashCode和equals一定相等,但是hashCode相等的两个对象未必相等

如果重写equals()必须重写hashCode(),比如在HashMap中,key如果是String类型,String如果只重写了equals()而没有重写hashcode()的话,则两个equals()比较为true的key,因为hashcode不同导致两个key没有出现在一个索引上,就会出现map中存在两个相同的key

原文链接:https://blog.csdn.net/w20001118/article/details/125724647

16.深拷贝和浅拷贝的区别

浅拷贝:浅拷贝只复制某个对象的引用,而不复制对象本身,新旧对象还是共享同一块内存
深拷贝:深拷贝会创造一个一模一样的对象,新对象和原对象不共享内存,修改新对象不会改变原对对象。

原文链接:https://blog.csdn.net/w20001118/article/details/125724647

17.什么是自动拆装箱,int和Integer有什么区别

基本数据类型,如int,float,double,boolean,char,byte,不具备对象的特征,不能调用方法。

装箱:将基本类型转换成包装类对象
拆箱:将包装类对象转换成基本类型的值

java为什么要引入自动装箱和拆箱的功能?主要是用于java集合中,List<Inteter> list=new ArrayList<Integer>();

list集合如果要放整数的话,只能放对象,不能放基本类型,因此需要将整数自动装箱成对象。

实现原理:底层是通过Integer.valueOf()和Integer.intValue()方法实现。

区别:

Integer是int的包装类,int则是java的一种基本数据类型
Integer变量必须实例化后才能使用,而int变量不需要
Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
Integer的默认值是null,int的默认值是0


原文链接:https://blog.csdn.net/leader_song/article/details/132094080

18.Java中有几种类型的流

原文链接:https://blog.csdn.net/leader_song/article/details/132094080

19.线程的状态

新建状态(New) :线程对象被创建后,就进入了新建状态。例如,Thread thread = new Thread()。


就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。


运行状态(Running):线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。


阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:


等待阻塞 -- 通过调用线程的wait()方法,让线程等待某工作的完成。


同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。


其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。


死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。


原文链接:https://blog.csdn.net/leader_song/article/details/132094080

20.怎么反转字符串

使用StringBuffer的reverse()方法

package r.tset;

/**
 * Date:2023/11/23
 * Author:Jo
 * Description:反转字符串
 */
public class Test {
    public static void main(String[] args) {

        String str = "hello world!";

        StringBuffer stringBuffer = new StringBuffer(str);

        System.out.println(stringBuffer.reverse());

    }
}

运行结果:

21.常见的异常

NullPointerException(空指针异常)

ClassCastException(类型转换异常)

ArrayIndexOutOfBoundsException(数组越界异常)

IllegalArgumentException(非法参数异常):当传递给方法的参数不符合方法的要求或范围时抛出。

FileNotFoundException(文件未找到异常)

IOException(输入/输出异常)

ArithmeticException(算数异常):当出现除以零或其他算术错误时抛出。

NumberFormatException(数字格式异常):当字符串无法转换为数字时抛出。

InterruptedException(中断异常):当一个线程在等待、睡眠或被阻塞时被中断时抛出。

22.Collection和Collections的区别

(1)Collection是最基本的集合接口,Collection派生了两个子接口list和set,分别定义了两种不同的存储方式。

(2)Collections:是Java提供的一个实用类,它包含了一系列静态方法,用于对集合进行操作和算法。这些方法包括对集合进行排序、查找、替换、填充等。Collections类中的方法都是静态的,可以直接通过类名调用。

简而言之,Collection是一个接口,定义了集合的基本操作,而Collections是一个实用类,提供了对集合进行操作的静态方法。

23.throw和throws的区别

throw:作用在方法内,表示抛出异常的具体内容,由方法内的语句处理

throw语句执行时一定发生了异常

throw new 异常类名称(构造函数参数);

throws:作用在方法声明上,表示抛出异常,由调用者来进行异常处理

可能出现异常,但不一定会发生异常

访问权限修饰符 返回类型 方法名(参数列表) throws 异常列表 {
    // 方法体
}

24.Java中,为什么不允许从静态方法中访问非静态变量

(1)静态变量也叫做类变量,在类加载时就会分配内存,可以通过类名直接访问静态变量

(2)非静态变量属于类的对象,只有在类的对象产生时,才会分配内存,

        需要通过类的实例去访问

(3)静态方法也叫做类方法,类加载时没有产生类的实例,内存中没有非静态变量,所以无法调用。如果允许从静态方法中直接访问非静态变量,就会导致混淆和不确定性,因为无法确定要访问的是哪个对象的变量。

25.接口和抽象类的区别

接口 

定义关键字:interface

抽象类

声明关键字:abstract class

共同点

接口和抽象类都不能实例化对象

区别

(1)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的

(2)一个类只能继承一个抽象类,一个类可以实现多个接口

(3)抽象类中可以没有抽象方法,但如果一个类中有抽象方法,那么这个类一定是抽象类

(4)接口中不可以有静态方法和静态代码块,抽象类中可以有静态方法和静态代码块

26.重写和重载的区别

重载:

1)在一个类里,参数名必须相同,参数列表 (参数个数,参数类型,参数顺序)必须不同。访问权限修饰符,返回值类型随意。

2)当有多个重载方 法时,调用方法根据参数个数、参数类型自动匹配方 法,如果匹配成功直接调用,匹配不成功,找能够自 动转换成对应的方法进行调用。


重写:

父类不能满足子类特殊需求,在子类中重新定义方法,叫做重写,规则如下

1)访问权限修饰符不能比父类严格。

2)返回值类型,方法名,参数列表必须一致 3)子类抛出的异常不能比父类多

27.谈谈对反射的理解

一、Java反射机制是什么?
1、Java反射机制(Java Reflection)是Java语言中一种动态(运行时)访问、检测 & 修改它本身的能力,主要作用是动态(运行时)获取类的完整结构信息 & 调用对象的方法~
更简单点的说就是Java程序在运行时(动态)通过创建一个类的反射对象,再对类进行相关操作,比如:

获取该对象的成员变量 & 赋值
调用该对象的方法(含构造方法,有参/无参)
判断该对象所属的类
2、更通俗点的说,我们使用某个类,都会知道这个类,以及要用它来做什么,可以直接通过new实例化创建对象,然后使用这个对象对类进行操作,这个就属于正射~

3、而反射则是一开始并不知道要初始化的是什么类,无法使用new来实例化创建对象,主要是通过JDK提供的反射API来实现,在运行时才知道要操作的是什么类,并且可以获取到类的完整构造以及调用对应的方法,这就是反射~

二、Java反射机制中获取Class的三种方式及区别?
1、获取类的java.lang.Class实例对象,常见的三种方式分别为:

通过MyClass.class获取
通过Class.forName("类的全局定名")获取
通过new MyClass().getClass()获取
2、通过MyClass.class获取,JVM会使用ClassLoader类加载器将类加载到内存中,但并不会做任何类的初始化工作,返回java.lang.Class对象

3、通过Class.forName("类的全局定名")获取,同样,类会被JVM加载到内存中,并且会进行类的静态初始化工作,返回java.lang.Class对象

4、通过new MyClass().getClass()获取,这种方式使用了new进行实例化操作,因此== 静态初始化和非静态初始化工作都会进行 == ,getClass方法属于顶级Object类中的方法,任何子类对象都可以调用,哪个子类调用,就返回那个子类的java.lang.Class对象

5、这3种方式,最终在JVM堆区对应类的java.lang.Class对象都属于同一个,也就是内存地址相同,进行==双等号比较结果为true,原因是JVM类加载过程中使用的是同一个ClassLoader类加载器加载某个类,不论加载多少次,生成到堆区的java.lang.Class对象始终只有一个,除非自定义类加载器,破坏JVM的双亲委派机制,使得同一个类被不同类加载器加载,JVM才会把它当做两个不同的java.lang.Class对象

三、Java反射机制的应用场景有哪些?

工厂模式中的简单工厂模式优化
代理模式中的动态代理方式实现
Java JDBC数据库操作

原文链接:https://blog.csdn.net/JustinQin/article/details/119850304

28.什么是序列化,什么情况下需要序列化

29.get和post的区别

(1)参数传递

        get请求的数据会附在URL之后,把数据放置在http协议头,以?分割URL和传输数据,参数

之间用&连接。示例:http://example.com/resource?param1=value1&param2=value2

        post请求会把提交的数据放置在http包的包体中。

(2)数据长度

        get请求由于参数附在URL中,数据长度受到浏览器和服务器的限制。通常用于获取信息

        post请求可以发送大量数据,理论上没有数据长度限制。通常用户提交表单数据或上传文件。

(3)安全性

        get请求由于参数暴露在URL中,相对不安全,适用于非敏感数据

        post请求参数不可见,对用户来说更安全

(4)缓存

        get请求可以被浏览器缓存,因为get请求是幂等的,重复请求不会产生副作用

        post请求不能被浏览器缓存,因为post请求可能会对服务器状态产生影响,重复请求可能会导

致不同的结果

幂等性:http://t.csdnimg.cn/u1YYA

30.字符串和数组转换

package jo.test;

/**
 * Date:2023/11/26
 * Author:Jo
 * Description:字符串和数组转换
 */
public class StrChange {

    public static void main(String[] args) {

        String str = "Hello, World!";

        // 使用默认字符集转换字符串为字节数组
        byte[] byteArray = str.getBytes();

        // 使用指定字符集转换字符串为字节数组
        // 使用UTF-8字符集
        // byte[] byteArray = str.getBytes(StandardCharsets.UTF_8);

        // 打印字节数组内容
        for (byte b : byteArray) {
            System.out.print(b + " ");
        }

        System.out.println();

        //字节数组转换成字符串
        String string = new String(byteArray);
        //打印字符串
        System.out.println(string);
    }
}

31.GC垃圾回收机制

(1)负责回收无用的内存。负责自动回收那些无用对 象所占用的内存。

(2)一个对象创建后被放置在JVM的堆内存中,只有 当对象不再被程序中的任何引用变量引用时,它的内 存才可能被回收

(3)系统自动运行,程序员不能干预

(4) finalize()方法,该方法有可能使对象复活,导致垃圾 回收器取消回收该对象的内存。定义在Object类,执 行finalize()方法时,如果出现异常,垃圾回收器不会 报告异常,程序继续正常运行。

(5)低优先级系统级守护线程独立运行, 在jvm空闲 时,回收释放无用内存。

(6)程序中可调用System.gc()或Runtime.gc()方法提示 垃圾回收器尽快执行垃圾回收操作

(7)有效防范动态内存分配中可能发生的两个危险:因 内存垃圾过多而引发的内存耗尽,以及不恰当的内存 释放所造成的内存非法引用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值