JAVA基础

如果你有更好的想法请在评论区留下您的答案,一起交流讨论

  1. 面向对象有哪些特征?
    答:继承、封装、多态
  2. JDK与JRE的区别是什么?
    答:JDK是java开发时所需环境,它包含了Java开发时需要用到的API,JRE是Java的运行时环境,JDK包含了JRE,他们是包含关系
  3. Java有哪几种基本数据类型?
    答:8种,分别是int、byte、short、long、double、flot、char、boolean
  4. == 和equals比较有什么区别?

答: == 是Java中的操作符,equals是Java中Object对象提供的对象比较Api。它们的区别是==比较的是左右两边对象的内存地址,而equals比较的是左右对象的值

  1. public,private,protected,默认的区别什么?
    答:它们是java中的权限修饰符,public可以在任何地方访问,private仅仅只能在本类中访问,protected可以在本类以及本类的子类中访问,默认则代表可以在本包中访问
  2. short s1=1; s1+=1;有错吗? s1=s1+1; 有错吗?
    答:short在和int类型进行计算的时候会转换为int类型,原因是Java中精度小于int的数值运算的时候都回被自动转换为int后进行计算。计算后的结果也是int,再将int类型赋值给short类型当然会报错,所以s1=s1+1是错误的,然而s1+=1是java底层采用了编译语法糖的形式完成的转换,在编译后依然是转换为int计算只不过最终做了一次强转
  3. float f = 1.9; 有错吗?
    答:有错,因为在Java中字面量的小数指的是double类型,double为8个字节float为4个字节,无法完成自动转换。如果需要将字面量的小数转换为float类型需要在小数后面加f或者F
  4. &和&&有什么区别?
    答:前者是与符号,后者是短路与符号。前者除了可以做逻辑运算和可以做位运算称为“按位与”,后者只能做逻辑运算,其次再逻辑运算中,这两个符号都需要左右两侧表达式为true时,最后结果才为true
  5. 2*8最有效率的计算方法是什么?
    答:2 << 3
  6. 怎么理解值传递和引用传递?
    答:值传递传递的是变量中的数据,应用传递则是传递变量的引用而不是值
  7. Java到底是值传递还是引用传递?
    答:Java中8种基本数据类型传递的是值,而引用数据类型传递的是引用
  8. 一个".java"源文件的类有什么限制?
    答:最多只能有一个public static void mian方法,最少有一个类
  9. final关键字有哪些用法?
    答:修饰类:最终类,不可被子类继承,修饰方法:最终方法,不可被子类进行方法覆盖,修饰变量:常量,必须在声明时赋值,且之后的程序中不可改变。
  10. final、finally、finalize有什么区别?
    答:除了名称相像,都比相同。final属于java的修饰符,finally是结合Java异常体现中的Try一起使用的标识符用来关闭一些资源,finalize是Object根类中的一个方法,是对象被回收之前执行的方法。
  11. void和Void有什么区别?
    答:void是关键字在java中代表返回值为空,Void是类名
  12. 为什么byte的取值范围为-128~127?
    答:2的8次方,且减去正数的零
  13. char类型可以存储中文汉字吗?
    答:可以,char默认为2个字节,不过char采用的是UTF-16BE的编码集,且该编码集支持中文,char可以动态的更具字符内容改变字节,最大可以到4
  14. 重载和重写有什么区别?
    答:重载是在同一类中,满足重载需要方法名相同,参数列表不同,与返回值和访问修饰符无关。重写是在继承关系中,子类对父类方法的覆盖,需要满足“一同两小一大”(方法名相同,返回值类型小于等于父类方法,声明抛出异常小于等于父类方法,访问权限修饰符大于等于父类方法)
  15. 构造器可以被重写和重载吗?
    答:构造器可以被重载,但是不能被重写,因为构造器不能被继承
  16. Java中的断言(assert)是什么?
    答:用于检测表达式或方法的最终结果是否符合预期
  17. Error和Exception有哪些区别?
    答:Error是系统错误,一般由于系统原因或JVM内部错误引起,无法被程序捕获处理,Exception是程序异常,其中又分编译时(检查时)异常和运行时异常,可以被程序捕获处理,一般我们在开发中针对运行时异常进行处理。
  18. Java中常见的异常有哪些?
    答:NullPointException空指针异常、Arithmeticexception算数异常、ClassCastException类型转换异常、ClassNotFoundException类为找到异常、illegalargumentexception方法参数错误异常、ArrayIndexOfOutBoundsException数组索引越界异常
  19. Java中常见的运行时异常有哪些?
    答:NoSuchMethodError 为找到方法异常(反射调用方法时),NumberFormatException 数值转换异常,NullPointException空指针异常、Arithmeticexception算数异常、ClassCastException类型转换异常
  20. 运行时异常和受检异常有什么区别?

答:

运行时异常包括 RuntimeException 类及其子类,表示 JVM 在运行期间可能出现的异常。Java 编译器不会检查运行时异常。

受检异常是Exception 中除 RuntimeException 及其子类之外的异常。Java 编译器会检查受检异常。

RuntimeException异常和受检异常之间的区别:是否强制要求调用者必须处理此异常,如果强制要求调用者必须进行处理,那么就使用受检异常,否则就选择非受检异常(RuntimeException)。一般来讲,如果没有特殊的要求,我们建议使用RuntimeException异常。

  1. 什么时候会发生空指针异常?
    答:对值为空的变量进行操作时
  2. 你知道有哪些避免空指针异常的方法?
    答:对值为空的变量进行操作时先判断是否为空
  3. throw和throws有什么区别?
    答:throw用于在方法中抛出异常,throws写在方法名称后面,用于声明抛出的异常类型
  4. try里面return,finally还会执行吗?
    答:会的,除了System.exit(0)finally都会执行
  5. int和Integer有什么区别?
    答:int是java的基本数据类型,Integer是Java的引用数据类型。Integer是int的包装类,它提供了对int的转换和计算等API,操作起来更加方便
  6. 什么是包装类型?有什么用?
    答:包装类型是对基本数据类型的封装,底层其实就是对基本数据类型的操作提供了API和语法糖
  7. 什么是自动装箱和拆箱?
    答:基本数据类型转引用数据类型为自动拆箱,反之为自动装箱
  8. 你怎么理解Java中的自动类型转换和强制类型转换?
    答:小转大自动转换,拓展变量的内存字节。大转小强制转换,缩小内存字节损失精度
  9. 你怎么理解Java中的类型提升?
    答:语法糖
  10. 你怎么理解强、软、弱、虚引用?
    答:
  11. java工程师人事面试常见问题及答案 java工程师面试题库_java

  12. switch是否能用在long上?
    答:可以,switch支持int、byte、short、char以及对应的包装类,和String类型
  13. switch case支持哪几种数据类型?
    答:如上
  14. String的底层实现是怎样的?
    答:char数组,以及字符串常量池
  15. String是可变的吗?为什么?
    答:不可变,java中的字面量字符串都存放在字符串常量池中,无法改变,只能引用
  16. 为什么不能用 + 拼接字符串?
    答:因为如果用+号拼接字符串JVM编译时会进行优化,转变为StringBuilder拼接。单个表达式使用问题不大,但是如果是多个表达式或者在循环内使用会频繁创建StringBuilder对象大大降低性能
  17. StringBuffer和StringBuilder有什么区别?
    答:前者线程安全效率低,后者线程不安全效率高,
  18. StringJoiner有什么用?
    答:用于做字符串拼接的工具类
//间隔符是,
StringJoiner joiner1 = new StringJoiner(",");
joiner1.add("1").add("2").add("3");
System.out.println(joiner1.toString());
//1,2,3

//以[开头中间的间隔符是,以]结尾
StringJoiner joiner2 = new StringJoiner(",", "[", "]");
joiner2.add("1").add("2").add("3");
System.out.println(joiner2.toString());
//[1,2,3]

//拼接sql 的in条件的时候, 使用这个就方便很多了
StringJoiner joiner3 = new StringJoiner("','", "'", "'");
joiner3.add("1").add("2");
//'1','2'
  1. 普通类和抽象类有什么区别?
    答:抽象类被abstract所修饰,
  2. 静态内部类和普通内部类有什么区别?
    答:普通内部类持有外部外部类的应用,可以调用外部类的属性及方法,而静态内部类没有持有外部内引用,无法调用外部内的方法及属性。静态内部类可以有静态成员(方法,属性),而非静态内部类则不能有静态成 员(方法,属性)。 非静态内部类能够访问外部类的静态和非静态成员。静态内部类不能访问外 部类的非静态成员,只能访问外部类的静态成员。
    实例化方式不同:
  1. 静态内部类:不依赖于外部类的实例,直接实例化内部类对象
  2. 非静态内部类:通过外部类的对象实例生成内部类对象
  1. 静态方法可以直接调用非静态方法吗?为什么?
    答:不能,因为静态方法的加载顺序优先于非静态方法,且静态方法属于类,无需对象实例,非静态方法则需要类的实例才能调用
  2. 静态变量和实力变量有什么区别?
    答:静态变量属于类,无需创建对象通过类名即可调用,而实例变量需要类创建实例才可以调用。加载角度而言只要JVM加载了静态变量所处的类,静态变量就以及可以使用,为分配了空间。而实例变量需要创建对象之后才会为其分配空间
  3. 内部类可以访问其外部类的成员吗?
    答:非静态内部类可以,因为它持有者外部内的引用。
  4. 接口和抽象类有什么区别?
    答:接口没有构造方法,抽象类有。抽象类中可以有普通成员变量;接口中没有普通成员变量。抽象类中可以包含非抽象普通方法;接口中的所有方法必须都是抽象的,不能有非抽象的方法。一个类可以实现多个接口,用逗号隔开,但只能继承一个抽象类;接口不可以实现接口,但可以继承接口,并且可以继承多个接口,用逗号隔开。
  5. 接口里面可以写方法实现吗?
    答:可以,jdk1.8之后可以写接口的默认方法实现
  6. Java中的UUID是什么?
    答:生成一串随机的数字,它保证对在同一时空中的所有机器都是唯一的
  7. Java类初始化顺序是怎样的?
    答:如下

java工程师人事面试常见问题及答案 java工程师面试题库_java工程师人事面试常见问题及答案_02

  1. hashCode有什么作用?
    答:hashcode在java中用于表示对象的唯一码。hashcode也用在Hash数据结构中,用来计算对象存放在Hash中的位置(存储地址)
  2. hashCode和identityHashCode的区别?
    答:
  1. Object类中的hashCode方法会返回一个hash码,只有指向同一个对象的引用变量调用才会返回相同值,而String类中放宽了要求,对象里的值相等也返回相同值
  2. identityHashCode方法是System类中的方法,调用该方法时,不管类中是否重写了Object类中的hashCode方法,都执行Object类中的hashCode方法,返回一个hashCode值。所以只有指向同一个对象的引用变量调用才会返回相同值
  1. 什么是Hash冲突?
    答:两个对象都放入同一个hash容器中,且计算出的hash值都相同。也称为hash碰撞,此时的解决办法是再hash
  2. Java常用的元注解有哪些?
    答:
    @Target:描述了注解修饰的对象范围
  • METHOD:用于描述方法
  • PACKAGE:用于描述包
  • PARAMETER:用于描述方法变量
  • TYPE:用于描述类、接口或enum类型

@Inherited:使被它修饰的注解具有继承性

@Retention:表示注解的运行时期范围

  • RetentionPolicy.SOURCE -------------注解将被编译器丢弃
  • RetentionPolicy.CLASS -------------注解在class文件中可用,但会被VM丢弃
  • RetentionPolicy.RUNTIME ---------VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息

@Documented:使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息

  1. Java泛型中的T、R、K、V、E分别指什么?
    答:
  • ? --不确定的Java类型,是一个通配符泛型
  • T --表示确定的Java类型
  • K、V --Java中的键值对key、value
  • E --Element (在集合中使用,因为集合中存放的是元素,也表示Collection容器中的类型)
    Java源码中的Class代表这个类型所对应的类,而Class<?>表示类型不确定的类。
  1. Java金额计算怎么避免精度丢失?
    答:使用BigDecimal进行与金钱相关的计算
  2. Java语法糖是什么意思?
    答:通过提供简单的编写方式在编译时完成对复杂操作的转换。通常是指Java中的简单语法,在编译时期还原成基础语法。
  3. transient关键字有什么作用?
    答:将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会被序列化
  4. 如何实现对象克隆?
    答:Java对象克隆又分深拷贝和浅拷贝,浅拷贝调用Object跟对象继承下来的clone,深拷贝可以借助SpringFramework提供的BeanUtils工具或者通过Java的序列化与反序列化实现。
  5. 对象克隆浅拷贝和深拷贝有什么区别?
    答:浅拷贝与深拷贝的区别,浅拷贝:如果对象中还包括着子对象,浅拷贝只能拷贝一份父对象的内存空间,而子对象则只是拷贝了其引用,值没有进行拷贝。深拷贝则是涉及到这个对象当前所占的所有空间(值)都进行拷贝。
  6. Java反射机制有什么作用?
    答:反射可以让程序在运行时具有检测自己和获取当前运行环境的能力。
    理解反射机制要了解静态编译和动态编译,静态编译时在程序运行之前编译时期就以及确定的,动态编译则可以才程序运行期间,使程序自己改变自己的行为模式或逻辑,具有高度的灵活性。典型的编程设计模式动态代理就是在运行时期完成的编译
  7. Java反射机制有什么优缺点?
    答:
    优点:增强程序灵活性和可拓展性,可帮助程序进行解耦合,提高自身的适应能力
    缺点:
    1、 性能问题。
    Java反射机制中包含了一些动态类型,所以Java虚拟机不能够对这些动态代码进行优化。因此,反射操作的效率要比正常操作效率低很多。我们应该避免在对性能要求很高的程序或经常被执行的代码中使用反射。而且,如何使用反射决定了性能的高低。如果它作为程序中较少运行的部分,性能将不会成为一个问题。
    2、安全限制。
    使用反射通常需要程序的运行没有安全方面的限制。如果一个程序对安全性提出要求,则最好不要使用反射。
    3、程序健壮性。
    反射允许代码执行一些通常不被允许的操作,所以使用反射有可能会导致意想不到的后果。反射代码破坏了Java程序结构的抽象性,所以当程序运行的平台发生变化的时候,由于抽象的逻辑结构不能被识别,代码产生的效果与之前会产生差异。
  8. 什么是宏变量和宏替换?

答:引用用宏变量,系统会自动把宏变量替换成他所指向的地址的值

String nb = "finaltest";
String nb1 = "final";
String nb2 = "test";
final String nb11 = "final";
final String nb22 = "test";
String nb3 = "final" + "test";
String nb4 = nb1 + nb2;
String nb5 = nb11 + nb22;
System.out.println(nb == nb3);
System.out.println(nb == nb4);
System.out.println(nb == nb5);

true
false
true
    
	nb定义了finaltest,nb3定义了 “final” + “test”,初始编译的时候nb3会确定初始值为finaltest(JVM在编译时会对字面量的字符串进行优化),因此初始值与nb相等,所以会把nb3引用的地址指向nb引用的地址,所以nb与nb3相等。
    而nb11,nb22根据上面三条规则得知是宏变量,引用用宏变量,系统会自动把宏变量替换成他所指向的地址的值,所以nb11+nb22就会替换成finaltest,然后与nb3一样,这就是宏替换。
  1. 什么是逃逸分析?
    答:在编程语言的编译优化原理中,分析指针动态范围的方法称之为逃逸分析。通俗一点讲,当一个对象的指针被多个方法或线程引用时,我们称这个指针发生了逃逸。
    而用来分析这种逃逸现象的方法,就称之为逃逸分析。全局变量赋值,方法返回值,实例引用传递。

参考文章

  1. 什么是伪共享?有什么解决方案?
    答:参考文章

什么是多线程环境下的伪共享(false sharing)?
伪共享是多线程系统(每个处理器有自己的局部缓存)中一个众所周知的性能问题。伪共享发生在不同处理器上的线程对变量的修改依赖于相同的缓存行,如下图所示:

小知识点:

****1.**共享就是一个内存区域的数据被多个处理器访问,伪共享就是不是真的共享。
这里的共享这个概念是基于逻辑层面的。实际上伪共享与共享在cache line 上实际都是共享的。
*2.*CPU访问的数据都是从cache line 中读取的。如果cpu 在cache 中找不到需要的变量,则称缓存未命中。

未命中时,需要通过总线从内存中读取进cache 中。每次读取的内存大小就是一个cache line 的大小。

**3.**如果多个CPU访问的不同内存变量被装载到了同一个cache line 中,则从程序逻辑层上讲,并没有共享变量,
但实际上在cache line 上他们是共享访问的,这个就是典型的伪共享。

**4.**伪共享与共享 在 cache line 的层面上必须都是共享的。多个CPU对共享内存的访问安全通过缓存一致性来保证。

*5*.伪共享问题很难被发现,因为线程可能访问完全不同的全局变量,内存中却碰巧在很相近的位置上。如其他诸多的并发问题,避免伪共享的最基本方式是仔细审查代码,根据缓存行来调整你的数据结构。

  1. Java 8新增了哪些特性?
    答:最核心的特性Lambda 表达式和函数式接口以及Stream API
  2. Java 8中的Lambda表达式有什么作用?
    答:Lambda 是一个匿名函数,可以把Lambda表达式理解为一段可以传递的代码(将代码像数据一样传递)。可以写出更加简洁、灵活的代码。作为一种更加紧凑的代码风格,使java的语言表达能力得到了提升。
  3. Java 8中的Optional类有什么作用?
    答:以解决程序中常见的NullPointerException异常问题
  4. Java 8中的@Repeatable注解有什么作用?
    答:@Repeatable可以用来指示某种类型的注解是可以重复添加的
  5. Java 8中的方法引用是指什么?
    答:方法引用,如果函数式接口以及有具体实现了可以直接引用该方法。语法为ClassName::MethodName || ObjectName::实例方法名称
  6. Java 8中的Stream有什么作用?
    答:提供了对集合计算的支持,集合负责存储而Stream负责计算。它用于操作数据源所产生的序列,例如复杂的查找、过滤映射数据等操作
  7. Java 8中的函数式编程怎么用?
    答:函数与其他数据类型一样,可以赋值给其他变量,也可以作为参数,也可以作为返回值
  • 代码简洁,开发快速
  • 易于理解,降低风险
  • 易于并行
  • 延迟执行
  1. 如何获取一个Stream流对象?
    答:
  • 数组获取Stream:Arrays.stream(数组对象)
  • 集合获取Stream:集合对象.stream()
  • 值获取Stream:Stream.of(值…)
  1. 什么是序列化,怎么序列化,为什么序列化,反序列化会遇到什么问题,如何解决。
    答:序列化是将内存中存储的对象数据转换为可断电存储或网络传输的二进制数据。序列化的方式很多,首先将需要序列化的类实现Serializable常见的JDK提供的ObjectOutPutStream或者JSON格式序列化等等。反序列可能会遇到反序列化后的类版本不一致问题,需要保证序列化和反序列化的版本一直