面试-基础阶段一

构造器 Constructor 是否可被 override?

  • 不可,重写是指在子类中定义一个同方法签名的方法覆盖掉从父类继承而来的方法;构造器名与类名存在一对一关系且无法被子类继承,因此不可被重写
2.重载和重写的区别
  • 重载发生在同一类中,同方法名,不同参数列表(参数的顺序,类型,个数不同), 与返回值和权限修饰符无关
  • 重写发生在子类当中, 需要存在继承关系, 要求同方法签名, 不同方法体, 返回值类型<=父类返回值类型, 权限>=父类权限
3.Java 面向对象编程三大特性
  • 封装性 : 高内聚低耦合
  • 继承性 : DRY原则
  • 多态性 :父引子,接口引实现类
String 为什么是不可变的?
  • String 底层是用一个 char 数组存储字符串的, 此数组的引用变量用 final 修饰, 是常引用, 无法指向新数组, 因此 String 不可变
  • private final char[] value
4.String、StringBuffer 和 StringBuilder 的区别是什么?
  • 可变性:
    _String 不可变
    _StringBuffer 和 StringBuilder 都是可变的(引用指向可变)
  • 安全性
    _String 不可变天生线程安全
    _StringBuffer 类的所有方法都加了同步锁, 因此线程安全
    _StringBuilder 类没有, 线程不安全
  • 执行效率
    _每次改变 String 对象, 都是生成一个新的 String 对象, 然后重新指向它, 性能偏低
    _相比 StringBuiler,StringBuiler 牺牲了安全性换来了性能的些许提高
5.自动装箱与拆箱
  • 自动装箱 : 是指把一个对应类型的常量直接赋值给一个包装类对象, 包装类对象会自动把数据进行封装
  • 自动拆箱 : 是指把一个包装类对象直接赋值给一个对应基本数据类型的引用变量, 包装类对象会自动把数据吐出, 配合赋值操作
6.接口和抽象类的区别是什么?
  • 接口:
    _接口中只能定义抽象方法, 不能有具体的实现( jdk1.8 的时候可以定义默认方法, 用 default 关键字修饰), 定义字段必须用 static final 修饰
    _接口和类之间是多实现的关系
    _接口之间为多继承
    _接口方法默认是 public 修饰, 不能用 private 修饰(无法被实现)
  • 抽象类
    _抽象类中可以定义具体实现
    _子类必须实现抽象类的所有抽象方法, 否则会编译报错
    _抽象类和类之间是单继承
7.构造方法有哪些特性?
  • 构造方法名与类名相同
  • 构造方法没有返回值
  • 构造方法可重载
  • 系统默认提供一个无参构造方法, 手动定义后失效
  • 无法被子类继承, 无法被重写
  • _创建类对象时自动调用
8.在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?
  • 完成继承属性的初始化工作(借用父类构造器来对继承属性进行空间初始化)
9.== 与 equals 区别
  • 对于基本数据类型, 都是比较其内容(值), 功能无二
  • 对于引用变量, == 比较的是其地址值, equals 在没被重写前也是默认比较其地址值, 重写之后通常用于比较对象内容
10.你重写过 hashcode 和 equals 么,为什么重写 equals 时必须重写 hashCode 方法?
  • 对于底层实现是哈希表的数据结构, 存储数据时需要先进行哈希值比较, 结果相同再进行内容比较; 只重写 equals 方法, 哈希值的碰撞概率很有可能会增加(因为基于内存地址,地址有限), 尤其是存储数据量比较大的时候, 且key值比对的效率远高于内容比对, 因此通常要求 equals 方法和 hashCode 方法的比对结果有相当程度的一致性, 所以重写时要求都重写

额外知识
首先一个对象肯定有物理地址,网上有人把对象的 hashcode 成是对象的地址,事实上这种看法是不全面的,确实有些 JVM 在实现时是直接返回对象的存储地址,但是大多时候并不是这样,只能说可能存储地址有一定关联, 那么对象如何得到 hashcode 呢?通过对象的内部地址(也就是物理地址)转换成一个整数,然后该整数通过 hash 函数的算法就得到了hashcode(不同jvm的实现不同, hotspot 的实现贴在了最后),所以,hashcode 是什么呢?就是在 hash 表中对应的位置。这里如果还不是很清楚的话,举个例子,hash 表中有 hashcode 为1、hashcode 为2、(...)3、4、5、6、7、8这样八个位置,有一个对象 A,A 的物理地址转换为一个整数17(这是假如),就通过直接取余算法,17%8=1,那么A的 hashcode 就为1,且A就在 hash 表中1的位置。

11.线程有哪些基本状态,并描述每种状态?
  • 新生状态 : 新建一个线程, 完成初始化后进入新生状态, 等待方法启动
  • 就绪状态 :
    _新生线程调用 start() 方法后启动进入就绪状态, 进入就绪队列, 等待 cpu 抽调
    _阻塞状态线程完成资源装卸或睡眠时间结束时重新进入就绪状态, 进入就绪队列, 等待 cpu 抽调
    _运行状态 : cpu 抽调线程, 进入 cpu 执行任务
  • 阻塞状态 : 执行任务过程中需要装卸资源或进入睡眠时出让 cpu, 进入阻塞状态, 进入阻塞队列等待阻塞条件解除
  • 死亡状态 :
    _线程完成所有任务进入死亡状态
    _线程被强制终止进入死亡状态(调用 exit 方法,断电)
    _有异常抛出而无异常捕捉进入死亡状态
12.final 关键字修饰这三个地方:变量、方法、类,会有什么作用
  • 修饰基本数据类型变量 : 锁定值
  • 修饰引用变量 : 锁定指针
  • 修饰方法 : 方法无法被重写
  • 修饰类 : 类无法被继承
13.Java 序列化中如果有些字段不想进行序列化,怎么办?
  • 用 transient 关键字修饰阻止变量的序列化
  • 只能修饰变量,不能修饰方法,类
14.获取用键盘输入常用的两种方法
  • 用扫描器 Scanner
    Scanner scanner = new Scanner(System.in);
    String s = scanner.nextLine();
    scanner.close;
  • 用输入流
    BufferReader reader = new BufferReader(new InputStream(System.in));
    String s = reader.readLine();
    reader.close();
15.既然有了字节流,为什么还要有字符流?
  • 字节流
    _以字节为处理单元
    _适用于各种流媒体传输
    _默认直接读写不用缓冲区
    _处理字符数据的时候要先把字符转成字节数据,如果转编用的字符集不一致很容易导致乱码,且效率低
  • 字符流
    _以两个字节为处理单元,适配 unicode 万国码
    _直接读取字符串,根据指定(UTF-8)编码格式转成字节数据(写入相反,反编码)
    _用到缓冲区(因为要进行内部编译反编译)
    _只能处理文本数据
16.描述深拷贝和浅拷贝
  • 深拷贝是在内存中拷贝了一个对象,并创建引用指向这个新对象,底层有两个对象
  • 浅拷贝是创建了个新引用指向原来的对象,底层只有一个对象
17.说说&和&&的区别。
  • & : 左边表达式运算结果为 false, 仍执行右边的表达式运算
  • && : 左边表达式运算结果为 false, 不执行右边的表达式
18.final, finally, finalize 的区别。
  • final : 关键字, 可以修饰类, 方法和变量
  • finally : 关键字, 用于修饰代码块, 通常与 try 搭配使用, 表示最终执行代码块
  • finalize : 是 Object 的一个方法, 垃圾收集器进行垃圾清理前调用, 做相应的资源回收工作(如关闭流,关闭文件等)
19.ArrayList 和 Vector 的区别
  • 开始时间 : ArrayList (jdk1.2) 和 Vector (jdk1.1) 是等价类关系
  • 线程安全性 : ArrayList 非线程安全, Vector 线程安全(源码有 sychronized)
  • 性能效率 : ArrayList 较高
  • 拓容量 : ArrayList 拓容50%, 拓容参数不可设置, Vector拓容100%, 拓容参数可设置
20.Arraylist 与 LinkedList 区别?
  • 底层数据结构方面 : ArrayList 基于 Object 数组, LinkedList 基于双向链表
  • crud性能方面 : ArrayList 查询性能好, 支持随机元素访问, LinkedList 增删性能好
  • 空间占用方面 :
    _ArrayLis 物理存储空间连续, 空间浪费体体现在末尾一般存在预留位
    _LinkedList 物理存储空间不连续, 每个存储单元占用空间比 ArrayList 大(需要存储前后链接单元的地址)
21.ArrayList 的拓容机制
  • 新容量 = 旧容量 + 旧容量 * 50%
22.HashMap 和 Hashtable 的区别
  • 线程安全性 : HashMap 非线程安全, HashTable 线程安全
  • 键值限制 : HashMap 允许键和值为 null, HashTable 不允许
  • 拓容量 :
    _HashMap 的hash 数组默认容量为16,拓容方式为16 * 2n
    _HashTable的 hash 数组默认容量为11,拓容方式为旧容量 * 2 + 1
23.说说 List, Set, Map 三者的区别?
  • List和Set 继承了 Collection 接口, Map 本身是一个父接口
  • List : 单元素有序集合, 存取有序, 元素可重复
  • Set : 单元素不重复集合, 存取无序, 元素不可重复
  • Map : 双元素映射集合, 以键值对的形式存储, key唯一
24.什么是线程死锁
  • 线程死锁是指两个或多个线程同时被阻塞, 线程之间相互申请对方拥有的资源, 却对获得的资源保持不放, 进入无限期阻塞状态, 称为线程死锁
25.如何避免线程死锁?
  • 破坏互斥条件(理论上无法破坏)
  • 破坏请求与保持条件(请求资源的同时,死抱资源不放)
  • 破坏不剥夺条件(申请对方资源的失败,强制释放对方的资源)
  • 破坏循环等待条件(反序释放资源)
26.说说 sleep() 方法和 wait() 方法区别和共同点?
  • 二者都可以暂停线程的执行
  • 主要区别 : sleep() 没有释放锁, wait() 释放了锁
  • sleep() 方法睡眠时间到了线程会自动苏醒, wait() 方法默认不会自动苏醒, 但也可以设定一个等待时间使线程自动苏醒
  • 应用方面 : sleep() 常用于线程的主动暂停, wait() 同常用于线程之间的通讯/交互(存在互动性质的情况)
27.HashMap 和 ConcurrentHashMap 的区别

线程安全方面 :
_ HashMap 非线程安全, concurrentHashMap 线程安全
_concurrentHashMap 采用了锁分段技术, 把Hash数组分成了若干段, 每段之间都有锁,插入数据需要获取相应小段的锁, 这种技术让锁的精度更高, 并发性能更好

28.现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行?
  • 利用 Thread 类的 join 方法
  • 在 T2 中调用T1的 join(0) 方法, 在 T3 中调用 T2 的 join(0) 方法, 如此便能使并行的线程变成串行
    额外补充 :
    join(0) 中的0表示在 join() 方法所在线程执行完后再执行调用 join() 方法的线程
    join(10) 则表示在 join() 方法所在线程执行完等待10毫秒后再执行调用 join() 方法的线程
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值