特点和特性

Java特点:跨平台、面向对象、安全性、多线程、简单易用、可维护性高。

特点 描述
跨平台 Java可以不受计算机的硬件和操作系统的限制,而独立于平台。因为Java中有自带的JVM,它执行经过javac命令编译完成的java源代码所生成的class文件转换成机器码语言在平台上操作。
面向对象 万物皆对象,Java以对象为基本粒度。对象中包含属性和方法,对象的说明用属性来表达,方法用来操作对象。这样可以对应用程序进行解耦,提高代码的可扩展性和重用性。
安全性 语言级安全性:Java的数据结构是完整的对象,这些封装过的数据类型具有安全性。
编译时安全性:编译时要进行Java语义和语法的检查,保证每个变量对应一个相应的值,编译后生成Java类。
运行时安全性:表示在运行Java类时要进行字节码校检器校检之后才可以运行。
可执行代码安全性:Java类在网络上使用时,对它的权限进行了设置,保证了被访问用户的安全性。
多线程 多线程是指允许一个应用程序同时存在两个或两个以上的线程,用于支持事务并发和多任务处理。
Java除了内置的多线程技术之外,还定义了一些类、方法等来建立和管理用户定义的多线程。
简单易用 就是指java源代码可以不用在特定环境下编写。
可维护性高

四大特性:继承、封装、多态、抽象。

特性 描述
继承 继承要有一定的层次结构,还要具备一定的可传递性;
子类只能继承父类非私有化的成员变量和方法;
实行就近原则,有局部变量优先使用局部变量,没有就使用子类成员变量,子类没有则使用父类成员变量。
封装 将抽象出来的属性和方法写在一个类中就是封装,将不需要对外提供的内容隐藏起来,提供公共的访问方式;
封装就是包装的过程,但封装不是绝对的封装,如果其他程序要获取已经封装好的数据,就要通过程序指定的接口或方法才能获取。
多态 多态是同一个行为具有多个不同表现形式或形态的能力;
多态就是同一个接口,使用不同的实例而执行不同操作;
多态性是对象多种表现形式的体现。
抽象 就是对同一类事物共有的属性(特征)和方法(功能/行为)进行抽取、归纳、总结;
抽象类不能实例化为一个对象,就比如水果是苹果,香蕉,梨等一类事物抽象出来的。

面向对象和面向过程

面向对象:指的是将问题分解成一个一个步骤,对每个步骤进行相应的抽象,形成对象,然后通过互相调用,解决组合问题;
也就是说在进行面向对象编程的时候,要把属性、行为等封装成对象,然后基于这些对象的能力进行业务逻辑的实现。

面向过程:指的是把问题分解成一个一个步骤,每个步骤用函数来实现,然后依次调用即可。

八大基本数据类型

Java 的两大数据类型:内置数据类型、引用数据类型。

类型 描述
内置数据类型 byte、short、int、long、float、double、boolean、char
引用数据类型 引用类型指向一个对象,指向对象的变量是引用变量
对象、数组都是引用数据类型,所有引用类型的默认值都是null

八大基本数据类型占用空间和范围:

类型 占用存储空间 表示范围
byte 1字节 -2^7 ~ 2^7 - 1(-128 ~ 127)
short 2字节 -2^15 ~ 2^15 - 1(-32768 ~ 32767)
int 4字节 -2^31 ~ 2^31 - 1(-2147483648 ~ 2147483647)
long 8字节 -2^63 ~ 2^63 - 1
float 4字节 -3.403E38 ~ 3.403E38
double 8字节 -1.798E308 ~ 1.798E308
boolean 1字节 true、false
char 2字节 0 ~ 65535

四大引用类型

从Java SE2开始,就提供了四种类型的引用:强引用、软引用、弱引用和虚引用。
Java中提供这四种引用类型主要有两个目的:
1、通过代码的方式决定某些对象的生命周期;
2、有利于JVM进行垃圾回收。

类别 回收机制 用途 生存时间
强引用 从不回收 对象状态 JVM停止运行时
软引用 内存不足时回收 缓存 内存不足
弱引用 对象不被引用时回收 缓存 GC运行后
虚引用 对象被回收时 管理控制精确内存稳定性 unknown

常见面试题锦集

equals方法和==的区别

  1. 对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
    如果作用于引用类型的变量,则比较的是所指向的对象的地址。

  2. 对于equals方法,注意:equals方法不能作用于基本数据类型的变量;
    如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
    诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。

String、StringBuilder和StringBuffer区别

  • String、StringBuffer是线程安全的,StringBuilder是非线程安全。
  • StringBuffer与StringBuilder的对象存储在堆中,String对象存储在Constant String Pool(字符串常量池)。
  • StringBuffer和StringBuilder是可变对象,String一旦创建无法修改,并且String是线程安全的。

为什么String不可变,不可变对象的好处

主要是为了安全。
不可变对象的好处主要也是保证了线程安全。

由于String广泛用于java类中的参数,所以安全是非常重要的考虑点。包括线程安全,打开文件,存储数据密码等等。
因为java字符串是不可变的,可以在java运行时节省大量java堆空间。因为不同的字符串变量可以引用池中的相同的字符串。如果字符串是可变得话,任何一个变量的值改变,就会反射到其他变量,那字符串池也就没有任何意义了。
String的不变性保证哈希码始终一,所以在用于HashMap等类的时候就不需要重新计算哈希码,提高效率。

final、finally、finalize区别

  1. final:修饰类,方法,变量(表示不可变)。
  2. finally:finally作为异常处理的一部分,它只能用在try/catch语句中,并且附带一个语句块,表示这段语句最终一定会被执行(不管有没有抛出异常),经常被用在需要释放资源的情况下。
  3. finalize:finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。

Exception和Error有什么区别

首先Exception和Error都是继承于Throwable 类,在 Java 中只有 Throwable 类型的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型。
Exception和Error体现了JAVA这门语言对于异常处理的两种方式。

  • Exception是java程序运行中可预料的异常情况,我们可以捕获到这种异常,并且对这种异常进行业务外的处理。
  • Error是java程序运行中不可预料的异常情况,这种异常发生以后,会直接导致JVM不可处理或者不可恢复的情况。所以这种异常不能被捕获到,比如OutOfMemoryError、NoClassDefFoundError等。

其中的Exception又分为检查性异常非检查性异常

  • 检查性异常必须在编写代码时,使用try catch捕获(比如:IOException异常)。
  • 非检查性异常在代码编写时,可以忽略捕获操作(比如:ArrayIndexOutOfBoundsException),这种异常是在代码编写或者使用过程中通过规范可以避免发生的。

RunTimeException和其他Exception区别?

其他Exception,受检查异常。可以理解为错误,必须要开发者解决以后才能编译通过,解决的方法有两种:throw到上层try-catch处理
RunTimeException:运行时异常,又称不受检查异常,不受检查!不受检查!!不受检查!!!
重要的事情说三遍,因为不受检查,所以在代码中可能会有RunTimeException时Java编译检查时不会告诉你有这个异常,但是在实际运行代码时则会暴露出来,比如经典的1/0,空指针等。如果不处理也会被Java自己处理。

泛型和类型擦除

泛型简单说就是能广泛适用的类型。
还有一种较为准确的说法就是为了参数化类型,就是可以将类型当作参数传递给一个类或者是方法。

  • 因为泛型可以使数据的类别像参数一样由外部传递进来,它提供了一种扩展能力,更符合抽象开发。
  • 当具体的类型确定后,泛型又提供了一种类型检测的机制,只有相匹配的数据才能正常的赋值,否则编译器就不通过。
  • 泛型提高了程序代码的可读性,不必要等到运行的时候才去强制转换。

泛型类中的类型参数与泛型方法中的类型参数是没有相应的联系的,泛型方法始终以自己定义的类型参数为准

通配符 ?

通配符的出现是为了指定泛型中的类型范围。

  • <?>被称作无限定的通配符,会被转译为Object类型。
  • <? extends T>被称作有上限的通配符,会被转译为T的类型。
  • <? super T>被称作有下限的通配符。

类型擦除

泛型信息只存在于代码编译期间,在编译器编译生成字节码后,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。

在泛型类被类型擦除的时候,之前泛型类中的类型参数部分如果没有指定上限,如 则会被转译成普通的 Object 类型,如果指定了上限如 则类型参数就被替换成类型上限。

泛型类或者泛型方法中,不接受8种基本数据类型如int、boolean等,而是需要使用它们的包装类Integer、Boolean等。

为什么会有类型擦除?

这是Java实现泛型的方式,也叫作伪泛型

Java的泛型在底层实现上使用了Object引用,编译器可以通过指定的泛型进行静态类型检查,在编译后又擦除为Object类型。
如果要实现真泛型的话,就需要修改JVM的源码,让虚拟机正确地读取和校验泛型信息,而之前的Java是没有这一概念的。
所以为了兼容旧程序,还需要为原本不支持泛型的API添加一套泛型API。

Java 泛型与类型擦除