java基础知识之面试题(二)

简介: 目录前言区别前言JVM是不能独立安装的。JRE和JDK都是可以独立安装的层层嵌套,jvm包括jdk,jdk包括jre区别JRE:java运行环境JDK:Java开发工具箱JVM:java虚拟机主要讲解jdk与jre的区别jdk(Java Development Kit):java 开发工具包jre(Java Runtime Environment):java 运行环境层层嵌套主要记住,==jvm包括jdk,jdk包括jre==即可而且主要的区分点是看你用在什么方面在编写jav

前言

主要讲解java的一些基础知识以及容易混淆的概念
实时更新汇总

如果想补充一些细节概念或者知识点可看
java零基础从入门到精通(全)
javaSE从入门到精通的十万字总结(全)

java语言有哪些特点?
面向对象、可靠性、安全性、支持多线程(c++调用操作系统的的多线程)、支持网络编程、编译与解释并存

1. JDK、JRE和JVM区分

JVM是不能独立安装的。
JRE和JDK都是可以独立安装的
层层嵌套

JDK = JRE + 开发工具集(例如Javac编译工具等)
JRE = JVM + Java SE 标准类库

  • JRE:java运行环境
  • JDK:Java开发工具箱
  • JVM:java虚拟机

主要讲解jdk与jre的区别
jdk(Java Development Kit):java 开发工具包
jre(Java Runtime Environment):java 运行环境

层层嵌套主要记住,==jvm包括jdk,jdk包括jre==即可

而且主要的区分点是看你用在什么方面
在编写java程序的时候,jdk很适合,因为要开发工具箱
如果在编译java的时候,jre很适合,因为需要java的运行环境

2. == 和 equals 的区别

java常考的面试中也有一个这个
主要是容易混淆并且记乱
主要的区分度是

  • == 在基本类型中是值比较,对于引用类型是地址比较
  • equals 是引用比较,但在多数类中(比如String、Integer 等)重写equals方法,导致很多都是值比较

equals( )∶它的作用也是判断两个对象是否相等,它不能用于比较基本数据类型的变量。

情况1:类没有覆盖equals()方法。则通过equals()比较该类的两个对象时,等价于通过“==”比较这两个对象。使用的默认是0bject类equals()方法。
情况2:类覆盖了equals()方法。一般,我们都覆盖equals()方法来两个对象的内容相等;若它们的内容相等,则返回true(即,认为这两个对象相等)。

为了更好的显示这种区分度,下面以代码展示演示
先展示==的代码比较
注意下面的代码区分度
新建的空间比较不同是因为开辟了新空间,而且比较的时候比较的是引用类型(记住)

String x = "A";
String y = "A";
String z = new String("A");
System.out.println(x==y); // true
System.out.println(x==z); // false
System.out.println(x.equals(y)); // true
System.out.println(x.equals(z)); // true

在这里插入图片描述

equals中比如在新建对象的时候,两个相同的数据对象为fasle

ceshi c1 = new ceshi("A");
ceshi c2 = new ceshi("A");
System.out.println(c1.equals(c2)); // false


//查看其源码
public boolean equals(Object obj) {
        return (this == obj);
}

而String改写了equals方法
所以比较的时候是比较值

String s1 = new String("A");
String s2 = new String("A");
System.out.println(s1.equals(s2)); // true

//查看其源码
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

3. 抽象类和接口类细节区分

先回顾其两者特点:

抽象类是类和类之间的共同特征,将这些共同特征进一步形成抽象类,由于类本身不存在,所以抽象类无法创建对象。
类到对象是实例化,对象到类是抽象
抽象方法不能被 final 修饰,因为抽象方法就是被子类实现的

  • 采用 abstract 关键字定义的类就是抽象类,采用 abstract 关键字定义的方法就是抽象方法
  • 抽象的方法只需在抽象类中,提供声明,不需要实现
  • 如果一个类中含有抽象方法,那么这个类必须定义成抽象类。抽象类中不一定有抽象方法,抽象方法必须出现在抽象类中
  • final和abstract不能同时同时使用,这两个关键字是对立的
  • 抽象类的子类可以是抽象类。也可以是非抽象类
  • 一个非抽象的类,继承抽象类,必须将抽象类中的抽象方法进行覆盖/重写/实现

接口是特殊的抽象类,类与类是继承extends,类与接口是实现implements,其实都是继承

  • 接口是一种“引用数据类型”,完全抽象的,支持多继承,且一个接口可以继承多个接口,只有常量+抽象方法
  • 所有的元素都是public修饰的,抽象方法的public abstract可以省略,常量的public static final可以省略,方法不能有方法体

通过其特点也可以讲述其不同
比如

  • 抽象类可以有构造函数;接口不能有
  • 类可以实现很多个接口;抽象类只能继承一个
  • 接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符

4. final关键字

  • final 修饰的类不能被继承
  • final 修饰的方法不能被覆盖
  • final 修饰的变量不能被修改
  • 构造方法不能被 final 修饰

变量在没有赋值的时候可以定义可以声明
但如果输出变量就必须给予定义以及赋值

5. String类细节

String不是基本数据类型,String属于引用类型
String类是一个final类,因此不能被继承

6. String、StringBuffer 和 StringBuilder 区别

String是一个final类表示的类容不可改变
StringBuffer表示的内容可以修改

StringBuffer 和 StringBuilder 区别:
StringBuffer是线程安全的可以在多线程中使用
StringBuilder是线程不安全的,但是运行效率非常高
具体详细的区别可看
探秘Java中的String、StringBuilder以及StringBuffer

7. super和this对比

this:

  • this 是一个引用,保存内存地址指向自己
  • this 不能出现在静态方法中
  • this 大部分情况下可以省略,在方法中区分实例变量和局部变量的时候不能省略
  • “this(实际参数列表)”出现在构造方法第一行,通过当前的构造方法去调用

本类当中其它的构造方法

super:
super 代表了当前对象中从父类继承过来的那部分特征。this 指向一个独立的对象

super与this共有的

  • super 和 this 都可以使用在实例方法当中
  • super 不能使用在静态方法当中,因为 super 代表了当前对象上的父类型特征,静态方法中没有 this,肯定也是不能使用 super 的
  • super 也有这种用法:“super(实际参数列表);”,这种用法是通过当前的构造方法调用父类的构造方法

==this 和 super 都是无法使用在静态方法当中的==

8. static与this对比

static和this指针的结合代码演示
static 的方法中不能直接访问实例变量,要访问实例变量必须先自己创建一个对象,通过“引用”可以去访问,不能通过 this 访问,因为在 static 方法中是不能存在 this 的

public class ThisTest {
    int i = 10;

    public static void main(String[] args) {
//这肯定是不行的,因为 main 方法带有 static,不能用 this
//System.out.println(this.i);
//可以自己创建一个对象
        ThisTest tt = new ThisTest();
//通过引用访问
        System.out.println(tt.i);
    }
}    

方法也同理,需要用对象去调用
实例方法必须先创建对象,通过引用去调用,在以上的 main 方法中并没有创建对象,更没有 this。

//错误代码示列:
public class ThisTest {
    public static void main(String[] args) {
        doSome();
    }
    public void doSome(){
        System.out.println("do some...");
    } }

正确代码示列:

public class ThisTest {
    public static void main(String[] args) {
        ThisTest tt = new ThisTest();
        tt.doSome();
    }
    public void doSome(){
        System.out.println("do some...");
    } }

总结:

this 不能使用在 static 的方法中,可以使用在实例方法中,代表当前对象,多数情况下 this 是可以省略不写的,但是在区分局部变量和实例变量的时候不能省略,在实例方法中可以直接访问当前对象实例变量以及实例方法,在 static 方法中无法直接访问实例变量和实例方法

9. 重写和重载对比

重写是⼦类对⽗类的允许访问的⽅法的实现过程进⾏重新编写, 返回值和形参都不能改变。即 外壳不变,核⼼重写!重写⽅法不能抛出新的检查异常或者⽐被重写⽅法申明更加宽泛的异常。

重载是在⼀个类⾥⾯,⽅法名字相同,⽽参数不同。返回类型可以相同也可以不同。

  • 重载:发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同。
  • 重写:发生在运行期,是子类对父类的允许访问的方法的实现过程进行重新编写。

1.返回值类型、方法名、参数列表必须相同,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。
2.如果父类方法访问修饰符为private/final/static则子类就不能重写该方法,但是被static修饰的方法能够被再次声明。
3.构造方法无法被重写

10. 静态方法和实例方法对比

  1. 在外部调⽤静态⽅法时,可以使⽤"类名.⽅法名"的⽅式,也可以使⽤"对象名.⽅法名"的⽅式。(调⽤静态⽅法可以⽆需创建对象。)

实例⽅法只有"对象名.⽅法名"这种⽅式。

  1. 静态⽅法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态⽅法), ⽽不允许访问实例成员变量和实例⽅法;实例⽅法则⽆此限制

11. 静态变量和实例变量对比

静态变量: 静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有⼀份,在类的加载过程中,JVM只为静态变量分配⼀次内存空间。

实例变量: 每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象 的,在内存中,创建⼏次对象,就有⼏份成员变量

12. final、finally与finalize对比

  • final是一个关键字。表示最终的。不变的
  • finally也是一个关键字,和try联合使用,使用在异常处理机制中
  • finalize()是Object类中的一个方法。作为方法名出现,finalize是标识符。这个方法是由垃圾回收器GC负责调用的

hashcode()与equals()

hashCode()的作用是获取哈希码,也称为散列码;它实际上是返回一个int 整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。散列表存储的是键值对(key-value),它的特点是:能根据“键"快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)

为什么重写equals()也要重写hashcode()方法
如果两个对象相等,则hashcode一定也是相同的。两个对象相等,对两个对象分别调用equals方法都返回true。但是,两个对象有相同的hashcode值,它们也不一定是相等的。因此,equals方法被覆盖过,则hashCode方法也必须被覆盖。

以"HashSet如何检查重复”为例子来说明为什么要有hashCode?
当把对象加入HashSet时,HashSet 会先计算对象的hashcode值来判断对象加入的位置,同时也会与其他已经加入的对象的hashcode值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同hashcode值的对象,这时会调用equals ()方法来检查hashcode相等的对象是否真的相同。如果两者相同,HashSet就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。

深拷贝与浅拷贝

  • 浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。
  • 深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。
相关文章
|
2月前
|
安全 架构师 Java
Java大厂面试高频:Collection 和 Collections 到底咋回答?
Java中的`Collection`和`Collections`是两个容易混淆的概念。`Collection`是集合框架的根接口,定义了集合的基本操作方法,如添加、删除等;而`Collections`是一个工具类,提供了操作集合的静态方法,如排序、查找、同步化等。简单来说,`Collection`关注数据结构,`Collections`则提供功能增强。通过小王的面试经历,我们可以更好地理解这两者的区别及其在实际开发中的应用。希望这篇文章能帮助你掌握这个经典面试题。
58 4
|
4月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
144 2
|
2月前
|
Java 程序员
Java社招面试中的高频考点:Callable、Future与FutureTask详解
大家好,我是小米。本文主要讲解Java多线程编程中的三个重要概念:Callable、Future和FutureTask。它们在实际开发中帮助我们更灵活、高效地处理多线程任务,尤其适合社招面试场景。通过 Callable 可以定义有返回值且可能抛出异常的任务;Future 用于获取任务结果并提供取消和检查状态的功能;FutureTask 则结合了两者的优势,既可执行任务又可获取结果。掌握这些知识不仅能提升你的编程能力,还能让你在面试中脱颖而出。文中结合实例详细介绍了这三个概念的使用方法及其区别与联系。希望对大家有所帮助!
198 60
|
27天前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
103 14
|
1月前
|
安全 Java 程序员
Java 面试必问!线程构造方法和静态块的执行线程到底是谁?
大家好,我是小米。今天聊聊Java多线程面试题:线程类的构造方法和静态块是由哪个线程调用的?构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节有助于掌握Java多线程机制。下期再见! 简介: 本文通过一个常见的Java多线程面试题,详细讲解了线程类的构造方法和静态块是由哪个线程调用的。构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节对掌握Java多线程编程至关重要。
57 13
|
2月前
|
算法 安全 Java
Java线程调度揭秘:从算法到策略,让你面试稳赢!
在社招面试中,关于线程调度和同步的相关问题常常让人感到棘手。今天,我们将深入解析Java中的线程调度算法、调度策略,探讨线程调度器、时间分片的工作原理,并带你了解常见的线程同步方法。让我们一起破解这些面试难题,提升你的Java并发编程技能!
100 16
|
2月前
|
Java 程序员 调度
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
87 9
|
2月前
|
安全 Java 程序员
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
77 12
|
2月前
|
监控 Dubbo Java
Java Dubbo 面试题
Java Dubbo相关基础面试题
|
2月前
|
SQL Java 数据库连接
Java MyBatis 面试题
Java MyBatis相关基础面试题

热门文章

最新文章