Java基础

00 可能涉及的知识

  • java基础知识
  • 设计模式
  • 异常处理,跨域
  • git使用
  • SpringBoot自动配置原理,AOP,Spring源码,springmvc流程
  • redis:持久化AOF
  • 数据结构算法题
  • 计算机网络3次握手
  • 并发

java基础

final 定义的变量不能再改变值,定义的类为最终类,不能再被继承

序列化:将一个对象编码为字节流称为对象的序列化,相反的处理过程称为反序列化

重写:子类重写父类方法

重载:同一个类,方法名字相同,而参数不同

java中值传递

  • 值传递 :方法接收的是实参值的拷贝,会创建副本;引用传递 :方法接收的直接是实参所引用的对象在堆中的地址,不会创建副本,对形参的修改将影响到实参。
  • java中只有值传递没有引用传递。如果参数是基本类型的话,传递的就是字面量值;如果参数是引用类型,传递的就是所引用的对象在堆中地址值的 拷贝,同样会指向该对象

多态:几个子类继承同一个父类,new对象时,把对象类型声明为父类类型,再调用对象的方法时就是调用的子类的方法。实现方法:

  • 继承父类,重写方法
  • 实现接口
  • 抽象类,抽象方法

面向对象特征

  • 继承

  • 封装

  • 多态:父类引用指向子类对象

==和equals区别

  • == 比较的是两个对象是否是同一对象,对比的是栈中的值,基本数据类型是变量值,引用类型是堆中内存对象的地址

  • 一个类没有重写equals方法,默认采用的是 ==(Object类中定义的),重写了equals方法按重写的规则来。String重写了equals方法,比较的是字符串内容

java public class test1 { public static void main(String[] args) { String a = new String("ab"); // a 为⼀个引⽤ String b = new String("ab"); // b为另⼀个引⽤ String aa = "ab"; // 放在常量池中 String bb = "ab"; // 从常量池中查找 if (a == b) // false,⾮同⼀对象 System.out.println("a==b"); if (aa == bb) // true System.out.println("aa==bb"); } }

字符型常量和字符串常量的区别

字符常量相当于⼀个ASCII 值,可以参加表达式运算; 字符串常量代表该字符串在内存中的地址

成员变量与局部变量的区别有哪些?

  • 成员变量如果没有被赋值,则会⾃动赋值;⽽局部变量不会⾃动赋值

  • 成员变量是对象的⼀部分,随着对象的创建⽽存在;⽽局部变量随着⽅法的调⽤⽽⾃动消失

  • 成员变量可以被 public , private , static 等修饰符所修饰,⽽局部变量不能被访问控制修饰

⼀个类的构造⽅法的作⽤是什么

​ 完成对象的初始化工作,即便没有声明构造方法也会有默认的不带参数的构造方法

静态方法和实例方法有何不同

​ 静态⽅法访问本类的成员时,只允许访问静态成员变量、⽅法,⽽不允许访问非静态的成员变量和方法

在 Java 中定义⼀个不做事且没有参数的构造⽅法的作⽤

​ Java 程序在执⾏⼦类的构造⽅法之前,如果没有⽤ super() 来调⽤⽗类特定的构造⽅法,则会调⽤⽗类中“没有参数的构造⽅法”,如果父类中没有不带参数的构造方法会在编译时报错

Java 序列化中 transient 关键字的作用

​ 被该变量修饰的关键字不会被序列化,当对象被反序列化时也不会被恢复

⽤键盘输⼊常⽤的两种⽅法

  • 通过Scanner

java Scanner input = new Scanner(System.in); String s = input.nextLine(); input.close();

  • 通过 BufferedReader

java BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); String s = input.readLine();

java异常类层次结构

Java基础_第1张图片

​ finally 块: ⽆论是否捕获或处理异常, finally 块⾥的语句都会被执⾏。当在 try 块或 catch 块中遇到 return 语句时, finally 语句块将在⽅法返回之前被执⾏,并覆盖原始的返回值。

Throwable类常⽤⽅法

  • public string getMessage() :返回异常发⽣时的简要描述
  • public string toString() :返回异常发⽣时的详细信息
  • public void printStackTrace() :在控制台上打印 Throwable 对象封装的异常信息

final

  • 修饰类:表示类不可被继承

  • 修饰方法:表示方法不可被子类覆盖,但是可以重载

  • 修饰变量:如果是基本数据类型的变量,则其数值⼀旦在初始化之后便不能更 改;如果是引⽤类型的变量,则在对其初始化之后便不能再让其指向另⼀个对象

String、StringBuffer、StringBuilder

  • String是final修饰的,每次操作都会产生新的String对象
  • StringBuffer是线程安全的,每个方法都加了synchronized
  • StringBuilder线程不安全

一般优先用StringBuilder,多线程情况下使用StringBuffer

接口和抽象类区别

  • 一个类可以实现多个接口,但只能实现一个抽象类;接口本身可以通过extends扩展多个接口
  • 接口中只能有static、final修饰的变量,不能有其他变量;抽象类不一定

  • 接口中只能有默认方法和静态方法;抽象类除了抽象方法还可以有普通方法

构造器 Constructor 是否可被 override

Constructor 不能被 override(重写),但是可以 overload(重载)

深拷贝和浅拷贝

深拷贝会重新创建一个对象然后指向它;浅拷贝传递的是对象的地址,两个变量会指向同一对象

为什么 Java 中只有值传递

对象作为参数传递的是对象地址值的拷贝;C++引用传递改变形参的值会改变实参,引用变量和被引用的变量是同一个

反射

运行时获取Class类对象及其内部信息(方法、属性、构造函数),然后控制实例对象的能力

⾃动装箱与拆箱

装箱:调用valueOf()将基本数据类型转换成对象,如Integer.valueOf(int)

拆箱:将包装类型转换为基本数据类型;如:Integer.intValue()

说说List,Set,Map三者的区别

  • List : 存储的元素是有序的、可重复的。
  • Set :存储的元素是⽆序的、不可重复的
  • Map:使⽤键值对(kye-value)存储,Key 是不可重复的,value可重复 的

说一下HashMap的结构、扩容机制以及树形化

HashMap是数组+链表+红黑树实现(红黑树:能够保证平衡的二叉查找树)

Java基础_第2张图片

​当HashMap中元素个数超过数组大小*loadFactor时就会扩容。默认数组大小Capacity为16,每次扩容就把数组大小扩大一倍;loadFactor为负载因子,默认为0.75,负载因子的大小决定了HashMap的数据密度

​当HashMap中一个链的对象个数达到8个,并且数组容量capacity达到64,这个链表就会用红黑树表示,如果没有达到64就先扩容解决。如果树中结点个数低于6个,树就会转换为链表

HashMap 的⻓度为什么是2的幂次⽅

计算元素在数组位置时,需要用hashCode值对数组长度length取余,即: hash%length,如果length的值是2的幂次就可以用二进制与&运算,hash&(length-1)的结果和hash%length结果一样,采⽤⼆进制位操作 &,相对于%能够提⾼运算效率

负载因子值的大小,对HashMap有什么影响

  • 负载因子的大小决定了HashMap的数据密度。
  • 负载因子越大密度越大,扩容时间就越晚,发生碰撞的几率就越高,数组中的链表就越容易长, 造成查询或插入时的比较次数增多,性能会下降。

  • 负载因子越小,就越容易触发扩容,数据密度也越小,意味着发生碰撞的几率越小,数组中的链表也就越短,查询和插入时比较的次数也越小,性能会更高,但是会浪费一定的内容空间

HashMap和HashTable区别

Java基础_第3张图片

  • 线程是否安全:HashMap线程不安全,HashTable线程安全,因为HashTable内部的方法基本经过synchronized修饰(效率低,全局一把锁)

  • 对 Null key的支持:HashMap支持存储为空的key,HashTable不允许支持为空的key

  • 底层数据结构:HashMap中当链表的长度大于8,并且数组的长度达到64时就会把链表转换为红黑树;HashTable没有这样的机制

HashMap和HashSet区别

HashSet底层使用HashMap实现的,在构造器中是new 了 HashMap,大部分方法都是调用的HashMap中的方法

```java // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object();

public HashSet() { map = new HashMap<>();}

public boolean add(E e) { return map.put(e, PRESENT)==null; } ```

HashSet如何检查重复

先计算hashCode(),如果hashCode值不一样,则加入该对象;如果hashCode值一样,就调用equals值比较,equals()返回true就认为两个对象一样,加入失败,equals()返回值不一样就加入该对象

ArrayList扩容机制

  • 如果添加元素时,先判断数组需要的最小容量,如果原数组是空数组,则指定数组最小容量为10(DEFAULT_CAPACITY),否则指定数组容量为数组中元素个数+1,如果需要的最小容量大于数组长度则扩容,扩容1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1);

Java基础_第4张图片

Arraylist 与 LinkedList 区别

  • Arraylist 底层使⽤的是 Object 数组;对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动指针
  • LinkedList底层使⽤的是双向链表;对于新增add()和删除操作remove(),LinkedList比较占优势,因为ArrayList要移动数据

ArrayList 与 Vector 区别

  • Vector和ArrayList几乎是完全相同的,都实现了相同的类和接口(TreeMap和TreeSet底层都用的红黑树)

  • 区别在于Vector是线程安全的(方法上加了synchronied),ArrayList线程不安全

如何选⽤集合?

  • 主要根据集合的特点来选⽤,⽐如我们需要根据键值获取到元素值时就选⽤ Map 接⼝下的集 合,需要排序时选择 TreeMap ,不需要排序时就选择 HashMap ,需要保证线程安全就选⽤ ConcurrentHashMap 。

  • 当我们只需要存放元素值时,就选择实现 Collection 接⼝的集合,需要保证元素唯⼀时选择实现 Set 接⼝的集合⽐如 TreeSet 或 HashSet ,不需要就选择实现 List 接⼝的⽐如 ArrayList 或 LinkedList ,然后再根据实现这些接⼝的集合的特点来选⽤。

说一下ConcurrentHashMap

Java基础_第5张图片

jdk.7之前 采用Segment 数组+HashEntry 数组 + 链表。Segment 的结构和 HashMap 类似,是 ⼀种数组和链表结构,⼀个 Segment 包含⼀个 HashEntry 数组,每个 HashEntry 是⼀个链表结构的元素,每个Segment对象用一把锁

jdk1.8 采用Node数组 + 链表 +红⿊树,类似HashMap ,synchronized 只锁定当前链表或红⿊⼆叉树的⾸节点,这样只要 hash 不冲突,就不会产⽣并 发,效率⼜提升 N 倍

hashCode()?????????????????????

hashCode()默认根据堆上的对象产⽣哈希值,哈希值代表了对象的特征,同一哈希值可能对应多个对象,即哈希值相等并不代表两个对象相等

你可能感兴趣的:(字符串,链表,java,数据结构,javase)