• 近期将进行后台系统升级,如有访问不畅,请稍后再试!
  • 极客文库-知识库上线!
  • 极客文库小编@勤劳的小蚂蚁,为您推荐每日资讯,欢迎关注!
  • 每日更新优质编程文章!
  • 更多功能模块开发中。。。

Java常考面试题总结(一)

文章目录[隐藏]

什么是 Java 虚拟机?为什么 Java 被称作是“平台无关的编程语言”?

Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程。

Java 源文件被编译成能被 Java 虚拟机执行的字节码文件。

Java 被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。

Java 虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。


java 的跨平台不是 java 源程序的跨平台 ,如果是这样,那么所以语言都是跨平台的, java 源程序先经过 javac 编译器编译成二进制的.class 字节码文件(java 的跨平台指的就是.class 字节码文件的跨平台,.class 字节码文件是与平台无关的),.class 文件再运行在 jvm 上,java 解释器(jvm 的一部分)会将其解释成对应平台的机器码执行,所以 java 所谓的跨平台就是在不同平台上安装了不同的 jvm,而在不同平台上生成的.class 文件都是一样的,而.class 文件再由对应平台的 jvm 解释成对应平台的机器码执行。

最后解释下机器码和字节码的区别: 一,机器码,完全依附硬件而存在~并且不同硬件由于内嵌指令集不同,即使相同的 0 1 代码 意思也可能是不同的~换句话说,根本不存在跨平台性~比如~不同型号的 CPU,你给他个指令 10001101,他们可能会解析为不同的结果~ 二,我们知道 JAVA 是跨平台的,为什么呢?因为他有一个 jvm,不论哪种硬件,只要你装有 jvm,那么他就认识这个 JAVA 字节码~~~~至于底层的机器码,咱不用管,有 jvm 搞定,他会把字节码再翻译成所在机器认识的机器码~~~

JDK 和 JRE 的区别是什么?

Java 运行时环境(JRE)。

它包括 Java 虚拟机、Java 核心类库和支持文件。

它不包含开发工具(JDK)–编译器、调试器和其他工具。

Java 开发工具包(JDK)是完整的 Java 软件开发包,包含了 JRE,编译器和其他的工具(比如:JavaDoc,Java 调试器),可以让开发者开发、编译、执行 Java 应用程序。

”static”关键字是什么意思?Java 中是否可以覆盖(override)一个 private 或者是 static 的方法?

Static 表示静态的意思,可用于修饰成员变量和成员函数,被静态修饰的成员函数只能访问静态成员,不可以访问非静态成员。

静态是随着类的加载而加载的,因此可以直接用类进行访问。

重写是子类中的方法和子类继承的父类中的方法一样(函数名,参数,参数类型,反回值类型),但是子类中的访问权限要不低于父类中的访问权限。

重写的前提是必须要继承,private 修饰不支持继承,因此被私有的方法不可以被重写。

静态方法形式上可以被重写,即子类中可以重写父类中静态的方法。

但是实际上从内存的角度上静态方法不可以被重写。

是否可以在 static 环境中访问非 static 变量?

static 变量在 Java 中是属于类的,它在所有的实例中的值是一样的。

当类被 Java 虚拟机载入的时候,会对 static 变量进行初始化。

如果你的代码尝试不用实例来访问非 static 的变量,编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上。

Java 支持的数据类型有哪些?什么是自动拆装箱?

Java 语言支持的 8 种基本数据类型是:byte、short、int、long、float、double、boolean、char

自动装箱是 Java 编译器在基本数据类型和对应的对象包装类型之间做的一个转化。

比如:把 int 转化成 Integer,double 转化成 Double,等等。反之就是自动拆箱。

Java 支持的数据类型包括两种:

一种是基本数据类型,包含 byte,char,short, boolean ,int , long,float,double;

另一种是引用类型:如 String 等,

其实是对象的引用,JVM 中虚拟栈中存的是对象的地址,创建的对象实质在堆中,通过地址来找到堆中的对象的过程,即为引用类型。

自动装箱就是 Java 编译器在基本数据类型和对应的对象包装类型间的转化,即 int 转化为 Integer,自动拆箱是 Integer 调用其方法将其转化为 int 的过程

Java 中的方法覆盖(Overriding)和方法重载(Overloading)是什么意思?

Java 中的方法重载发生在同一个类里面两个或者是多个方法的方法名相同但是参数不同的情况。

与此相对,方法覆盖是说子类重新定义了父类的方法。

方法覆盖必须有相同的方法名,参数列表和返回类型。

覆盖者可能不会限制它所覆盖的方法的访问。

Java 中,什么是构造方法?什么是构造方法重载?什么是复制构造方法?

当新对象被创建的时候,构造方法会被调用。每一个类都有构造方法。

在程序员没有给类提供构造方法的情况下,Java 编译器会为这个类创建一个默认的构造方法。

Java 中构造方法重载和方法重载很相似。

可以为一个类创建多个构造方法。

每一个构造方法必须有它自己唯一的参数列表。

Java 不支持像 C++中那样的复制构造方法,这个不同点是因为如果你不自己写构造方法的情况下,Java 不会创建默认的复制构造方法。

Java 支持多继承么?

Java 中类不支持多继承,只支持单继承(即一个类只有一个父类)。

但是 java 中的接口支持多继承,,即一个子接口可以有多个父接口。

(接口的作用是用来扩展对象的功能,一个子接口继承多个父接口,说明子接口扩展了多个功能,当类实现接口时,类就扩展了相应的功能)。

接口和抽象类的区别是什么?

从设计层面来说,抽象是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。

Java 提供和支持创建抽象类和接口。

它们的实现有共同点,不同点在于:

接口中所有的方法隐含的都是抽象的。

而抽象类则可以同时包含抽象和非抽象的方法。

类可以实现很多个接口,但是只能继承一个抽象类

类可以不实现抽象类和接口声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。

抽象类可以在不提供接口方法实现的情况下实现接口。

Java 接口中声明的变量默认都是 final 的。抽象类可以包含非 final 的变量。

Java 接口中的成员函数默认是 public 的。抽象类的成员函数可以是 private,protected 或者是 public。

接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含 main 方法的话是可以被调用的。

也可以参考 JDK8 中抽象类和接口的区别

什么是值传递和引用传递?

值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。

引用传递一般是对于对象型变量而言的,传递的是该对象地址的一个副本, 并不是原对象本身 。

一般认为,java 内的传递都是值传递, java 中实例对象的传递是引用传递。

进程和线程的区别是什么?

进程是执行着的应用程序,而线程是进程内部的一个执行序列。

一个进程可以有多个线程。线程又叫做轻量级进程。

线程的划分小于进程,线程隶属于某个进程。

进程是程序的一种动态形式,是 CPU、内存等资源占用的基本单位,而线程是不能占有这些资源的。

进程之间相互独立,通信比较困难,而线程之间共享一块内存区域,通信比较方便。

进程在执行的过程中,包含比较固定的入口,执行顺序,出口,而线程的这些过程会被应用程序所控制。

创建线程有几种不同的方式?你喜欢哪一种?为什么?

①继承 Thread 类(真正意义上的线程类),是 Runnable 接口的实现。

②实现 Runnable 接口,并重写里面的 run 方法。

③使用 Executor 框架创建线程池。Executor 框架是 juc 里提供的线程池的实现。

调用线程的 start():启动此线程;调用相应的 run()方法

继承于 Thread 类的线程类,可以直接调用 start 方法启动线程(使用 static 也可以实现资源共享).一个线程(对象)只能够执行一次 start(),而且不能通过 Thread 实现类对象的 run()去启动一个线程。

实现 Runnable 接口的类需要再次用 Thread 类包装后才能调用 start 方法。(三个 Thread 对象包装一个类对象,就实现了资源共享)。

线程的使用的话,注意锁和同步的使用。(多线程访问共享资源容易出现线程安全问题)

一般情况下,常见的是第二种。

* Runnable 接口有如下好处:

*①避免点继承的局限,一个类可以继承多个接口。

*②适合于资源的共享

/*

* Thread 的常用方法:

* 1.start():启动线程并执行相应的 run()方法

* 2.run():子线程要执行的代码放入 run()方法中

* 3.currentThread():静态的,调取当前的线程

* 4.getName():获取此线程的名字

* 5.setName():设置此线程的名字

* 6.yield():调用此方法的线程释放当前 CPU 的执行权(很可能自己再次抢到资源)

* 7.join():在 A 线程中调用 B 线程的 join()方法,表示:当执行到此方法,A 线程停止执行,直至 B 线程执行完毕,

* A 线程再接着 join()之后的代码执行

* 8.isAlive():判断当前线程是否还存活

* 9.sleep(long l):显式的让当前线程睡眠 l 毫秒 (只能捕获异常,因为父类 run 方法没有抛异常)

* 10.线程通信(方法在 Object 类中):wait() notify() notifyAll()

*

*设置线程的优先级(非绝对,只是相对几率大些)

* getPriority():返回线程优先值

* setPriority(int newPriority):改变线程的优先级

*/

概括的解释下线程的几种可用状态。

1. 新建( new ):新创建了一个线程对象。

2. 可运行( runnable ):线程对象创建后,其他线程(比如 main 线程)调用了该对象 的 start ()方法。

该状态的线程位于可运行线程池中,等待被线程调度选中,获 取 cpu 的使用权 。

3. 运行( running ):可运行状态( runnable )的线程获得了 cpu 时间片( timeslice ) ,执行程序代码。

4. 阻塞( block ):阻塞状态是指线程因为某种原因放弃了 cpu 使用权,也即让出了 cpu timeslice ,暂时停止运行。

直到线程进入可运行( runnable )状态,才有 机会再次获得 cpu timeslice 转到运行( running )状态。

阻塞的情况分三种:

(一). 等待阻塞:运行( running )的线程执行 o . wait ()方法, JVM 会把该线程放 入等待队列( waitting queue )中。

(二). 同步阻塞:运行( running )的线程在获取对象的同步锁时,若该同步锁 被别的线程占用,则 JVM 会把该线程放入锁池( lock pool )中。

(三). 其他阻塞: 运行( running )的线程执行 Thread . sleep ( long ms )或 t . join ()方法,或者发出了 I / O 请求时, JVM 会把该线程置为阻塞状态。当 sleep ()状态超时、 join ()等待线程终止或者超时、或者 I / O 处理完毕时,线程重新转入可运行( runnable )状态。

5. 死亡( dead ):线程 run ()、 main () 方法执行结束,或者因异常退出了 run ()方法,则该线程结束生命周期。死亡的线程不可再次复生。

同步方法和同步代码块的区别是什么?

区别:

同步方法默认用 this 或者当前类 class 对象作为锁;

同步代码块可以选择以什么来加锁,比同步方法要更细颗粒度,我们可以选择只同步会发生同步问题的部分代码而不是整个方法;

同步方法使用关键字 synchronized 修饰方法,而同步代码块主要是修饰需要进行同步的代码,用 synchronized(object){代码内容}进行修饰;

在监视器(Monitor)内部,是如何做线程同步的?程序应该做哪种级别的同步?

监视器和锁在 Java 虚拟机中是一块使用的。

监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。

每一个监视器都和一个对象引用相关联。

线程在获取锁之前不允许执行同步代码。

什么是死锁(deadlock)?

死锁 :是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去

(1) 因为系统资源不足。

(2) 进程运行推进顺序不合适。

(3) 资源分配不当等。

如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则
就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。

(1) 互斥条件:一个资源每次只能被一个进程使用。

(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之
一不满足,就不会发生死锁。

死锁的解除与预防:

理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和
解除死锁。

所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确
定资源的合理分配算法,避免进程永久占据系统资源。

此外,也要防止进程在处于等待状态的情况下占用资源。

因此,对资源的分配要给予合理的规划。

如何确保 N 个线程可以访问 N 个资源同时又不导致死锁?

使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。

因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。

多线程产生死锁的四个必要条件:

互斥条件:一个资源每次只能被一个进程使用。
保持和请求条件:一个进程因请求资源而阻塞时,对已获得资源保持不放。
不可剥夺调教:进程已获得资源,在未使用完成前,不能被剥夺。
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

只要破坏其中任意一个条件,就可以避免死锁,其中最简单的就是破环循环等待条件。按同一顺序访问对象,加载锁,释放锁。

Java 集合类框架的基本接口有哪些?

集合类接口指定了一组叫做元素的对象。

集合类接口的每一种具体的实现类都可以选择以它自己的方式对元素进行保存和排序。

有的集合类允许重复的键,有些不允许。

Java 集合类提供了一套设计良好的支持对一组对象进行操作的接口和类。

Java 集合类里面最基本的接口有:

Collection:代表一组对象,每一个对象都是它的子元素。

Set:不包含重复元素的 Collection。

List:有顺序的 collection,并且可以包含重复元素。

Map:可以把键(key)映射到值(value)的对象,键不能重复。

为什么集合类没有实现 Cloneable 和 Serializable 接口?

克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。

因此,应该由集合类的具体实现来决定如何被克隆或者是序列化。

什么是迭代器(Iterator)?

Iterator 接口提供了很多对集合元素进行迭代的方法。

每一个集合类都包含了可以返回迭代器实例的迭代方法。

迭代器可以在迭代的过程中删除底层集合的元素,但是不可以直接调用集合的 remove(Object Obj)删除,可以通过迭代器的 remove()方法删除。


丨极客文库, 版权所有丨如未注明 , 均为原创丨
本网站采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行授权
转载请注明原文链接:Java 常考面试题总结(一)
喜欢 (0)
[247507792@qq.com]
分享 (0)

欢迎 注册账号 登录 发表评论!

  • 精品技术教程
  • 编程资源分享
  • 问答交流社区
  • 极客文库知识库

客服QQ


QQ:2248886839


工作时间:09:00-23:00