java语言具有哪些特点?

  • Java 为纯面向对象的语言。它能够直接反应现实生活中的对象。
  • 具有平台无关性。Java 利用 Java 虚拟机运行字节码,无论是在 Windows、Linux 还是 MacOS 等其它平台对 Java 程序进行编译,编译后的程序可在其它平台运行。
  • Java 为解释型语言,编译器把 Java 代码编译成平台无关的中间代码,然后在 JVM 上解释运行,具有很好的可移植性。
  • Java 提供了很多内置类库。如对多线程支持,对网络通信支持,最重要的一点是提供了垃圾回收器。
  • Java 具有较好的安全性和健壮性。Java 提供了异常处理和垃圾回收机制,去除了 C++中难以理解的指针特性。

JDK、JRE、JVM三者区别?

  • JDK:Java 开发工具包(Java Development Kit),提供了 Java 的开发环境和运行环境,包含JRE
  • JRE:Java 运行环境(Java Runtime Environment),提供了 Java 运行所需的环境。包含JVM
  • JVM:Java虚拟机

简述java基本数据类型

  • byte: 占用 1 个字节,取值范围-128 ~ 127
  • short: 占用 2 个字节,取值范围-215 ~ 215-1
  • int:占用 4 个字节,取值范围-231 ~ 231-1
  • long:占用 8 个字节
  • float:占用 4 个字节
  • double:占用 8 个字节
  • char: 占用 2 个字节
  • boolean:占用大小根据实现虚拟机不同有所差异

简述自动装箱与拆箱

对于 Java 基本数据类型,均对应一个包装类。

装箱:就是自动将基本数据类型转换为包装器类型,如 int->Integer

拆箱:就是自动将包装器类型转换为基本数据类型,如 Integer->int

构造方法,成员变量初始化以及静态成员 变量三者的初始化顺序?

先后顺序:静态成员变量、成员变量、构造方法。

详细的先后顺序:父类静态变量、父类静态代码块、子类静态变量、子类静态代码块、父类非静态变量、父类非静态代码块、父类构造函数、子类非静态变量、子类非静态代码块、子类构造函数

java代码块执行顺序

  • 父类静态代码块(只执行一次)
  • 子类静态代码块(只执行一次)
  • 父类构造代码块
  • 父类构造函数
  • 子类构造代码块
  • 子类构造函数
  • 普通代码块

面向对象的三大特性

继承:对象的一个新类可以从现有的类中派生,派生类可以从它的基类那继承方法和实例变量,且派生类可以修改或新增新的方法使之更适合特殊的需求。

封装:将客观事物抽象成类,每个类可以把自身数据和方法只让可信的类或对象操作,对不可信的进行信息隐藏。

多态:允许不同类的对象对同一消息作出响应。不同对象调用相同方法即使参数也相同,最终表现行为是不一样的。

为什么java语言不支持多重继承?

为了程序的结构能够更加清晰从而便于维护。假设 Java 语言支持多重继承,类 C 继承自类 A 和类 B,如果类 A 和 B 都有自定义的成员方法 f(),那么当代码中调用类 C 的 f() 会产生二义性。

Java 语言通过实现多个接口间接支持多重继承,接口由于只包含方法定义,不能有方法的实现,类 C 继承接口 A 与接口 B 时即使它们都有方法f(),也不能直接调用方法,需实现具体的f()方法才能调用,不会产生二义性。

多重继承会使类型转换、构造方法的调用顺序变得复杂,会影响到性能。

接口和抽象类的区别

相同点:

(1)接口和抽象类都不能被实例化

(2)实现接口或继承抽象类的普通子类都必须实现这些抽象方法

不同点:

(1)抽象类可以包含普通方法和代码块,接口里只能包含抽象方法,静态方法和默认方法,

(2)抽象类可以有构造方法,而接口没有。

(3)抽象类中的成员变量可以是各种类型的,接口的成员变量只能是 public static final 类型的,并且必须赋值。

(4)实现接口的关键字为 implements,继承抽象类的关键字为 extends。一个类可以实现多个接口,只能继承一个抽象类。

重载和重写的区别

重载发生在同一个类中,方法名相同,但是参数列表、返回类型、权限修饰符可以不同

重写发生在子类中,方法名、参数列表、返回类型相同,权限修饰符要大于父类方法,声明异常范围要小于父类方法,但是final和private修饰的方法不可重写。

==和equals的区别

==比较基本类型,比较的是值,==比较引用类型,比较的是内存地址

equlas是Object类的方法,本质上与==一样,但是有些类重写了equals方法,比如String的equals被重写后,比较的是字符值,另外重写了equlas后,也必须重写hashcode()方法。

深拷贝和浅拷贝?

浅拷贝:浅拷贝只复制某个对象的引用,而不复制对象本身,新旧对象还是共享同一块内存
深拷贝:深拷贝会创造一个一摸一样的对象,新对象和原对象不共享内存,修改新对象不会改变原对对象。

Java创建对象得五种方式?

(1)new关键字 

 (2)Class.newInstance 

(3)Constructor.newInstance

(4)Clone方法 

 (5)反序列化

String、StringBuffer、StringBuilder的区别

String 由 char[] 数组构成,使用了 final 修饰,对 String 进行改变时每次都会新生成一个 String 对象,然后把指针指向新的引用对象。

StringBuffer可变并且线程安全

StringBuiler可变但线程不安全。

操作少量字符数据用 String;单线程操作大量数据用 StringBuilder;多线程操作大量数据用 StringBuffer。

为什么要把String设计为不可变

  • 节省空间:字符串常量存储在 JVM 的字符串池中可以被用户共享。
  • 提高效率:String 可以被不同线程共享,是线程安全的。在涉及多线程操作中不需要同步操作。
  • 安全:String 常被用于用户名、密码、文件名等使用,由于其不可变,可避免黑客行为对其恶意修改。

 简述Object类常用方法

  • hashCode:通过对象计算出的散列码。用于 map 型或 equals 方法。需要保证同一个对象多次调用该方法,总返回相同的整型值
  • equals:判断两个对象是否一致。需保证 equals 方法相同对应的对象 hashCode 也相同。
  • toString: 用字符串表示该对象
  • clone:深拷贝一个对象

简述throw与throws的区别?

throw 一般是用在方法体的内部,由开发者定义当程序语句出现问题后主动抛出一个异常。

throws 一般用于方法声明上,代表该方法可能会抛出的异常列表。

出现在java程序中的finally代码块是否一定会执行?

当遇到下面情况不会执行。

当程序在进入 try 语句块之前就出现异常时会直接结束。
当程序在 try 块中强制退出时,如使用 System.exit(0),也不会执行 finally 块中的代码。
其它情况下,在 try/catch/finally 语句执行的时候,try 块先执行,当有异常发生,catch 和 finally 进行处理后程序就结束了,当没有异常发生,在执行完 finally 中的代码后,后面代码会继续执行。值得注意的是,当 try/catch 语句块中有 return 时,finally 语句块中的代码会在 return 之前执行。如果 try/catch/finally 块中都有 return 语句,finally 块中的 return 语句会覆盖 try/catch 模块中的 return 语句。

简述泛型?

泛型,即“参数化类型”,解决不确定对象具体类型的问题。在编译阶段有效。在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型在类中称为泛型类、接口中称为泛型接口和方法中称为泛型方法。

简述注解?

Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。

其可以用于提供信息给编译器,在编译阶段时给软件提供信息进行相关的处理,在运行时处理写相应代码,做对应操作。

简述元注解?

元注解可以理解为注解的注解,即在注解中使用,实现想要的功能。其具体分为:

@Retention: 表示注解存在阶段是保留在源码,还是在字节码(类加载)或者运行期(JVM 中运行)。
@Target:表示注解作用的范围。
@Documented:将注解中的元素包含到 Javadoc 中去。
@Inherited:一个被@Inherited 注解了的注解修饰了一个父类,如果他的子类没有被其他注解修饰,则它的子类也继承了父类的注解。
@Repeatable:被这个元注解修饰的注解可以同时作用一个对象多次,但是每次作用注解又可以代表不同的含义

简述java中的Class对象?

java 中对象可以分为实例对象和 Class 对象,每一个类都有一个 Class 对象,其包含了与该类有关的信息。

获取 Class 对象的方法?

  • Class.forName(“类的全限定名”)
  • 实例对象.getClass()
  • 类名.class

java反射机制是什么?

Java 反射机制是指在程序的运行过程中可以构造任意一个类的对象、获取任意一个类的成员变量和成员方法、获取任意一个对象所属的类信息、调用任意一个对象的属性和方法。反射机制使得 Java 具有动态获取程序信息和动态调用对象方法的能力。可以通过以下类调用反射 API。

  • Class 类:可获得类属性方法
  • Field 类:获得类的成员变量
  • Method 类:获取类的方法信息
  • Construct 类:获取类的构造方法等信息

序列化是什么?

序列化是一种将对象转换成字节序列的过程,用于解决在对对象流进行读写操作时所引发的问题。序列化可以将对象的状态写在流里进行网络传输,或者保存到文件、数据库等系统里,并在需要的时候把该流读取出来重新构造成一个相同的对象。

java中线程安全的基本数据结构有哪些?

  • HashTable: 哈希表的线程安全版,效率低
  • ConcurrentHashMap:哈希表的线程安全版,效率高,用于替代 HashTable
  • Vector:线程安全版 Arraylist
  • Stack:线程安全版栈
  • BlockingQueue 及其子类:线程安全版队列

简述java的List

List 是一个有序队列,在 Java 中有两种实现方式:

ArrayList 使用数组实现,是容量可变的非线程安全列表,随机访问快,集合扩容时会创建更大的数组,把原有数组复制到新数组。

LinkedList 本质是双向链表,与 ArrayList 相比插入和删除速度更快,但随机访问元素很慢。

HashMap原理

1.HashMap在Jdk1.8以后是基于数组+链表+红黑树来实现的,特点是,key不能重复,可以为null,线程不安全

2.HashMap的扩容机制:

HashMap的默认容量为16,默认的负载因子为0.75,当HashMap中元素个数超过容量乘以负载因子的个数时,就创建一个大小为前一次两倍的新数组,再将原来数组中的数据复制到新数组中。当数组长度到达64且链表长度大于8时,链表转为红黑树

3.HashMap存取原理:

(1)计算key的hash值,然后进行二次hash,根据二次hash结果找到对应的索引位置

(2)如果这个位置有值,先进性equals比较,若结果为true则取代该元素,若结果为false,就使用高低位平移法将节点插入链表(JDK8以前使用头插法,但是头插法在并发扩容时可能会造成环形链表或数据丢失,而高低位平移发会发生数据覆盖的情况)

想要线程安全的HashMap怎么办?

(1)使用ConcurrentHashMap

(2)使用HashTable

(3)Collections.synchronizedHashMap()方法

ConcurrentHashMap原如何保证的线程安全?

JDK1.7:使用分段锁,将一个Map分为了16个段,每个段都是一个小的hashmap,每次操作只对其中一个段加锁

JDK1.8:采用CAS+Synchronized保证线程安全,每次插入数据时判断在当前数组下标是否是第一次插入,是就通过CAS方式插入,然后判断f.hash是否=-1,是的话就说明其他线程正在进行扩容,当前线程也会参与扩容;删除方法用了synchronized修饰,保证并发下移除元素安全。

HashTable与HashMap的区别?

(1)HashTable的每个方法都用synchronized修饰,因此是线程安全的,但同时读写效率很低

(2)HashTable的Key不允许为null

(3)HashTable只对key进行一次hash,HashMap进行了两次Hash

(4)HashTable底层使用的数组加链表

ArrayList和LinkedList的区别?

 ArratList的底层使用动态数组,默认容量为10,当元素数量到达容量时,生成一个新的数组,大小为前一次的1.5倍,然后将原来的数组copy过来;因为数组在内存中是连续的地址,所以ArrayList查找数据更快,由于扩容机制添加数据效率更低

LinkedList的底层使用链表,在内存中是离散的,没有扩容机制;LinkedList在查找数据时需要从头遍历,所以查找慢,但是添加数据效率更高

Collection 和 Collections 有什么区别?

Collection 是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,所有集合都是它的子类,比如 List、Set 等。
Collections 是一个包装类,包含了很多静态方法、不能被实例化,而是作为工具类使用,比如提供的排序方法:Collections.sort(list);提供的反转方法:Collections.reverse(list)。