未经允许所有内容都可都可都可转载,不对的地方欢迎指正

String

1.String s1 = “a”;String s2 = “a”; a==b? s1.equals(s2)?

  • String 字符串时常量,常量存储在方法区的常量池。
  • 进入常量池规则,如果没有,创建,如果有,不再创建通过地址指向即可。
  • 所以,s1 = “a”, 会在常量池创建一个字符串常量 “abc”,地址给了s1
  • 当s2 = “a” 时,常量池已经有了整个字符串对象,所以将地址给了s2.
  • 两个引用指向了同一个地址,所以a==b 返回true.
  • String类重写了equals方法。先比较了长度,后转char数组每位逐一比较,比较的是属性值,所以equals也是相等的。

2.下面这句话创建了几个对象?String s = new String(“abc”);

  • 如果常量池有 “abc” 整个字符串,创建了一个对象。即堆中创建了一个String对象。 堆中对象地址与常量池中不同。
  • 如果常量池没有 “abc”,则创建了两个对象,先在常量池创建了字符串对象,在再堆中创建了String对象。

3.String s1 = “abc”. s2 = new String(abc) 判断是否相等。

  • s1 == s2 // false. 结合1.2 略
  • s1.equals(s2) // ture. 同上略

4. 如下,+ 号的底层是什么的理解?

  • s2 == s3 ture, 单纯的字符串相加已经在编译器完成了常量池的指向。
  • s2 == s4 false, s1 + b, s1本身不是字符串常量,而是字符串的引用。而+号实际上是通过StringBuffer 或者 StringBuilder的append方法拼接后转化为String对象,对象在堆中。
  1. @Test
  2. public void testStr(){
  3. String s1 = "a";
  4. String s2 = "ab";
  5. String s3 = "a"+"b";
  6. String s4 = s1 + "b";
  7. System.out.println(s2 == s3); // ture
  8. System.out.println(s2 == s4); // false
  9. }

5.String ,StringBuffer, StringBuilder的区别

略。

6. intern方法

  • 如问题4 String s4 = (s1 + “b”).intern(); s2 == s4 为true.
  • 当intern方法被调用时,如果常量池中有一个字符串和当前调用方法的字符串equals相等,name就返回常量池中字符串引用,如果池中没有,放入,返归引用。

7.为什么使用HashMap时总是使用String做key?

  • 因为Stirng时不可变的,当创建字符串时,他的hashcode被缓存下来,不需要再次计算。
  • HashMap内部实现时通过key的hasCode来确定Value的位置。所以相比使用其他key计算更快。

8 String和byte ,char的互转。

ArrayList

1、讲讲ArrayList? — arrayList实现了List接口,继承与AbstarctList、底层数据结构为动态数组。线程不安全。 2、说说ArrayList默认长度? —指定正整数为指定数据长度,空构造长度为0,第一次添加元素时初始化,默认大小为10. 3、ArrayList的扩容? — 原大小的1.5倍和添加元素后的长度做比较。取大的。 4、ArrayList为什么增删慢? — 底层为数组,内存空间连续,需要动态改变数组大小,调用System.arrayCopy且需要移动其他元素位置。频繁地增删建议使用LinkedList. 5、线程安全吗? —线程不安全,使用Vector替代,或者使用 SynchronizedList 、CopyonWriteArrayList 6、modCout作用? —-迭代时next方法中会校验 modCount和expectModCount大小,如果改变抛出ConcurrentModificationException异常。 7、如何拷贝一个arrayList数组至另外一个ArrayList? —7.1 直接new = old.clone(); 浅拷贝 7.2 new ArrayList(old); 浅拷贝 7.3 Collection.copy 身拷贝 8、什么时候使用ArrayList,什么时候使用LinkedList? arrayList 增加删除慢。LinkedList 查询慢。

== 和 equals 的区别?

== 比较的是栈中的值, 基本数据类型比较的是变量值。 引用类型比较的是堆中的地址。 equals : Object类中默认也是通过 == 比较,通常会重写。

重载和重写?

重写 override 发生在子父类中,方法名,参数名必须与父类相同, 返回值范围小于等于父类,异常小于等于父类。访问修饰符大于等于父类,如果父类访问修饰符为private,则不能重写。 重载 overload 发生在同一个类中,方法名必须相同、 参数类型不同、个数不同、顺序不同。 返回值和修饰符可以不同。发生在编译时。

什么是面向对象

做一件事情,面向过程更注重每一个步骤和顺序。 面向对象更注重做一件事情需要哪些参与者。即这些参与者需要做什么。 举例说明(洗衣服):

  1. 面向过程: 打开洗衣机—> 放衣服 —> 放洗衣粉—> 清洗衣服 —> 烘干
  2. 面向对象: 人(对象): 打开洗衣机 放衣服 放洗衣粉 都是人的方法, 洗衣机(对象): 清洗衣服 烘干 都是洗衣机的方法

面向对象的三大特性

  • 封装

将一系列的功能封装成方法对外可见, 内部的实现细节外部无需关注。 同时也可以通过修饰符 限定封装的方法对谁可用。

  • 继承

继承父类方法,做出自己的改变和扩展。 子类共性的方法或者属性,直接定义在父类,无需自己再定义。只需要根据自身特性扩展。

  • 多态

基于对象所属类的不同,调用同一个方法,实际执行的逻辑不同。

抽象类和接口的区别

  • 基础

1) 抽象类中可以存在普通函数、接口中1.7前只能是public abstract方法,1.8后可以有静态和default方法。 2) 抽象类中成员变量可以是各种类型的。而接口中的成员变量只能是publice static final的。 3) 抽象类只能继承一个,而接口可以多实现。

  • 高级

1) 接口 like a的关系。 2) 抽象类 is a 的关系。 3) 比如: 飞行物可以是一个接口 可以定义fly这个方法, 而鸟就是实现了这个接口的抽象类,可以定义鸟的名称、大小、颜色等属性, 而飞机也是实现了 飞行物接口的,可以定义型号、生产地、邮箱大小等属性。

数据类型

java基础 - 图5

数据结构

线性

数组

内存空间连续,可根据下标查询,查询快,增加删除慢

链表

内存空间不连续,查询慢,增加删除快

Stack栈(Vector子类,底层为数组):

  1. 是什么
    1. 一种特殊线性数据结构
    2. 只允许从在固定的一端(栈顶)插入和删除元素。
    3. FILO first in last out: 先进后出
  2. 类关系图

image.png

  1. 构造方法:默认大小:10,扩容机制同Vector

image.png

  1. 常用方法:

image.png

队列

  1. 类关系图

image.png

  1. 特点: 先进先出 FILI
  2. 非阻塞队列:ConcurrentLinkedQueue
  3. 阻塞队列:

image.png
image.png
add:
image.png
image.png
image.png
image.png
image.png

树形

二叉树简介:

image.png

数的基本术语

若一个结点有子树,那么该结点称为子树根的“双亲”,子树的根称为该结点的“孩子”。有相同双亲的结点互为“兄弟”。一个结点的所有子树上的任何结点都是该结点的后裔。从根结点到某个结点的路径上的所有结点都是该结点的祖先。

满二叉树

高度为h,并且由2h-1个结点组成的二叉树,称为满二叉树

image.png

完全二叉树

定义:一棵二叉树中,只有最下面两层结点的度可以小于2,并且最下层的叶结点集中在靠左的若干位置上,这样的二叉树称为完全二叉树。

特点:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。显然,一棵满二叉树必定是一棵完全二叉树,而完全二叉树未必是满二叉树。

image.png

二叉搜索树(BST):

如果左子树存在,则其左子树中的每个节点的值都小于该节点的值 如果右子树存在,则其右子树的每个节点的值都大于该节点值 树在插入的时候会导致倾斜,不同的插入顺序导致树的高度不一致。比如:

image.png

image.png

每次插入,如果大于跟节点,从右边找位置,小于从左边。 从右边一直找到大于当前值的节点,左边没节点放左边,左边有节点和左边比,最终插入的原则,左小右大,一条树线性上右边小到大,左边大到小。

高度平衡树(AVL)

BST不同的插入顺序会导致树的高度不一样,而树的高度直接影响了查询效率。最坏的情况下所有节点都在一条线上。 平衡树在插入和删除的时候会将高度保持在LogN上。 具有二叉搜索树的全部特点,而且左右高度差不超过1

image.png

image.png

2-3-4 树

image.png

红黑树

image.png
image.png

集合框架

Colleciton类关系图

image.png

ArrayList(不安全,效率高)

image.png

Vector(线程安全,效率不高)

image.png

ArrayList 和 Vector区别:

image.png

HashMap

脑图整理: https://www.processon.com/mindmap/612211871e08534545453e07 有空回来补充。

IO

javaIO体系

  • inputStream

image.png

  • outputStream

image.png

  • Reader

image.png

  • Writer

image.png

java中有几种类型的流?

字节流和字符流

  1. 字节流继承自inputStream和OutPutStream.
  2. 字节流继承自Reader和Writer

谈谈javaIO里面常见类,字节流,字符流,接口,实现类,方法阻塞

  1. 输入流就是指从外部文件输入到内存,输出流指从内存输出到文件。
  2. 字节流主要是InputStream和OutputStream和他们的子类FileInputStream,FileOutputStream,BufferedOutputStream等。
  3. 字符流主要是Reader和Writer和他们的子类。BufferedReader、FileReader等。
  4. 他们都实现了Closeable,Flushable,Appendable这些接口。
  5. java中的阻塞式方法是指程序程序在调用该方法时,必须等待输入数据可用,或者检测到输入结束,参会继续往下执行,否则一致会停留在该语句上。比如read()方法和readLine()方法。

字符流和字节流有什么区别

  1. 字节流在操作的时候本身是不会用到缓冲区的,是直接操作的文件。字符流在字符流操作的时候使用到了缓冲区。
  2. 字节流在操作文件时,即使不关闭资源,即不调用close方法,文件也能输入,因为是直接操作的文件。而字符流用的是缓冲区,需要flush,close才能真正的刷新缓冲区输出内容。
  3. InputStream,read方法返回int,因为字节流每次读取的是1一个字节,占位8bit,范围在0——28-1. 如果读取到流末尾返回-1.
  4. Reader,read方法范围int,因为字符流每次读取的是2个字节,占位16bit,范围在0——216-1,如果读取到行末尾返回-1.

反射

序列化

什么是序列化

序列化是指将对象持久化为可以存储或者传输的形式的过程。 将持久化存储转化为对象的过程称为反序列化。

JAVA相关类

image.png

示例代码

  • 方式一:
    • 实现serializable
    • 通过ObjectOutputStream的write和ObjectInputStrem的read实现。

image.png

  • 方式二
    • 继承Externalizable
    • 必须设置无参构造方法
    • 复写writeExternal和readExternal可以指定需要序列化和反序列化的属性。
    • 读取数据类型一致,读取顺序一致

image.png
image.png

泛型

泛型中的extends和super的区别。

<? extend T>表示包括T在内的任何T的子类 <? super T>表示包括T在内的任何T的父类。

String

String、StringBuffer、StringBuiler区别

  1. Stirng是final修饰的。不可变,每次操作都会产生新的对象。
  2. StringBuilder和StringBuffer都是在原对象上操作。
  3. StirngBuffer是线程安全的,StringBuilder是线程不安全的。
  4. StirngBuffer的每个方法都synchronized修饰的。
  5. 性能 StirngBuilder > StringBuffer > String
  6. 优先使用StringBuilder,多线程共享变量时使用StringBuffer.

7种单例

深拷贝浅拷贝

什么是深拷贝、什么是浅拷贝

  1. 一个对象中,存在两种类型的属性,一种是基本数据类型。一种是引用数据类型。
  2. 浅拷贝是指,只会拷贝基本数据类型的值,以及示例对象的引用,并不会复制一份引用地址所指向的对象。即浅拷贝出来的对象,内部指向的是同一个对象。
  3. 深拷贝既会拷贝基本数据类型的值,也会针对实例对象的引用地址所指向的对象进行复制,即最后指向的是一个新的对象。

实现深拷贝的两种方式

  1. 实现Cloneable方法,并覆盖object中的clone方法。设置作用域为public。
  2. 实现序列或接口Serializbale,通过反序列化来生成新对象。

List扩容是深拷贝还是浅拷贝

  1. 地从使用的是 Arrays.copyof 和 System.arrayCopy.
  2. 对于数组来说,是深拷贝。相当于拷贝了一份新的数组空间。
  3. 对用数组元素来说,只有基本数据类型和String时,是深拷贝。
  4. 引用数据类型都是浅拷贝。

值传递引用传递

  1. 基本数据类型是值传递,对形参的修改不会影响实参。
  2. 引用数据类型是引用传递,形参和实参指向内存中同一个地址。所以对形参的修改会影响实际的对象。
  3. String和Ingteger、Double等封装类型可以理解为值传递,对形参的修改不会影响实参对象。

JDK8新特性

ConcurrentHashMap

JAVA中的异常体系

image.png

  1. 所有的异常都继承自Throwable. 分为两个子类ERROR 和 Exception.
  2. ERROR一旦发生,就只有一个结果,那就是程序终止,JVM退出,ERROR是不可处理的。比如OutOFMemoryError 和 StackOverflowError.
  3. Exception下面有很多内容,大概分为两个部部分,RuntimeException和Exception的直接子类。
  4. RuntimeException被称为运行时异常,运行时异常,在编写程序的时候,可以选择处理,也可以不处理。 运行时异常都是写代码过程中,能避免的,比如NumberFormatException,ArrayIndexoutOfBoundsException等。
  5. Exception的直接子类,都被称为编译时异常,编译时异常并不是在编译阶段发生的。是表示在编写程序的时候必须预先对这种异常进行处理,不处理编译器会报错。比如IOException. ClassNotFoundException.

final

修饰方法

  1. 表示方法不可被子类覆盖,即不能使用override从写,
  2. final修饰的方法可以重写。

修饰变量

表示变量一旦被赋值,就不可以更改它的值。

  1. 修饰成员变量
    1. 如果final修饰的是类变量,即static修饰,赋值必须在
      1. 声明时赋值
      2. 静态代码块中赋值
    2. 如果final修饰的成员变量,即没有static修饰,赋值必须在
      1. 声明时赋值
      2. 非静态代码块赋值
      3. 构造器中赋值
  2. 修饰局部变量
    1. 系统不会为局部变量初始化,这句话的意思是
      1. 比如成员变量,在创建对象的时候会初始化属性
      2. 比如类变量,随着类的加载而初始化
      3. 都是系统做的初始化。
    2. final修饰的成员变量,可以在声明的时候初始化,也可以不初始化。
    3. 如果声明的时候没有初始化,后面的代码中可以对final的变量赋值,但是只能赋值一次。
  3. 修饰基本数据类型和引用数据类型
    1. 如果修饰的是基本数据类型,初始化后数值不能修改。
    2. 如果是引用数据类型,初始化后不能再指向其他对象,但是可以修改其属性。

为什么局部内部类只能访问局部final变量

  1. 编译后会生成两个class文件,因此内部类和外部类是同级的。
  2. 内部类不会因为定义在方法中就会随着方法的执行完毕被销毁。
  3. 当外部类的方法执行结束时,局部变量就销毁掉了。
  4. 但是,局部内部类对象可能还存在,比如内部类是在外部类方法新启动线程执行的。
  5. 这样就出现了一个问题,内部类引用了一个不存在的变量。
  6. 为了解决这个问题,就将外部类的局部变量复制了一份作为内部类的成员变量,这样当外部方法执行结束后,内部类还可以正常访问这个变量。延迟了局部变量的声明周期。
  7. 将局部变量复制为内部类成员变量时,必须保证是一样的。 如果不设置为final。内部类中如果修改了,外部类没有办法感知到。

hashCode和equals.

hashcode介绍

  1. hashcode的作用是获取对象的哈希码,也称为散列码。
  2. 实际上返回的是一个整数,作用是确定该对对象在hash表中的索引位置。
  3. Object的方法,任意对象都有hashcode方法,作用是能根据索引快速找到堆中的位置。