Java面试题总结(一)--java基础

一.static和final的用法

1.static

  • 修饰变量:被修饰的变量称为静态变量或类变量,它属于类而不是实例,所有实例共享同一个静态变量。
  • 修饰方法:被修饰的方法称为静态方法,它属于类而不是实例,直接通过类名调用,无需创建对象
  • 修饰代码块: 被修饰的代码块称为静态代码块,它在类加载时执行,且只执行一次

自我理解:被修饰的变量和方法在运行时,存储在方法区和静态区,是程序运行时被分配的一块内存空间。实例是指类创建的具体对象,无论有多少的对象,静态变量只有一份,当一个实例修改了变量,其他实例也会受到影响。生命周期同类生命周期一致,类加载时初始化,程序结束或类被卸载时销毁。

2.final

  • 修饰类:不能被继承
  • 修饰方法:不能被子类重写
  • 修饰变量:一旦赋值后不可改变

使用 staticfinal 的一些常见场景包括:

  • 使用static可以创建工具类,其中方法直接通过类名调用
  • 使用final可以定义常量,保证其值不被修改
  • 使用static final可以定义全局变量

二.抽象类与接口的区别

1.定义方式:

  • 抽象类使用abstract关键字定义,可以包含抽象方法和具体方法,也可以包含成员变量;
  • 接口使用interface关键字定义只能包含抽象方法和常量,不能包含成员变量
  • 注:在Java8之后,接口中增加一些新特性:默认方法,静态方法,私有方法
  • 自我理解: 增加新特性后最大的便利在于接口中定义的方法,不在只是抽象方法了,不是必须重写,对开发者来说,在对接口修改时,其实现类无需修改,更加灵活。

2.继承关系:

  • 一个类只能继承一个抽象类,但可以实现多个接口,抽象类通过继承来实现代码的复用,而接口通过实现来实现代码的复用。

3.实现方式:

  • 子类继承抽象类时需要使用extends关键字;实现接口时,需要使用implements关键字

4.设计目的:

  • 抽象类主要表示类的共性,它是一种模板用于派生具体子类;接口用于定义一组相关的操作,类似于功能的作用

三.类有哪些基本特性?优点是什么?(或者面向对象的三大特性)

具有封装性,继承性,多态性

  • 封装性:类的封装性为类的成员提供共有、缺省、私有、保护等访问权限,目的是隐藏类中的私有变量和类中方法的实现细节
  • 继承性;允许通过继承原有类的某些特性或全部特性而产生全新的类,原有的类成为父类,新创建的类成为子类,子类可以继承父类的共性,也可以创建出它特有的个性。
  • 多态性:是指在父类中定义的属性和方法被子类继承之后,可以具有不同的数据类型和表现出来不同的行为,表现形式:重载和重写

四.重载和重写的区别

  • 重载:指在同一类中定义多个方法名相同的方法,参数类型和个数不同,返回值必须相同
  • 重写:指在子类中重新定义父类中的方法,方法名、参数列表和返回类型必须相同
  • 自我理解:重载在同一个类中,重写在父子类中,重载同名方法,不同参数,同返回值,重写子类需要与父类中的定义的方法---"全部相同"。

五.Error和Exception有什么区别?

共同点:

  • 都是Throwable的子类

区别:

  • Error:为系统错误,不可恢复,例如:内存溢出,栈溢出等
  • Exception: 程序中的异常,通常为逻辑错误,外部环境等原因引起,分为以下两种类型:
  • 检查异常: 必须处理或者捕获,在方法的声明中使用throws关键字声明或使用try-catch语句进行捕获和处理。例如,IOException、SQLException等都是受检异常
  • 非检查异常:通常由程序逻辑错误引起,可以选择捕获和处理,也可以不处理,例如NullPointerException、ArrayIndexOutOfBoundsException等。
  • 自我理解:Error不能恢复的系统异常,Exception中,非检查异常由于代码逻辑和代码编辑错误,及大意引起开的程序异常,这些错误是不应该发生的,应尽量避免。检查异常,编写某些代码需要必须处理的异常,可以交给异常处理器统一处理。在编写一些业务上的逻辑问题时,我们也可以去主动捕获异常,如文本格式要求,获取参数的格式要求等,不符合业务要求我们可以统一交给异常处理器,返回给前端进行显示,提醒用户重新编辑。

六.Java会存在内存泄漏吗?

会的,内存泄漏指程序中的内存被分配后,无法回收和释放,导致内存不断增加,最终可能导致内存耗尽。

什么情况下,会出现内存泄漏:

  • 对象引用为及时释放:例如,长时间持有对象引用的静态变量、集合中的对象引用未及时移除等情况都可能导致内存泄露
  • 资源未被正确释放:例如,忘记关闭文件流、数据库连接等情况都可能导致内存泄露。
  • 循环引用:例如,两个对象相互引用,但没有其他对象引用它们,就会导致内存泄露。

七.多线程有几种实现方法,都是什么?同步有几种实现方法都是什么?

多线程的实现方法有三种:

1. 继承Thread类:创建一个继承自Thread类的子类,并重写run()方法来定义线程的执行逻辑。然后通过创建子类的实例并调用start()方法来启动线程。

2. 实现Runnable接口:创建一个实现了Runnable接口的类,并实现其run()方法来定义线程的执行逻辑。然后通过创建该类的实例,并将其作为参数传递给Thread类的构造方法来创建线程对象,最后调用线程对象的start()方法来启动线程。

3. 使用线程池:通过使用Java提供的Executor框架,可以创建一个线程池来管理线程的执行。可以使用ThreadPoolExecutor类来创建线程池,并通过submit()方法提交任务给线程池执行。

同步的实现方法有四种:

1. synchronized关键字:使用synchronized关键字可以修饰方法或代码块,实现对共享资源的同步访问。当一个线程获取到对象的锁时,其他线程将被阻塞,直到该线程释放锁。

2. ReentrantLock类:ReentrantLock是Java提供的一个可重入锁,通过lock()方法获取锁,通过unlock()方法释放锁。与synchronized关键字相比,ReentrantLock提供了更多的灵活性和功能,例如可中断锁、公平锁等。

3. ReadWriteLock接口:ReadWriteLock是Java提供的一个读写锁接口,通过它可以实现对共享资源的读写操作的并发访问。它提供了读锁和写锁两种锁的机制,读锁可以被多个线程同时获取,写锁只能被一个线程获取。

4. AtomicInteger类:AtomicInteger是Java提供的一个原子操作类,它可以实现对整型变量的原子操作。通过使用AtomicInteger可以避免多线程环境下的竞态条件和数据不一致的问题。

八.sleep()和wait()的区别

  • 功能:

sleep()函数用于暂停当前线程的执行一段时间

wait()函数用于等待子线程结束

  • 使用场景:

sleep()函数通常用于在程序中添加延迟或等待一段时间后执行某些操作

wait()函数通常在父线程中使用,用于等待子线程完成执行后在继续执行父进程的代码

  • 阻塞:

sleep()函数会阻塞当前线程的执行,即暂停当前线程的运行,但不会影响其他线程的执行

wait()函数会阻塞当前线程的执行,即暂停当前进程的运行,直到指定的子线程结束

  • 返回值

sleep()函数没有返回值

wait()函数会返回子线程的退出状态

  • 如果返回值大于0,表示返回的是子进程的PID,子进程已经退出。
  • 如果返回值等于0,表示返回的是子进程的PID,子进程正在运行。
  • 如果返回值小于0,表示发生了错误,返回的是一个负数,表示等待子进程的过程中出现了错误。
  • 参数

sleep()函数接受一个参数,表示暂停的时间长度(单位为秒)

wait()函数可以通过参数来指定等待的子进程

九.Java跨平台原理

java源程序(.java文件)通过编译器编译成为Class文件(字节码文件),而它的class文件是基于字节码(以byte为单位存储的文件),而字节码文件描述的是程序要运行的虚指令(可以理解为一种机器指令)的集合,这种虚指令于平台无关,java虚拟机可以识别它(不同安装响应的jre,运行jvm,就可以)

十.有了基本类型,为什么还需要需要包装类型

Java是一种面向对象的编程语言,基本类型并不具备对象的特征,为了让基本类型就有对象的特征,就出现了包装类。它相当于将基本类型包装起来,使得它具有了对象的特性。另外当使用ArrayList,HashMap中放东西时,因为容器都是装的Object的,这时候就需要包装类型了。

十一."=="和"equals"的区别

  • ==比较两个对象的内存地址值,相同返回true,不同false
  • equals默认情况下时于==一样的,但是重写了equals()方法后,通常比较的内容是否相同

十二.讲一下java中的集合 

集合(Collection)是一种存储和操作一组对象的容器,Java提供了多种集合类,每个集合类都有不同的特点和用途。

1.List(列表):可以包含重复元素

  • ArrayList:基于数组实现的动态数组,支持随机访问和快速插入/删除元素
  • LinkedList: 基于链表实现的双向链表,支持快速插入/删除元素,但访问元素需要遍历链表
  • Vector:与ArrayList类似,但是是线程安全的,支持同步访问 

2.Set(集):是无序的集合,不允许包含重复的元素。

  • HashSet: 基于哈希表实现的集合,不保证元素的顺序,查找速度快
  • LInkedHashSet: 基于Hash表和链表实现的集合,按照插入顺序维护元素的顺序
  • TreeSet: 基于红黑树实现的集合,按照元素的自然顺序或者指定的比较器进行排序

3.Map(映射):是一种键值对的集合,每一个建只能对应一个值

  • HashMap: 基于哈希表实现的映射,不保证键值对的顺序,查找速度快
  • LinkedHashMap: 基于哈希表和链表实现的映射,按照插入顺序维护键值对的顺序
  • TreeMap: 基于红黑树实现的Map,按照键的自然顺序或者指定的比较器进行排序

十三.String、StringBuffer、StringBuilder的区别? 

  1. 运行速度:StringBuild>StringBuffer>String
  2. 不可变性:String是不可变的,每回创建或修改,都会创建一个新的对象。StringBuild和StingBuffer是可变的,对其修改不会创建新的对象。
  3. 线程安全:StringBuilder是线程不安全的,而StringBuffer是线程安全的。
  • String:适用于少量的字符串操作的情况
  • StringBuilder: 适用于单线程下在字符缓冲区进行大量操作的情况
  • StringBuffer: 适用于线程下在字符缓冲区进行大量操作的情况

十四. 静态变量和实例变量的区别?

  1. 存储位置:静态变量存储在静态存储区,实例变量存储在堆内存中的对象中
  2. 内存分配:静态变量在程序启动的时候就会分配内存,在程序的整个运行期间都存在。实例变量在创建对象的时候才会分配内存,每个对象都有自己的实例变量
  3. 生命周期:静态变量的生命周期同程序的生命周期相同,而实例变量的生命周期与对象的生命周期相同
  4. 访问方式:静态变量通过类名直接访问,也可以通过对象引用访问。实例变量只能通过对象引用访问。
  5. 初始化时机:静态变量在类加载的时候被初始化,实例变量在创建对象的时候初始化。

十五.同步异步区别,什么情况下使用?

  1. 同步:指任务顺序执行,每个任务执行完在执行下一个任务。在同步执行中,任务之间是相互依赖的,后面的任务必须等前面的任务执行完毕才能执行,同步执行简单直观,可能导致程序执行效率低。
  2. 异步:指任务的执行不按顺序执行,每个任务在执行过程中可以同时执行其他任务,任务之间是相互独立的,不需要等待其他任务的完成。可以提高程序的执行效率。

执行时间较短的任务可以选择同步执行;较快的可以选择异步执行;并发性要求较高的任务选择异步执行,提高并发和响应;任务之间存在依赖关系的可以选择同步执行。

十六.Java中有几种类型的流?

  1. 字节流:字节流以字节为单位进行读取和写入数据。设用于处理二进制数据或字节流形式的文本。主要由:InputStream和OutputStream及其子类组成。InputStream:用于从输入源读取字节数据的抽象类。OutputStream:用于向输出目标写入字节数据的抽象类。
  2. 字符流(Character Stream):字符流以字符为单位进行读取和写入数据。它们适用于处理文本数据,可以自动处理字符编码和解码。在Java中,字符流主要由Reader和Writer类及其子类组成。Reader:用于从输入源读取字符数据的抽象类。Writer:用于向输出目标写入字符数据的抽象类。

十七.数组中没有有length()这个方法?String有没有length()这个方法?

数组中没有length()方法,但是数组中有length这个属性。用来标识数组的长度。String中有这个方法用来得到字符串的长度。

十八.super与this的区别

  1. super关键字:

    • super用于在子类中访问和调用父类的成员(属性和方法)。
    • 可以使用super关键字来调用父类的构造函数,以便在子类中初始化父类的属性。
    • 在子类中,可以使用super关键字来调用父类的方法,以便在子类中扩展或重写父类的方法。
  2. this关键字:

    • this用于在类的内部访问和引用当前对象的成员(属性和方法)。
    • this关键字可以用于访问当前对象的属性和方法,以及调用当前对象的构造函数。
    • 在类的方法中,可以使用this关键字来引用当前对象,以便在方法内部访问和操作当前对象的成员。

十九.子类继承父类,子类和父类中都有静态常量,静态代码块,构造方法,那么执行顺序是怎么样的?

  • 执行顺序如下:
  1. 首先,父类的静态代码块会在子类加载之前执行
  2. 接下来子类静态代码块会在子类加载时执行
  3. 父类的静态常量会在父类的静态代码块之后进行初始化
  4. 父类的构造方法会在子类的构造方法之前执行
  5. 子类的静态常量会在子类的静态代码块之后进行初始化
  6. 子类的构造方法会执行
  • 总结:父类的静态代码块→子类的静态代码块→父类的静态常量→父类的构造方法→子类的静态常量→子类的构造方法

二十.Java中的类加载器?

建议二十和二十一一起看!!!

  1. 启动类加载器(Bootstrap Class Loader):它是JVM的一部分,负责加载java的核心类库,如java.long包中的类,它是最顶级的类加载器,由C++实现。
  2. 扩展类加载器(Extension Class Loader):它是由sun.misc.Launcher$ExtClassLoader实现的,负责加载Java的扩展类库,如javax包中的类。它是由Java编写的类加载器。
  3. 应用程序类加载器(Application Class Loader):它是由sun.misc.Launcher$AppClassLoader实现的,负责加载应用程序的类。它是Java中默认的类加载器,也是大多数开发者使用的类加载器。

二十一.双亲委派

 好处:

  • 主要为为了安全性,避免用户自己编写的类动态替换java中的一些核心类,
  • 同时避免类的重复加载,因为JVM区分不同的类。不仅仅是根据类名,相同的class文件被不同的ClassLoader加载就是不同的两个类

二十二.转发和重定向的区别?

  1. 转发(Forward):转发是指在服务器内部将请求从一个资源(如Servlet、JSP)传递给另一个资源进行处理。在转发过程中,客户端浏览器并不知道服务器内部的转发操作,它只知道最终响应的资源。转发是通过请求的转发器(RequestDispatcher)实现的。

    特点:

    • 转发是服务器内部的操作,客户端浏览器并不知道转发的过程。
    • 转发是在同一个请求中完成的,浏览器地址栏不会改变。
    • 转发可以共享请求的属性和参数。
    • 转发可以将请求转发给同一个Web应用程序中的其他资源。

    使用场景:

    • 在同一个Web应用程序中的不同资源之间进行数据共享和处理。
    • 实现MVC架构中的控制器转发请求给视图进行渲染。
  2. 重定向(Redirect):重定向是指服务器返回一个特殊的响应给客户端浏览器,告诉它重新发送一个新的请求到指定的URL。客户端浏览器会根据重定向响应的URL重新发送请求。重定向是通过设置响应的状态码和Location头实现的。

    特点:

    • 重定向是通过向客户端浏览器发送特殊的响应来实现的。
    • 重定向会导致浏览器地址栏的URL发生改变。
    • 重定向不共享请求的属性和参数。
    • 重定向可以将请求重定向到任意URL,包括其他Web应用程序。

    使用场景:

    • 在不同的Web应用程序之间进行页面跳转。
    • 处理表单提交后的重定向,避免表单的重复提交。

总结: 转发和重定向都是用于实现请求的转发或跳转,但它们的实现方式和特点有所不同。转发是服务器内部的操作,不会改变浏览器地址栏的URL,可以共享请求的属性和参数;而重定向是通过向客户端浏览器发送特殊的响应来实现的,会改变浏览器地址栏的URL,不共享请求的属性和参数。

类比下:

转发:张三(客户端)去找李四(服务器)借钱,李四没有钱,去找了王五借钱,借到钱后借给了张三,这个过程中张三是不知道李四去借钱的。

重定向:张三(客户端)去找李四(服务器)借钱,李四告诉张三我没钱,去找王五借钱吧,张三就去找王五借钱了。

二十三.Integer a1 = 100; Integer a2 = 100; a1 == a2 结果是什么,并解释?

true,因为在Integer中包含一个享元模式,会存储一个[-128,127]的缓存,当a1=100,a2=100这量条命令时触发装箱,会取缓存,最终指向的是同一个内存地址,结果为true。但是假如a2=200的话,不在缓存的取值范围内,就会创建一个新的对象,a1和a2在进行==对比时地址值就不相同了,结果为false。

待更新

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值