java基础面试题

过年期间刷刷面试题目,虽说都已经在公司做了两年开发,但是总共就经手过一个项目。还是只会些基础,坑的很的是虽然工作是后端开发,但是在工作当中遇到大部分的问题都是来自于前端页面。下面这些面试题,如果问起来,也是有的会很懵,不知道怎么回答。

1.字符型常量和字符串常量的区别
  • 字符型常量是单个引号引起的字符,字符串常量是双引号引起的若干个字符
  • 字符串常量相当于一个整型值, 可以参加表达式运算, 字符串常量代表的是一个地址值
  • 字符串常量只占两个字节
2. 重载和重写的区别
  • 重载是同一个方法根据输入的参数的不同,做出不同的处理
  • 重写是子类继承父类的相同的方法, 输入的数据不一样,但要做出和父类不同的响应时, 你就要覆盖父类方法
  • 重载就是同一个类中多个同名方法根据不同的传参来执行不同的逻辑
  • 重写发生在运行期,是子类对父类允许访问的方法的实现过程进行重新编写
  • 返回值类型,方法,参数列表必须相同,抛出的异常范围小于等于父类, 访问修饰符范围大于父类
  • 如果父类方法的访问修饰符为 private /final/static 则子类就不能重写该方法, 但是被static 修饰的方法能够再次被声明。
  • 构造方法无法被重写
  • 重写就是子类对父类方法的重新改造,外部样子不能改变,内部逻辑可以改变
3. 封装

把属性私有化,同时提供给外界访问的方法。

4. 继承

子类复用父类

  • 子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和私有方法子类是无法访问的,只是拥有
  • 子类可以拥有自己的属性和方法,既子类可以对父类进行扩展。
  • 子类可以用自己的方式实现父类的方法。
5. 多态
6. StringBuffer和StringBuilder的区别是什么? String 为什么是不可变的?
  • String 类中使用final 关键字来修饰的字符串数组来保存字符串
    private final char value[],所以String 是不变的
    java9 以后使用byte数组来保存字符串
  • StringBuffer和StringBuilder 都是继承AbstractStringBuilder, AbstractStringBuilder使用字符串数组保存字符串,没有用final 关键字修改,所以String 是可变的
  • 线程安全性
    String 可以理解为常量,不可变,所以是线程安全的,StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以也是线程安全的。StringBuilder并没有对方法添加同步锁,所以不是线程安全的。
  • 性能
    String 是不可变的,每次对String 进行修改时,都会生成一个新的String 对象。然后将指针指向新的对象。StringBuffer每次操作都会修改StringBuffer 对象本身,而不是生成新的对象并改变对象引用。
7. 自动装箱与拆箱
  • 装箱: 将基本类型用他们对应的引用类型包装起来。
  • 拆箱: 将包装类型转换为基本类型。
8. 在一个静态方法内调用一个非静态方法为什么是错误的
  • 由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量, 也不可以访问非静态成员。
9. 在java 中定义一个不做事且没有参数的构造方法有什么作用
  • java 程序在执行子类的构造方法前,如果没有用super() 来调用父类特定的构造方法,则会默认调用“父类无参的构造方法"。如果父类中没有无参的构造方法,编译器会报错.
10. import java 和 javax 有什么区别
  • 最开始javaAPI 所必须的包是java 包,javax 只是当作扩展包使用,但是随着时间的推移,javax 包也成为javaAPI 的组成部分,所以java 和 javax 包没有区别,只是一个名字。
11. 接口和抽象类的区别是什么
  • 接口的方法默认是public , 所有方法在接口中不能有实现,而抽象类可以有非抽象方法。
  • 接口中除了有static、final 变量, 不能有其他变量,而抽象类中则不一定
  • 一个类能实现多个接口,但是只能继承一个抽象类,而接口本身可以通过extends 扩展多个接口。
  • 接口方法默认时public , 抽象方法可以被public, protected,default 修饰,抽象方法就是为了被重写,所以不能被private 所修饰。
  • 从设计层面上说,抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象,是一种行为的规范。
12. 成员变量和局部变量的区别
  • 从语法形式上看:成员变量是属于类的,而局部变量是在方法中定义变量的或是方法的参数。成员变量可以被public, private, static 等修饰符修饰,而局部变量不可以被访问修饰符及static 所修饰,但是成员变量和局部变量都能被final 所修饰。
  • 从变量在内存中存储方式看,如果成员变量是使用static 修饰,那么这个成员变量是属于类的,如果没有使用static 修饰,这个成员变量是属于实例的。而对象存在于堆内存中,局部变量则存在于栈内存。
  • 从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失
  • 成员变量如果没有赋初值:则会自动以类型的默认值而赋值(一种情况例外:被final 修饰的变量必须显式的赋初值)而局部变量则不会自动赋初值。
13. 创建一个对象用什么运算符?对象实体与对象引用有何不同?
  • new 关键字。 new 创建对象实例,对象实例存在于堆内存中,对象引用指向对象实体,对象引用存在于栈内存中。一个对象引用可以指向0 或1 个对象实体,但是一个对象实体可以有多个引用。
14. 什么是方法的返回值?返回值在类的方法里的作用是什么?
  • 方法的值是指我们获取到的某个方法体中的代码执行后产生的结果!
15. 一个类的构造方法的作用是什么?若一个类没有声明构造方法,该程序能正确执行吗?为什么?
  • 主要作用是完成类对象的初始化工作。 可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。
16. 构造方法有哪些特性?
  • 方法名与类名相同
  • 没有返回值,但不能用void 来声明构造函数
  • 生成类的对象时自动执行,无需调用
17. 静态方法和实例方法有什么不同
  • 在外部调用静态方法时,可以使用“类名.方法名”的方式,也可以使用“对象名.方法名”的方式。而实例方法只有这种方法。也就是调用静态方法不用实例化对象。
  • 静态方法访问本类成员时,只允许访问静态成员(静态方法和静态变量),不允许访问实例方法和实例变量。
18. 对象相等和指向他们的引用相等, 两者有什么区别?
  • 对象的相等,比的时内存中存放的内容相等。引用相等指的是他们指向的内存地址相等。
19. 在调用子类方法之前会先调用父类没有参数的构造方法,其目的是?
  • 帮助子类做初始化工作
20. == 与 equals
  • == 判断的是两个对象的地址是不是相等,即判断两个对象是不是一个对象, 基础类型比较的是值,引用类型比较的是地址
  • equals() 也是判断两个对象是不是相等。 一类是没有覆盖equals 方法,等价于 == , 另一类是覆盖了equals 方法。若相等,则返回true.
  • 说明: 当String 类型创建对象时,虚拟机会在常量池中查找有没有已经存在的值和想要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个String 对象。
21. hashCode 和 equals

为什么重写equals 时必须重写hashCode 方法?

  • 如果两个对象相等,则hashCode 一定也是相同的
  • 两个对象相等,两个对象分别调用equals 方法都返回true
  • 有两个对象的hashCode 相等, 他们也不一定相等
  • 因此equals 方法覆盖, hashCode 方法也必须要覆盖
  • hashCode 的默认行为是对堆上的对象产生特殊值。如果没有重写hashCode(), 则该class 的两个对象无论如何都不会相等。(即使这两个对象指向相同的对象)
22. 为什么Java中只有值传递
23. 简述线程、程序、进程的概念。以及他们呢之间的关系是什么?
  • 线程是比进程更小的执行单位,一个进程执行过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和系统资源。所以系统在产生一个线程,或者多个线程之间切换工作,负担比进程小得多。也正是如此,线程被成为轻量级进程。
  • 程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是程序是静态代码。
  • 进程是程序的一次执行过程。也是系统运行程序的基本单位,因此进程是动态的。
24. 线程有哪些基本状态?

这个补充在后面的线程面试题

25. 关于final 关键字的一些总结

final 关键字主要用于三个地方: 变量、方法、类

  • 对于变量来说,如果是数值类型,一旦声明为final , 则其数值不能改变,如果是引用类型,声明为final , 则说明它不能再指向另一个对象。
  • 对于类来说,一旦被声明为final , 则不能被其他类继承。 final 类中的所有方法都被隐式的声明为final.
  • 使用final 方法的原因有两个,第一个是可以把方法锁住,防止任何继承类修改他的含义。第二个原因是效率, 在早期java 的实现版本中,会将final 方法转为内嵌调用,如果方法过于庞大,可能看不出来内嵌调用带来的任何性能的提升。 类中所有的private 方法都会隐式的指定为final
26. Java 中的异常处理
27. Java 序列化中如果有些字段不想进行序列化,怎么办?

对于不想进行序列化的变量,使用transient 关键字修饰。
transient 关键字的作用是: 阻止实例中那些用此关键字修饰的变量序列化。当对象被反序列化时,被transient 修饰的变量不会被持久化和恢复。transient 只能修饰变量,不能修饰类和方法。

28. 获取用键盘输入的两种方法
  • Scanner
  • BufferedReader
29. Java 中的IO流

补充在后面的流部分

30. 常见关键字总结:static,final,this,super
31. Collections 工具类和Arrays工具类常见方法总结
32. 深拷贝VS 浅拷贝
  • 深拷贝: 对基本类型进行值传递, 对引用类型,创建一个新的对象,并复制其内容,此为深拷贝。
  • 浅拷贝: 对基本类型进行值传递, 对引用类型进行引用传递般的拷贝,此为浅拷贝。

补充:

33. long 或double 类型为什么不是线程安全的?

Java虚拟机规范定义的许多规则中的一条:所有对基本类型的操作,除了某些对long类型和double类型的操作之外,都是原子级的。
目前的JVM(java虚拟机)都是将32位作为原子操作,并非64位。当线程把主存中的 long/double类型的值读到线程内存中时,可能是两次32位值的写操作,显而易见,如果几个线程同时操作,那么就可能会出现高低2个32位值出错的情况发生。
要在线程间共享long与double字段是,必须在synchronized中操作,或是声明为volatile。

34. Java 中的访问修饰符

public : all
protected : 继承,同包
(default): 同包
private : 当前类

35. new 对象的过程
  1. 虚拟机遇到一条new指令时,首先将去检查这个指令的参数能否在常量池中定位到一个类的符号引用。并且检查这个符号引用代表的类是否已经被加载、解析和初始化过。如果没有,那就先执行类加载的过程。
  2. 在类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需内存的大小在类加载完成之后便可完全确定。为对象分配内存空间的任务等同于把一块确定大小的内存从Java堆中划分出来。有两种方式:`
  • 指针碰撞:假设Java堆中内存是规整的,所有用过的内存都放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,那分配内存就是将指针往空间空间挪动一段与对象大小相等的距离,这种分配内存的方式就被称为指针碰撞;

  • 空闲列表:如果Java堆中的内存并不是规整的,已经使用的内存和空闲内存相互交错,那就没有办法简单地使用指针碰撞的方法进行内存分配了。虚拟机此时必须维护一个列表用来记录哪些内存块是可用的,在分配的时候从列表中找到一块足够大的空间为分配给对象实例,并且更新列表上的记录,这种分配方式就被称为空闲列表。

(选择哪一种分配方式由Java堆是否规整决定,而Java堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定)。
除了如何划分可用空间之外,还要考虑的一个问题就是 对象创建 在虚拟机中是非常频繁的行为,即使是仅仅修改一个指针的位置,在并发的情况之下也并不是线程安全的 ---- 可能出现正在给对象A分配内存,指针还没来得及修改,对象B同时使用了原来的指针来分配内存的情况。解决方案也有两种:

一种 是对分配内存空间的动作进行同步处理 ---- 实际上虚拟机采用CAS配上失败重试的方式保证更新操作的原子性;

另一种
是把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程缓冲分配(ThreadLocal
Allocation
Buffer,TLAB)。哪个线程需要分派内存,就在哪个线程的TLAB上分配,只有TLAB用完并分配新的TLAB时,才需要同步锁定。虚拟机是否使用TLAB,可以通过-XX:+/-UseTLAB参数来设定。

  1. 内存分配完成之后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),如果使用TLAB,则此工作可以提前至TLAB分配时进行。这一步操作保证了对象的实例字段在Java代码中可以不赋初值就可以直接使用,程序能访问到这些字段的数据类型所对应的零值。

  2. 接下来,虚拟机要对对象进行一些必要的设置,比如这个对象是哪个类的实例、如何才能找到类的元数据、对象的哈希码、对象的GC分代年龄等信息。

  3. 在上面的工作完成之后,从虚拟机的角度来看,一个新的对象已经产生了。但从Java程序的角度来看,对象创建才刚刚开始 —— 方法还没执行,所有的字段都还为零。一般来说(由字节码中是否跟随invokespecial指令所决定),执行 new 指令之后会接着执行方法,把对象按照程序员的意愿进行初始化,这样一个真正的对象才算创建完成。

链接:https://www.jianshu.com/p/26dda4e5016a

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值