Java常见面试题:JavaSE基础知识(二)

  • A+
所属分类:后端开发

整理了一些java常见的面试题型和基础知识,预计共五章。本篇为第二章,全文一共7304字。建议使用右下角“文章目录”检索查看!Java常见面试题:JavaSE基础知识(二)

 

字符串如何转基本数据类型?

调用基本数据类型对应的包装类中的方法 parseXXX(String)或 valueOf(String)即可返回相应基本类型。

 

基本数据类型如何转字符串?

一种方法是将基本数据类型与空字符串(“”)连接(+)即可获得其所对应的字符串;另一种方法是调用 String类中的 valueOf()方法返回相应字符串。

 

匿名内部类中对接口的方法为什么要加public

对于接口当中常见的成员:而且这些成员都有固定的修饰符。

  • 全局常量:public static final
  • 抽象方法:public abstract

由此得出结论,接口中的成员都是公共的权限,都是 public。

 

构造代码块和构造函数的区别

1)作用: 构造函数是给特定的对象进行初始化的; 构造代码块是对所有对象初始化。

2)格式: 构造函数是: 类名{}。构造代码块: {}

3)执行顺序: 静态代码块------构造代码块--------->构造函数

 

普通代码块、静态代码块、构造代码块区别

普通代码块:在方法或语句中出现的{}就称为普通代码块。

构造代码块:直接在类中定义且没有加 static 关键字的代码块称为{}构造代码块。

静态代码块: 在 java 中使用 static 关键字声明的代码块。

点击:展开

1)普通代码块:在方法或语句中出现的{}就称为普通代码块。普通代码块和一般的语句执行顺序由他们在代码中出现的次序决定--“先出现先执行”

public static void main(String[] args) {
    {
        int x = 3;
        System.out.println("1,普通代码块内的变量 x=" + x);
    }
    int x = 1;
    System.out.println("主方法内的变量 x=" + x); {
        int y = 7;
        System.out.println("2,普通代码块内的变量 y=" + y);
    }
}

Java常见面试题:JavaSE基础知识(二)

2)构造代码块:直接在类中定义且没有加 static 关键字的代码块称为{}构造代码块。构 造代码块在创建对象时被调用,每次创建对象都会被调用,并且构造代码块的执行次序优先 于类构造函数。

public class DemoCode2 {
    {
        System.out.println("第一代码块");
    }

    public DemoCode2() {
        System.out.println("构造方法");
    }

    {
        System.out.println("第二构造块");
    }

    public static void main(String[] args) {
        new DemoCode2();
        new DemoCode2();
        new DemoCode2();
    }
}

Java常见面试题:JavaSE基础知识(二)

3)静态代码块: 在 java 中使用 static 关键字声明的代码块。静态块用于初始化类,为 类的属性初始化。每个静态代码块只会执行一次。由于 JVM 在加载类时会执行静态代码块, 所以静态代码块先于主方法执行。

如果类中包含多个静态代码块,那么将按照"先定义的代码先执行,后定义的代码后执行"。

注意: 1 静态代码块不能存在于任何方法体内。 2 静态代码块不能直接访问静态实例变量 和实例方法,需要通过类的实例对象来访问。
public class DemoCode3 {

    {
        System.out.println("DemoCode3 的构造块");
    }

    static {
        System.out.println("DemoCode3 的静态代码块");
    }

    public DemoCode3() {
        System.out.println("DemoCode3 的构造方法");
    }

    public static void main(String[] args) {
        System.out.println("DemoCode3 的主方法");
        new DemoCode3();
        new DemoCode3();
    }
}

Java常见面试题:JavaSE基础知识(二)

 

this与this()的区别

this(有参数/无参数) 用于调用本类相应的构造函数; this. 后跟方法或属性 指示本类的方法或属性。

super(有参数/无参数) 用于调用父类相应的构造函数;super. 后跟方法或属性(父类中指明的 public )

 

Java中实现多态的机制是什么?

靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。

 

异常的定义

程序运行过程中的不正常现象就叫异常。

异常体系的根类是:Throwable

 

异常的分类(两种)

  1. 编译时被检测异常:
    1. 该异常在编译时,如果没有处理(没有抛也没有try),编译失败。
    2. 该异常被标识,代表这可以被处理。
  2. 运行时异常(编译时不检测)
    1. 在编译时,不需要处理,编译器不检查。
    2. 该异常的发生,建议不处理,让程序停止。需要对代码进行修正。
  3. 异常体系的特点:

异常体系中的所有类及其子类对象都具备可抛性。也就是说可以被throw和throws关键字所操作。

关于 final,finally,finalize区别,可参考:“Java常见面试题:JavaSE基础知识(一)”——final 、finally 、finalize

 

为什么父类不抛异常,子类就不能抛异常

将父类引用传入给方法 A(没有抛异常),方法 A 使用父类引用。使用多态将子类对象传递给 A,如果子类抛出异常 B,因为 A 方法没有过处理异常 B, 将会导致程序错误

 

Error和Exception的区别

Error 类和 Exception 类的父类都是 Throwable 类。

error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。

exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。

详细:展开

Error 类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢出等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和和预防,遇到这样的错误,建议让程序终止。

Exception 类表示程序可以处理的异常,可以捕获且可能恢复。遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。

Exception 类又分为运行时异常( Runtime Exception)和受检查的异常(Checked Exception ),运行时异常;ArithmaticException,IllegalArgumentException,编译能通过,但是一运行就终止了,程序不会处理运行时异常,出现这类异常,程序会终止。而受检查的异常,要么用 try。。。 catch 捕获,要么用 throws 字句声明抛出,交给它的父类处理,否则编译不会通过。

 

Exception和RuntimeException的区别

Exception:一般性的错误,是需要我们编写代码进行处理的。

RuntimeException:运行时异常,这个我们也不需要处理。

在用throws抛出一个的时候,如果这个异常是属于RuntimeException的体系的时候,我们在调用的地方可以不用处理。(RuntimeException和RuntimeException的子类)

在用throws抛出一个的时候,如果这个异常是属于Exception的体系的时候,我们在调用的地方必须进行处理或者继续抛出。

 

throws和throw的区别

有throws的时候可以没有throw。

有throw的时候,如果throw抛的异常是Exception体系,那么必须有throws在方法上声明。

throws用于方法的声明上,其后跟的是异常类名,后面可以跟多个异常类,之间用逗号隔开

throws 表示出现异常的一种可能性,并不一定会发生这种异常。

throw用于方法体中,其后跟的是一个异常对象名

 

自定义异常

定义类继承Exception或者RuntimeException

  1. 为了让该自定义类具备可抛性。
  2. 让该类具备操作异常的共性方法。
class MyExcepiton extends Exception {
    MyExcepiton() {}

    MyExcepiton(String message) {
        super(message);
    }
}

class MyException extends RuntimeException {
    MyExcepiton() {}

    MyExcepiton(String message) {
        super(message);
    }
}

 

什么时候会用到自定义异常?

当需要自己定义异常的名称和特有内容,增强阅读性、方便查找时。

 

常见的RuntimeException(运行期异常)

  1. java.lang.NullPointerException 空指针异常;出现原因:调用了未经初始化的对象或者是不存在的对象。
  2. java.lang.ClassNotFoundException 指定的类找不到;出现原因:类的名称和路径加载错误;通常都是程序试图通过字符串来加载某个类时可能引发异常。
  3. java.lang.NumberFormatException 字符串转换为数字异常;出现原因:字符型数据中包含非数字型字符。
  4.  java.lang.IndexOutOfBoundsException 数组角标越界异常,常见于操作数组对象时发生。
  5. java.lang.IllegalArgumentException 方法传递参数错误。
  6. java.lang.ClassCastException 数据类型转换异常。
  7. java.lang.NoClassDefFoundException 未找到类定义错误。
  8. SQLException SQL 异常,常见于操作数据库时的 SQL 语句错误。
  9. java.lang.InstantiationException 实例化异常。
  10. java.lang.NoSuchMethodException 方法不存在异常。

 

hashCode()和equals方法的联系?

equals方法的特性:自反性、一致性、传递性、对称性、非空性。

只要重写equals,就必须重写hashCode。

因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法。

如果自定义对象做为Map的键,那么必须重写hashCode和equals。 说明:String重写了hashCode和equals方法,所以我们可以非常愉快地使用String对象作为key来使用。

 

String、StringBuilder、StringBuffer的区别?

1)String是字符串常量,StringBuffer和StringBuilder是字符串变量

2)String只读字符串,意味着其引用的字符串内容不能发生改变。StringBuffer/StringBuilder 表示的字符串对象可以直接进行修改。

3)StringBuffer是线程安全的,StringBuilder是非线程安全的。相比StringBuffer来说,StringBuilder的效率要高

详细:展开

(1)可变不可变

String:字符串常量,在修改时不会改变自身;若修改,等于重新生成新的字符串对象。

StringBuffer:在修改时会改变对象自身,每次操作都是对 StringBuffer 对象本身进行修改,不是生成新的对象;使用场景:对字符串经常改变情况下,主要方法: append(), insert()等。

(2)线程是否安全

String:对象定义后不可变,线程安全。

StringBuffer:是线程安全的(对调用方法加入同步锁),执行效率较慢,适用于多线程下操作字符串缓冲区大量数据。

StringBuilder:是线程不安全的,适用于单线程下操作字符串缓冲区大量数据。

(3)共同点

StringBuilder 与 StringBuffer 有公共父类 AbstractStringBuilder(抽象类)。

StringBuilder、 StringBuffer 的方法都会调用 AbstractStringBuilder 中的公共方法,如super.append(...)。

只是 StringBuffer 会在方法上加 synchronized 关键字,进行同步。最后,如果程序不是多线程的,那么使用StringBuilder 效率高于 StringBuffer。

 

同步和异步有何异同,在什么情况下分别使用他们?举例说明。

如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。

当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率

 

sleep()和 wait()有什么区别?

sleep 是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用 sleep 不会释放对象锁。

wait 是 Object 类的方法,对此对象调用 wait 方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出 notify 方法(或 notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

 

获得年月日、小时分钟秒?

public static void main(String[] args) {
    Date t = new Date();
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    System.out.println(df.format(t));
}

Java常见面试题:JavaSE基础知识(二)

 

获得从 1970年 1月 1日 0时 0分 0秒到现在的毫秒数

System.out.println(Clock.systemDefaultZone().millis());
System.out.println(System.currentTimeMillis());
System.out.println(Calendar.getInstance().getTimeInMillis());

 

获得某月的最后一天

展开

//获取当前月第一天:
Calendar c = Calendar.getInstance();
c.add(Calendar.MONTH, 0);
c.set(Calendar.DAY_OF_MONTH,1);//设置为 1 号,当前日期既为本月第一天
String first = format.format(c.getTime());
System.out.println("===============first:"+first);

//获取当前月最后一天
Calendar ca = Calendar.getInstance();
ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
String last = format.format(ca.getTime());
System.out.println("===============last:"+last);

//Java 8
LocalDate today = LocalDate.now();
//本月的第一天
LocalDate firstday = LocalDate.of(today.getYear(),today.getMonth(),1);
//本月的最后一天
LocalDate lastDay =today.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("本月的第一天"+firstday);
System.out.println("本月的最后一天"+lastDay);

 

Java 中有几种类型的流

1)按照流的方向:输入流(inputStream)和输出流(outputStream)。

2)按照实现功能分:节点流(可以从或向一个特定的地方(节点)读写数据。如 FileReader)和处理流(是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如 BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。)

3)按照处理数据的单位: 字节流和字符流。字节流继承于 InputStream 和 OutputStream,字符流继承于InputStreamReader 和 OutputStreamWriter。

 

IO流常用基类

1)字节流

输出字节流:

  1. OutputStream:字节写入流抽象类
    1. FileOutputStream: 字节写入流
    2. BufferedOutputStream: 字节写入流缓冲区
    3. PrintStream:打印流

输入字节流:

  1. InputStream:字节读取流抽象类
    1. FileInputStream:  字节读取流
    2. BufferedInputStream: 字节读取流缓冲区

 

2)字符流 

输出字符流:

  1. Writer:字符写入流的抽象
    1. FileWriter: 字符写入流
    2. BufferedWriter: 字符写入流缓冲区
    3. OutputStreamWriter:字符通向字节的转换流(涉及键盘录入时用)
    4. OutputStreamWriter:  打印流,可处理各种类型的数据

输入字符流:

  1. Reader: 字符读取流的抽象类
    1. FileReader:字符读取流
    2. LineNumberReader:跟踪行号的缓冲字符读取流
    3. BufferedReader:字符读取流缓冲区
    4. InputStreamReader:字节通向字符的转换流(涉及键盘录入时用)

图示:展开

Java常见面试题:JavaSE基础知识(二) Java常见面试题:JavaSE基础知识(二)

 

字节流如何转为字符流

字节输入流转字符输入流通过 InputStreamReader 实现,该类的构造函数可以传入 InputStream 对象。

字节输出流转字符输出流通过 OutputStreamWriter 实现,该类的构造函数可以传入 OutputStream 对象。

  • 扫扫关注公众号
  • weinxin
  • 扫扫体验小程序
  • weinxin
亦枫

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

目前评论:1   其中:访客  1   博主  0

    • avatar 头条 2

      文章不错支持一下吧