Java语言有哪些特点?
- 面向对象(封装,继承,多态);
- 平台无关性,平台无关性的具体表现在于,Java 是“一次编写,到处运行(Write Once,Run any Where)”的语言,因此采用 Java 语言编写的程序具有很好的可移植性,而保证这一点的正是 Java 的虚拟机机制。在引入虚拟机之后,Java 语言在不同的平台上运行不需要重新编译。
- 可靠性、安全性;
- 支持多线程。C++ 语言没有内置的多线程机制,因此必须调用操作系统的多线程功能来进行多线程程序设计,而 Java 语言却提供了多线程支持;
- 支持网络编程并且很方便。Java 语言诞生本身就是为简化网络编程设计的,因此 Java 语言不仅支持网络编程而且很方便;
- 编译与解释并存;
Java和C++有什么关系,他们有什么区别?
- 都是面向对象的语言,都支持封装、继承和多态;
- C++ 支持指针,而 Java 没有指针的概念;
- C++ 支持多继承,而 Java 不支持多重继承,但允许一个类实现多个接口;
- Java 是完全面向对象的语言,并且还取消了 C/C++ 中的结构和联合,使编译程序更加简洁;
- Java 自动进行无用内存回收操作,不再需要程序员进行手动删除,而 C++ 中必须由程序释放内存资源,这就增加了程序员的负担。
- Java 不支持操作符重载,操作符重载则被认为是 C++ 的突出特征;
- Java 允许预处理,但不支持预处理器功能,所以为了实现预处理,它提供了引入语句(import),但它与 C++ 预处理器的功能类似;
- Java 不支持缺省参数函数,而 C++ 支持;
- C 和 C++ 不支持字符串变量,在 C 和 C++ 程序中使用“Null”终止符代表字符串的结束。在 Java 中字符串是用类对象(String 和 StringBuffer)来实现的;
- goto 语句是 C 和 C++ 的“遗物”,Java 不提供 goto 语句,虽然 Java 指定 goto 作为关键字,但不支持它的使用,这使程序更简洁易读;
- Java 不支持 C++ 中的自动强制类型转换,如果需要,必须由程序显式进行强制类型转换。
Java语言和C语言有哪些区别?
Java语言属于面向对象语言的代表,在构建复杂业务逻辑方面具有一定的优势,而C语言则是面向过程编程语言的代表
- 应用场景不同:Java语言属于“全场景”编程语言之一,可以应用于Web开发、Android开发、大数据开发等场景,而C语言的应用场景相对比较集中,主要用于操作系统、嵌入式开发等领域
- 技术体系不同:Java是面向对象编程语言,在技术体系的设计上更注重移植性、安全性和可扩展性
- 发展道路不同:Java语言的发展道路主要体现三个特点,第一跨平台,第二是资源整合能力强,第三是并发处理能力强
JVM、JRE和JDK的关系是什么?
JDK是(Java Development Kit)的缩写,它是功能齐全的 Java SDK。它拥有 JRE 所拥有的一切,还有编译器(javac)和工具(如 javadoc 和 jdb)。它能够创建和编译程序。
JRE是Java Runtime Environment缩写,它是运行已编译 Java 程序所需的所有内容的集合,包括 Java 虚拟机(JVM),Java 类库,java 命令和其他的一些基础构件。但是,它不能用于创建新程序。
JDK包含JRE,JRE包含JVM。
什么是字节码?
Java之所以可以“一次编译,到处运行”,一是因为JVM针对各种操作系统、平台都进行了定制,二是因为无论在什么平台,都可以编译生成固定格式的字节码(.class文件)供JVM使用。因此,也可以看出字节码对于Java生态的重要性。
之所以被称之为字节码,是因为字节码文件由十六进制值组成,而JVM以两个十六进制值为一组,即以字节为单位进行读取。在Java中一般是用javac命令编译源代码为字节码文件,一个.java文件从编译到运行的示例如图所示。
采用字节码的好处是什么?
Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。
面向对象的三大特性及定义?
封装、继承、多态
- 封装:把一个对象属性私有化,同时提供一些可以被外界访问属性的方法
- 继承:用来复用一些代码,同时也可以进行扩展
- 多态:不同类的对象对同一信息作出不同的响应
多态的好处?
允许不同类对象对同一信息做出响应,即同一信息可以根据发送对象的不同而采用多种不同的行为方式,主要有以下优点:
- 可替代性:多态对已存在代码具有可替代性
- 可扩充性:增加新的子类不影响已经存在的类结构
- 接口性:多态是超类通过方法签名,向子类提供一个公共接口,由子类来完善或者重写它来实现的
- 灵活性
- 简化性
Java创建对象有哪几种方式?
java中提供了四种创建对象的方式
- 用new语句创建对象
- 通过反射机制,采用Class.newInstance()创建对象
- 调用对象的clone()方法
- 利用反序列化的手段,调用java.io.ObjectInputStream对象的readObject()方法
Object中有哪些公共方法?如何使用?
equals(),clone(),getClass(),notify(),notifyAll(),wait(),toString
- equals():直接判断this和obj本身的值是否相等,即用来判断调用equals的对象和形参obj所引用的对象是否是同一对象,所谓同一对象就是指内存中同一块存储单元,如果this和obj指向的是同一块内存对象,则返回true,如果this和obj指向的不是同一块内存,则返回false,注意:即使内容完全相等的两块不同的内存对象,也返回false
public boolean equals(Object obj)
{
return this == obj;
}
- clone():java赋值是复制对象引用,clone()实现了对象对属性的复制,但是它的可见范围是projected的,所以实体类使用克隆的前提是: ① 实现Cloneable接口,这是一个标记接口,自身没有方法 ② 覆盖clone()方法,可见性提升为public
- getClass():获取对象的运行时对象的类
- notify():用来唤醒一个在此对象监视器上等待的线程
- notifyAll():通知所有等待此对象的线程,开始执行
- wait():让拥有object对象的锁的线程进入等待状态,并释放对象锁
- toString():返回表示当前对象的字符串。
equals 与 == 的区别?
-
==是判断两个变量或实例是不是指向同一个内存空间
-
equals是判断两个变量或实例所指向的内存空间的值是不是相同
接口和抽象类有哪些区别?
-
从语法层面来讲,抽象类可以有方法实现,而接口中的方法只能是抽象方法,抽象类中的成员变量可以是多种类型,而接口中的成员变量只能是public、static、final类型,接口中不能含有静态代码块及静态方法,而抽象类可以有静态代码块和静态方法,一个类只能继承于一个抽象类,而一个类却可以实现多个接口。
-
从设计层面来看,两者抽象的层次不同,抽象类是对整个类整体的进行抽象,包括属性、行为,但是接口只是对类行为进行抽象,继承抽象类是一种“是不是”的关系,而接口实现是一种“有没有”的关系,如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是具备不具备的关系,比如鸟能否起飞
Java的引用类型,即四大引用?
- 强引用(StrongReference)我们使用的大部分引用实际上都是强引用,这是使用最普遍的引用,如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它,当内存空间不足时,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题
- 软引用(SoftReference)如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足,就会回收这些对象的内存,只要垃圾回收器没有回收它,该对象就可以被程序使用
- 弱引用(WeakReference)在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前空间足够与否,都会回收它的内存,不过,由于垃圾回收器是一个优先级很低的线程,因此不一定很快发现那些只具有弱引用的对象、弱引用可以和一个引用队列(Reference)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中去
- 虚引用(PhantomReference)如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收,虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列联合使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中,程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收,程序如果发现某个虚引用已经加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动
四大引用在程序中是如何使用的?
- 强引用是使用最普遍的引用,平常我们随意的一个new对象就是一个强引用如:
Object strongReference = new Object();
- 软引用可用来实现内存敏感的高速缓存
//强引用
String strongReference = new String("abc");
//软引用
String str = new String("abc");
SoftReference<String> softReference = new SoftReference<String>(str);
通过代码可以看出软引用使用SoftReference来实现 软引用可以和引用队列(Reference)联合使用,如果软引用所引用对象被垃圾回收,JAVA虚拟机就会把这个软引用加入到与之关联的引用队列中
ReferenceQueue<String> referenceQueue = new ReferenceQueue<>();
String str = new String("abc");
SoftReference<String> softReference = new SoftReference<>(str, referenceQueue);
str = null;
// Notify GC
System.gc();
System.out.println(softReference.get()); // abc
Reference<? extends String> reference = referenceQueue.poll();
System.out.println(reference); //null
- 弱引用和软引用的区别不大,只是弱引用的对象拥有更短暂的生命周期 由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象
String str = new String("abc");
WeakReference<String> weakReference = new WeakReference<>(str);
str = null;
JVM首先将弱引用的对象引用置为null,然后通知垃圾回收器进行回收
str = null;
System.gc();
- 虚引用作用不大,并不会决定对象的生命周期,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。主要用来跟踪对象被垃圾回收器回收的活动。 虚引用必须和引用队列(Reference)联合使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
String str = new String(“abc”);
ReferenceQueue queue = new ReferenceQueue();
//创建虚引用,要求必须与一个引用队列关联
PhantomReference pr = PhantomReference(str,queue);
内存不足时,软引用是怎么回收内存的呢?
当内存不足时,JVM首先将软引用中的对象引用置为null,然后通知垃圾回收器进行回收:
if(JVM内存不足){
//将软引用的对象引用置为null
str = null;
//通知垃圾回收器进行回收
System.gc();
}
也就是说垃圾收集线程会在虚拟机抛出OutOfMemoryError之前回收软引用对象,而且虚拟机会尽可能优先回收长时间闲置不用的软引用对象
说一个你知道的软引用的一个应用场景
比如说web开发时,浏览器的后退按钮,按后退时,这个后退时显示的网页内容是重新进行请求还是从缓存中取出就需要考虑一下具体的实现策略
- 如果一个网页在浏览结束时就进行内容的回收,则按后退查看前面浏览过的页面时,需要重新构建
- 如果将浏览过的网页存储到内存中会造成内存的大量浪费,甚至会造成内存溢出
这个时候就可以使用软引用,很好的解决实际问题
// 获取浏览器对象进行浏览
Browser browser = new Browser();
// 从后台程序加载浏览页面
BrowserPage page = browser.getPage();
// 将浏览完毕的页面置为软引用
SoftReference softReference = new SoftReference(page);
// 回退或者再次浏览此页面时
if(softReference.get() != null) {
// 内存充足,还没有被回收器回收,直接获取缓存
page = softReference.get();
} else {
// 内存不足,软引用的对象已经回收
page = browser.getPage();
// 重新构建软引用
softReference = new SoftReference(page);
}