java工程师查漏补缺

在网上看到一篇文章 https://mp.weixin.qq.com/s/hlAn6NPR1w-MAwqghX1FPg 觉得内容挺全,因此想通过上面的问题去学习,查漏补缺并开一篇博客来记录一下。

java基础知识

面向对象编程和面向过程编程

面向过程就是讲按照处理问题的步骤来写一个个方法来完成,按照处理问题的顺序调用方法。
面向对象就是讲处理问题需要的人或物抽象程一个对象,让对象去处理问题。
比如面试:
面向过程就是:按照面试流程写一个个方法,先写一个笔试的方法,让面试者自我介绍的方法,问问题的方法。
面向过程就是:将笔试,自我介绍,提问这些属性方法抽象程一个面试官,直接让面试官去面试。

面向对象的三大基本特征和五大基本原则

三大基本特征:封装,继承,多态
五大基本原则: 1、单一职责原则(SRP) 2、开放封闭原则(OCP)3、里氏替换原则(LSP)4、依赖倒置原则(DIP)5、接口隔离原则(ISP)

为什么说 Java 中只有值传递

值传递:会对传的参数拷贝一份传给方法,方法堆值修改不会影响到原来的值。

引用传递:不会拷贝,直接将原值传过去,方法能够影响到原来的值。
在java中是只有值传递,有人以为传递对象是引用传递,因为方法可以修改对象的属性。但其实传递对象时,传递的是对象地址(就是会将地址应用复制一份给形参),方法可以修改地址指向的对象,但没有办法改变方法外实参指向的地址。

java类初始化顺序

父类静态成员和static块--->子类静态成员和static块---->父类普通成员和非static块---->父类构造函数----->子类普通成员和非static块------>子类构造函数

  • 类的静态成员和static块在类加载的初始化阶段就已经通过()类构造器赋值初始化了,因为类加载会先加载父类,所以父类静态成员和static块会比子类静态成员和static块先初始化。

  • 子类的构造函数第一行会默认调用父类的构造函数,会比子类构造函数先执行。

  • 构造函数执行就是对类成员赋值,所以类普通成员和非static块必然先与构造函数初始化

byte,short,int,long取值范围大小

byte(-27~27-1),short(-215~215-1),int(-231~231-1),long(-263~263-1)

为什么浮点性无法表示金额

float的精度是23位,double精度是52位。在存储或运算过程中,当超出精度时,超出部分会被截掉,由此就会造成误差。
BigDecimal是通过数组模拟大数,可以保存任意精度的数。
需要注意的是如果通过public BigDecimal(double val)的方法构造BigDecimal还是会出现精度丢失的现场,因为double精度已经丢失了,通过它创建的BigDecimal精度也丢失。
第二个要注意的地方是,当使用BigDecimal进行除法计算时可能会出现无限循环小数例如:

new BigDecimal("1").divide(new BigDecimal("3"))

这时程序会抛出异常java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
这个可以通过加两个参数解决

public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)

第一参数表示除数, 第二个参数表示小数点后保留位数,
第三个参数表示舍入模式,只有在作除法运算或四舍五入时才用到舍入模式

JDK 6 和 JDK 7 中 substring 的原理及区别

substring(int beginIndex, int endIndex)方法截取字符串并返回其[beginIndex,endIndex-1]范围内的内容。
String对象对象有三个属性char value[], int offset,int count他们分别用来存储真正的字符数组,数组的第一个位置索引以及字符串中包含的字符个数

  • 在jdk6中,调用substring当会创建一个新的String对象newStr,但newStr的value属性还是指向原来的char[]对象,通过修改offeset和count来表示不同的字符串;这回有个问题就是:当引用字符串的整个数组的对象失效了,但通过substring产生的只引用几个字符的字符串还有效,那整个字符数组都不能回收,这就会产生内存泄漏。

  • 在jdk7中,调用substring会生成并引用一个新的字符数组,与原来的字符串没有关联,不会产生内存泄漏。

replaceFirst、replaceAll、replace 区别

  • replace(String oldChar, String newChar):对匹配oldChar的所有字符串替换成newChar
  • repalaceAll(String oldChar, String newChar);将oldChar以正则表达式的形式匹配字符串,并把所有匹配的替换成newChar
  • replaceFirst(String oldChar, String newChar):将oldChar以正则表达式的形式匹配字符串,并把第一个匹配的替换成newChar

java字符串的拼接

  • +:通过加号拼接字符串其实底层会新建一个StringBuilder对象,通过append方法来进行进行拼接
    疑问?既然底层也是通过StringBuilder拼接,那为啥建议通过StringBuilder来拼接呢,不一样吗?
    虽然都是通过StringBuilder,但是通过+拼接还会先将新建一个StringBuilder对象再拼接,拼接完再转String对象。如果只是进行一次拼接,那+和StringBuilder其实没什么差别。但是如果在一个循环内不断拼接,通过append只要建立一个StringBuild对象,但是如果是+就要不断的建StringBuilder,拼接,转String,建StringBuilder,拼接,转String...这其中的性能消耗是非常大的。

switch 对 String 的支持

其实Java的switch只支持整形,那为什么除了byte,short,int(不支持long),char和String也可以呢?
其实char会转成ASCII,所以也是int类型
至于String则是会转成HashCode,但是不同的的对象HashCode是有可能相同的,所以当HashCode匹配上后还要通过equals()方法判断对象是否相同。

transient、instanceof、final、static、volatile、synchronized、const 原理及用法

  • transient:表示变量不参与序列化过程
  • instanceof:用来判断引用类型的变量所指向的对象是否是一个类(或者接口,抽象类,父类)的实例
  • const:const是Java预留关键字,用于后期扩展用,用法跟final相似,不常用

Collection 和 Collections 区别

1、java.util.Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。
List,Set,Queue接口都继承Collection。
直接实现该接口的类只有AbstractCollection类,该类也只是一个抽象类,提供了对集合类操作的一些基本实现。List和Set的具体实现类基本上都直接或间接的继承了该类。
2、java.util.Collections 是一个包装类。它包含有各种有关集合操作的静态方法(对集合的搜索、排序、线程安全化等),大多数方法都是用来处理线性表的。此类不能实例化,就像一个工具类,服务于Java的Collection框架。

Arrays.asList 获得的 List 使用时需要注意什么

(1)该方法不适用于基本数据类型(byte,short,int,long,float,double,boolean)
(2)该方法将数组与列表链接起来,当更新其中之一时,另一个自动更新
(3)不支持add和remove方法

Arrays.asList获得的ArrayList其实是Arrays的一个内部类,这个类引用传进来的数组,因为数组的大小是固定的因此不支持add和remove方法方法,因为引用的都是一个数组,所以数组和列表更新其中一个,另一个也会更新,asList()要求参数是对象数组,但基本类型不是对象,因此不能用asList.

Enumeration 和 Iterator 区别

Enumeration 只有2个函数接口。 通过Enumeration,我们只能读取集合的数据,而不能对数据进行修改。
Iterator 只有3个函数接口。 Iterator除了能读取集合的数据之外,也能数据进行删除操作。

Iterator 支持 fail-fast 机制,而 Enumeration 不支持 :
Enumeration 是JDK 1.0添加的接口。使用到它的函数包括Vector、Hashtable等类,这些类都是JDK 1.0中加入的,Enumeration存在的目的就是为它们提供遍历接口。Enumeration本身并没有支持同步,而在Vector、Hashtable实现Enumeration时,添加了同步。
而Iterator 是JDK 1.2才添加的接口,它也是为了HashMap、ArrayList等集合提供遍历接口。Iterator是支持fail-fast机制的:当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。
简单得概括总结是:枚举速度快,占用内存少,但不是快速失败的,线程不安全。迭代允许删除底层数据,枚举不行。

fail-fast 和 fail-safe

fail-fast:在使用迭代器遍历一个集合对象时,比如增强for,如果遍历过程中对集合对象的内容进行了修改(增删改),会抛出 ConcurrentModificationException 异常.
fail-safe:采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先copy原有集合内容,在拷贝的集合上进行遍历.缺点:因为遍历的是拷贝的集合,那如果原来的集合发生更新,遍历过程中也是无法感知的。

CopyOnWriteArrayList

CopyOnWriteArrayList是在jdk1.5时java并发包中提供的容器,实现原理是当我们需要往容器修改元素时,会先将容器copy一份,然后在copy的容器进行修改操作,读取操作就还是在原来的容器进行,这样对容器的读操作就不用加锁了。不过copy和修改操作还是要加锁的。
代码实例

 public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] elements = getArray();
        int len = elements.length;
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        newElements[len] = e;
        setArray(newElements);
        return true;
    } finally {
        lock.unlock();
    }
}

ConcurrentSkipListMap

ConcurrentSkipListMap是线程安全的Map,通过跳跃表实现,跳跃表有很多层,最低层包含所有元素,上层元素是低层的子集。
跳跃表查找的过程:先通过最上层查找,当下一个元素大于要找的元素时,就转到下一层找。
相比于红黑树的优点:修改操作更简单,红黑树插入元素可能会导致整棵树调整优化

Java 枚举如何比较

compareTo()方法:枚举类型的compareTo()方法返回的是两个枚举的序数的差
equals():枚举类型的每个枚举都是单例的,equals()方法也是通过来判断的,因此我们可以通过equals()或来判断两个枚举是否相等

switch 对枚举的支持

switch是支持枚举类型的,要注意的是case后面只要写枚举值(first)就好,不用类型(TestEmun.first)

枚举的线程安全及序列化

https://www.cnblogs.com/fswhq/p/11272921.html

Java 中能创建 volatile 数组吗?

能,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不是整个数组。我的意思是,如果改变引用指向的数组,将会受到 volatile 的保护,但是如果多个线程同时改变数组的元素,volatile 标示符就不能起到之前的保护作用了。

Java 中应该使用什么数据类型来代表价格?

如果不是特别关心内存和性能的话,使用BigDecimal,否则使用预定义精度的 double 类型。

怎么将 byte 转换为 String?

可以使用 String 接收 byte[] 参数的构造器来进行转换,需要注意的点是要使用的正确的编码,否则会使用平台默认编码,这个编码可能跟原来的编码相同,也可能不同。

Java 中怎样将 bytes 转换为 long 类型?

String接收bytes的构造器转成String,再Long.parseLong

我们能将 int 强制转换为 byte 类型的变量吗?如果该值大于 byte 类型的范围,将会出现什么现象?

是的,我们可以做强制转换,但是 Java 中 int 是 32 位的,而 byte 是8位的,所以,如果强制转化是,int 类型的高 24 位将会被丢弃,byte 类型的范围是从 -128 到 127。

原文地址:https://www.cnblogs.com/zdl2234/p/14291519.html