Java 问题总结

一、基础

1、JDK 和 JRE 的区别

JRE(Java Runtime Environment)

  • Java 运行时环境。主要包括 Java 虚拟机和核心类库。
  • 应用场景:如果你不需要开发只需要运行Java程序,那么你可以安装JRE。例如程序员开发出的程序最终卖给了用户,用户不用开发,只需要运行程序,所以用户在电脑上安装JRE即可。

JDK(Java Development Kit)

Java 开发工具包,包含了 JRE 、编译器和其它工具,可以让开发者开发、编译、执行 Java 应用程序。

2、静态方法和实例方法的区别

对比项 静态 动态
绑定方式 编译时静态绑定 运行时动态绑定
对象数 整个进程中只有一份 在进程中可创建多个实例
调用方式 不用创建实例,可以通过类.方法名调用 必须实例化后才可调用
可重写性 不能被重写,因为它是编译时静态绑定的,而重写是基于运行时动态绑定的 非 private 的方法可重写

3、说一下大 O 表示法

语句执行次数是问题规模 n 的函数,记作 T(n) = O(f(n)) 。
一般用来描述时间复杂度和空间复杂度。

4、Exception 和 Error 的区别

Exception

程序本身可以处理的异常。这些是可以预料的一些异常,应该被捕获或处理。
例:NullPointerException、ClassCastException

Error

程序本身不可处理的异常。
例:内存溢出。

5、Lamada 函数

Lamada 函数是一种匿名函数,优点是轻量、简捷。

二、数据类型

三、面向对象

1、Java 是否支持多继承

这个要从不同的角度区分:

  • 类:只支持单继承
  • 接口:支持多继承

2、接口和抽象类的区别

对比项 抽象类 接口
继承性 单继承性 多实现
方法类型 可以有抽象方法和非抽象方法 只能有抽象方法
实现方法 非抽象方法可以不实现 必须实现接口中的所有方法
权限 函数也可以是 private 和 protected 函数都是 public 的
包含对象 可包含非 final 的对象 申明的变量都是 final 的

3、绑定 ? 静态绑定? 动态绑定 ?

  • 绑定:把一个方法与其所在的类/对象关联起来叫做方法的绑定。
  • 静态绑定:在编译的时候就已经知道方法是属于那个类的。
  • 动态绑定:在程序运行过程中,才能具体确定哪个方法属于哪个类。

四、泛型

五、集合框架

1、集合类框架的基本接口有哪些

  • Collection:代表一组对象,每一个对象都是它的子元素。
  • Set:不包含重复元素的Collection。
  • List:有顺序的collection,并且可以包含重复元素。
  • Map:可以把键(key)映射到值(value)的对象,键不能重复。

2、hashCode()和equals()方法的作用

  1. 确定索引:Java中的HashMap使用这两个方法来确定键值对的索引和取值
  2. 重复:如果没有正确的实现这两个方法,两个不同的键可能会有相同的hash值,因此,可能会被集合认为是相等的。

3、数组(Array)和列表(ArrayList)有什么区别?

区别:

  • 存什么的:Array 可以包含基本类型和对象类型,ArrayList 只能包含对象类型。
  • 大小:Array 大小是固定的,ArrayList 的大小是动态变化的。
  • ArrayList 提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。

使用场景:
对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。

4、ArrayList 和 LinkedList 的区别

  • 速度:ArrayList 查询快,增删慢;LinkedList 增删快,查询慢。
  • 存储:LinkedList 更占内存,因为它不仅存储了元素内容,还多存储2个引用。

六、多线程

1、进程和线程的区别

对比项 进程 线程
作用 资源分配的最小单位 程序执行的最小单位
资源 进程间相互独立 同一进程不同线程间相互共享
健壮性 一个进程死掉不会影响其它线程 一个线程死掉会影响整个进程

2、创建线程的几种方法

  1. 继承 Thread 类
  2. 实现 Runnable 接口
  3. Executor 创建线程池
  4. 实现 Callable 接口

3、线程的几种状态

  • 新创建:创建了一个线程对象。
  • 可运行:已经调用 start 方法,正在等待 CPU 的时间片。
  • 运行:获得了 CPU 的时间片,并且正在运行。
  • 阻塞:线程因为某种原因让出了 CPU 使用权。
  • 死亡:线程执行完了 run() 或 main() 方法。

4、什么情况会引起线程阻塞

  1. 等待阻塞:运行的线程执行了 wait 、join、sleep 方法。
  2. 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则 JVM 会把该线程放入锁池。
  3. IO操作:发出了 IO 请求时, JVM 会把该线程置为阻塞状态。

5、sleep、wait、join的区别

  • sleep:不释放锁让出 CPU
  • wait:释放锁让出 CPU
  • join:调用线程先阻塞,等待被调用线程释放后才执行

6、线程锁

什么是线程锁?

多线程可以同时运行多个任务,但是当多个线程同时访问共享数据时,可能导致数据不同步,甚至错误!
线程锁主要用来给方法、代码块加锁。当某个方法或者代码块使用锁时,那么在同一时刻至多仅有有一个线程在执行该段代码。

哪些可以作为线程锁?

可作为线程锁的有对象锁和类锁,对象锁是用来修饰实例方法的,类锁是用来修饰静态方法的。

对象锁:多个线程调用同一个对象的同步方法会阻塞,调用不同对象的同步方法不会阻塞。

public synchronized void obj3() {}

public void obj2() {
       synchronized (this) {}
}

public void obj2() {
       String str=new String("lock");
       //在方法体内,调用一次就实例化一次,多线程访问不会阻塞,因为不是同一个对象,锁是不同的
       synchronized (str) {}
       }
   }

类锁:

public static synchronized void obj3() {}

public void obj1() {
        synchronized (test.class) {}
}

类锁和对象锁同时存在时,多线程访问时不会阻塞,因为他们不是一个锁。

死锁

当两个线程都持有对方所需要的资源,并且同时等待对方的资源时就会造成死锁。举例:夫妻吵架,都待着对方先道歉,就会造成死锁。

7、volatile 关键字

L1

  • 可见性:被 volatile 修饰的变量被改变后其它线程立马可见,避免出现脏读的现象。
  • 有序性:防止指令重排序。

为什么会出现脏读?
Java内存模型规定所有的变量都是存在主存当中,每个线程都有自己的工作内存。线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作。并且每个线程不能访问其他线程的工作内存。变量的值何时从线程的工作内存写回主存,无法确定。

L2

计算机在执行程序时,每条指令都是在CPU中执行的,而程序运行过程中的临时数据是存放在主存(物理内存)当中的。

执行指令过程中,势必涉及到数据的读取和写入。这时就存在一个问题,由于CPU执行速度很快,而从内存读取数据和向内存写入数据的过程跟CPU执行指令的速度比起来要慢的多,因此如果任何时候对数据的操作都要通过和内存的交互来进行,会大大降低指令执行的速度。因此在CPU里面就有了高速缓存。

当程序在运行过程中,会将运算需要的数据从主存复制一份到CPU的高速缓存当中,那么CPU进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据,当运算结束之后,再将高速缓存中的数据刷新到主存当中。

那这样就会有问题了:

i = i + 1;

假如初始值为 0,两个线程都操作主存中的变量 i,我们希望执行两次加法后 i 的值为 2,实际情况会如我们预期吗?

可能存在下面一种情况:初始时,两个线程分别读取 i 的值存入各自所在的 CPU 的高速缓存当中,然后线程 1 进行加 1 操作,然后把 i 的最新值 1 写入到内存。此时线程 2 的高速缓存当中i的值还是 0,进行加 1 操作之后,i 的值为 1,然后线程 2 把 i 的值写入内存,最终结果 i 的值是1。

解决这样的问题有两种方案:

  1. 总线加锁:synchronized
  2. 一致性协议:volatile

由于在锁住总线期间,其他CPU无法访问内存,导致效率低下。所以就有了缓存一致性协议。

MESI 协议保证了每个缓存中使用的共享变量的副本是一致的。它核心的思想是:当 CPU 写数据时,如果发现操作的变量是共享变量,会发出信号通知其他 CPU 将该变量的缓存置为无效状态,因此当其他CPU 需要读取这个变量时,发现自己缓存中该变量是无效的,那么它就会从内存重新读取。

七、底层原理

1、Java虚拟机原理

L1:

我们平常写的代码放在.java文件中,通过javac会将其编译成.class字节文件,执行的时候会将这些字节class文件载入内存并转化为机器码执行。

L2:

Java的类加载器将.class文件载入内存,并分配给RuntimeDataArea,执行引擎会解释或编译这些类文件,转化成特定CPU机器码,CPU执行机器码,到此结束整个过程。

L3:

类加载器分为4种:Bootstrap、Extention、System、UserDefined,它们分别加载系统基本API、安全性能相关、应用程序中的类(也就是classpath中配置的)、开发人员自定义一些程序需要加载的类。

运行时区域:
堆内存:存放对象实例。
方法区:被虚拟机加载的类信息、常量、变量、方法。
运行时常量池:是方法区的一部分,存放程序中使用的各种常量。

以上这些是被线程所共享的。
而另外一部分就是线程,而每个线程中又包括了:虚拟机栈、程序计数器、本地方法栈。
虚拟机栈:作用是存放一系列栈帧,执行一个方法时入栈,结束时出栈。
程序计数器:每个线程启动时会创建一个程序计数器,它用来存放当前正在被执行的字节码指令的地址。
本地方法栈:与虚拟机栈类似,但它是用来执行native方法。

执行引擎:
Java的字节码,并不能被机器识别,如果想要被机器运行还要转换为机器码,而类执行引擎就是来完成这一步的,可以由其字节码解释器来转换,也可由即时编译器来转换。

2、JVM垃圾回收算法

  1. 引用计数(Reference Counting) 比较古老的回收算法。原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只用收集计数为0的对象。此算法最致命的是无法处理循环引用的问题。

  2. 标记-清除(Mark-Sweep) 此算法执行分两阶段。第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。此算法需要暂停整个应用,同时,会产生内存碎片。

  3. 复制(Copying) 此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现“碎片”问题。当然,此算法的缺点也是很明显的,就是需要两倍内存空间。

  4. 标记-整理(Mark-Compact) 此算法结合了 “标记-清除”和“复制”两个算法的优点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且把存活对象 “压缩”到堆的其中一块,按顺序排放。此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。

  5. 增量收集(Incremental Collecting) 实施垃圾回收算法,即:在应用进行的同时进行垃圾回收。

  6. 分代(Generational Collecting) 基于对对象生命周期分析后得出的垃圾回收算法。把对象分为年青代、年老代、持久代,对不同生命周期的对象使用不同的算法(上述方式中的一个)进行回收。现在的垃圾回收器(从J2SE1.2开始)都是使用此算法的。

待总结

参考:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352