Java面试–代码解析版
本文最后更新于261 天前,其中的信息可能已经过时,如有错误请发送邮件到2067863254@qq.com

一.Java基础

基础概念与常识Java语言有哪些特点:

1.面向对象:支持封装,继承和多态三大特性;代码以类和对象为单位

public class Animal {
    public void sound() {
        System.out.println("动物发出声音");
    }
}

public class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("汪汪汪");
    }
}

2.平台无关性

3.强类型语言

4.自动内存管理

5.多线程支持:内置对多线程编程的支持;通过Thread类或者Runnable接口创建线程;提供synchronized和lock实现同步机制

public class MyThread implements Runnable {
    @Override
    public void run() {
        System.out.println("线程正在执行");
    }
}

JVM vs JDK vs JRE

JVM

java虚拟机是运行java字节码的虚拟机。字节码和不同系统的JVM实现是java语言“一次编译,随处可以运行”的关键所在

JDK和jRE

JDK它是功能齐全的javaSDk,是提供给开发者使用,能够创建和编译Java程序的开发套件。他包含JRE,同时还包含了编译 java 源码的编译器 javac 以及一些其他工具比如 javadoc(文档注释工具)、jdb(调试器)、jconsole(基于 JMX 的可视化监控⼯具)、javap(反编译工具)等等。

JRE(Java Runtime Environment) 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有内容的集合,主要包括 Java 虚拟机(JVM)、Java 基础类库(Class Library)。

也就是说,JRE 是 Java 运行时环境,仅包含 Java 应用程序的运行时环境和必要的类库。而 JDK 则包含了 JRE,同时还包括了 javac、javadoc、jdb、jconsole、javap 等工具,可以用于 Java 应用程序的开发和调试。如果需要进行 Java 编程工作,比如编写和编译 Java 程序、使用 Java API 文档等,就需要安装 JDK。而对于某些需要使用 Java 特性的应用程序,如 JSP 转换为 Java Servlet、使用反射等,也需要 JDK 来编译和运行 Java 代码。因此,即使不打算进行 Java 应用程序的开发工作,也有可能需要安装 JDK。

不过,从 JDK 9 开始,就不需要区分 JDK 和 JRE 的关系了,取而代之的是模块系统(JDK 被重新组织成 94 个模块)+ jlinkopen in new window 工具 (随 Java 9 一起发布的新命令行工具,用于生成自定义 Java 运行时映像,该映像仅包含给定应用程序所需的模块) 。并且,从 JDK 11 开始,Oracle 不再提供单独的 JRE 下载。

什么是字节码?采用字节码的好处是什么?

在Java中,JVM可以理解的代码就叫做字节码(即扩展名为.class的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。

需要格外注意的是 .class->机器码 这一步。在这一步 JVM 类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度会相对比较慢。而且,有些方法和代码块是经常需要被调用的(也就是所谓的热点代码),所以后面引进了 JIT(Just in Time Compilation) 编译器,而 JIT 属于运行时编译。当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。而我们知道,机器码的运行效率肯定是高于 Java 解释器的。这也解释了我们为什么经常会说 Java 是编译与解释共存的语言 。

为什么说java语言“编译与解释并存”?

我们可以将高级编程语言安装程序的执行方式分为两种:

编译型:编译型语言open in new window 会通过编译器open in new window将源代码一次性翻译成可被该平台执行的机器码。一般情况下,编译语言的执行速度比较快,开发效率比较低。常见的编译性语言有 C、C++、Go、Rust 等等。

解释型:解释型语言open in new window会通过解释器open in new window一句一句的将代码解释(interpret)为机器代码后再执行。解释型语言开发效率比较快,执行速度比较慢。常见的解释性语言有 Python、JavaScript、PHP 等等。

为什么说java语言“编译与解释并存”?这是因为 Java 语言既具有编译型语言的特征,也具有解释型语言的特征。因为 Java 程序要经过先编译,后解释两个步骤,由 Java 编写的程序需要先经过编译步骤,生成字节码(.class 文件),这种字节码必须由 Java 解释器来解释执行。

java有哪些数据类型

定义:Java语言是强类型语言,对于每一种数据都定义了明确的具体的数据类 型,在内存中分配了不同大小的内存空间。

java三大特性

封装

定义: 封装是指将对象的状态(属性)和行为(方法)捆绑在一起,并对外部隐藏对象的内部实现细节,仅提供公共的访问方式。通过封装,可以保护数据不被外部随意访问和修改,提高代码的安全性和可维护性。

// 定义一个 Person 类
class Person {
    // 私有属性,外部无法直接访问
    private String name;
    private int age;

    // 公共的 getter 方法,用于获取 name 属性
    public String getName() {
        return name;
    }

    // 公共的 setter 方法,用于设置 name 属性
    public void setName(String name) {
        this.name = name;
    }

    // 公共的 getter 方法,用于获取 age 属性
    public int getAge() {
        return age;
    }

    // 公共的 setter 方法,用于设置 age 属性
    public void setAge(int age) {
        if (age >= 0) {
            this.age = age;
        } else {
            System.out.println("年龄不能为负数");
        }
    }
}

public class EncapsulationExample {
    public static void main(String[] args) {
        Person person = new Person();
        // 通过 setter 方法设置属性值
        person.setName("张三");
        person.setAge(25);
        // 通过 getter 方法获取属性值
        System.out.println("姓名: " + person.getName());
        System.out.println("年龄: " + person.getAge());
    }
}

解释: 在上述代码中,Person 类的 name 和 age 属性被声明为 private,这意味着它们只能在 Person 类内部被访问。外部代码要访问和修改这些属性,必须通过公共的 getter 和 setter 方法。这样可以对属性的访问进行控制,例如在 setAge 方法中,添加了对年龄的合法性检查,避免了非法数据的输入。

继承

**定义:**继承是指一个类(子类)可以继承另一个类(父类)的属性和方法,从而实现代码的复用和扩展。子类可以拥有父类的所有非私有属性和方法,并且可以根据需要添加自己的属性和方法,或者重写父类的方法。

// 定义一个父类 Animal
class Animal {
    // 父类的属性
    protected String name;

    // 父类的方法
    public void eat() {
        System.out.println(name + " 正在吃东西");
    }
}

// 定义一个子类 Dog,继承自 Animal 类
class Dog extends Animal {
    // 子类的方法
    public void bark() {
        System.out.println(name + " 正在汪汪叫");
    }
}

public class InheritanceExample {
    public static void main(String[] args) {
        Dog dog = new Dog();
        // 子类可以使用父类的属性
        dog.name = "旺财";
        // 子类可以调用父类的方法
        dog.eat();
        // 子类可以调用自己的方法
        dog.bark();
    }
}

多态

定义: 多态是指同一个方法调用可以根据对象的不同类型而表现出不同的行为。多态的实现依赖于继承和方法重写,通过父类引用指向子类对象,在运行时根据实际对象的类型来调用相应的方法。

// 定义一个父类 Shape
class Shape {
    public void draw() {
        System.out.println("绘制图形");
    }
}

// 定义一个子类 Circle,继承自 Shape 类,并重写 draw 方法
class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println("绘制圆形");
    }
}

// 定义一个子类 Rectangle,继承自 Shape 类,并重写 draw 方法
class Rectangle extends Shape {
    @Override
    public void draw() {
        System.out.println("绘制矩形");
    }
}

public class PolymorphismExample {
    public static void main(String[] args) {
        // 父类引用指向子类对象
        Shape circle = new Circle();
        Shape rectangle = new Rectangle();

        // 调用 draw 方法,根据实际对象的类型表现出不同的行为
        circle.draw();
        rectangle.draw();
    }
}

重载和重写的区别

重写

从字面上看,重写就是重新写一遍的意思。其实就是子类把父类的方法重新写一遍。子类继承了父类原有的方法,但有时子类不想原封不动地继承父类的方法,这是就可以在方法名,参数列表,返回类型((除过子类中方法的返回值是父类中方法返回值的子类时)都相同的情况下,对方法体进行修改或重写,这就是重写。但要注意子类函数的访问修饰权限不能低于父类的。

public class Father {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Son s = new Son();
        s.sayHello();
    }

    public void sayHello() {
        System.out.println("Hello");
    }
}

class Son extends Father{

    @Override
    public void sayHello() {
    、    // TODO Auto-generated method stub
        System.out.println("hello by ");
    }

}

重写总结

发生在父类和子类之间

方法名,参数列表,返回类型(除过子类方法中的返回类型是父类返回类型的子类)必须相同

访问修饰符的限制一定要大于被重写方法的访问修饰符

重写方法一定不能抛出新的检查异常或者比重写方法更加宽泛的检查型异常

重载

在一个类中,同名的方法如果有不同的参数列表(参数类型不同,参数个数不同甚至是参数的顺序不同)则视为重载。同时,重载对返回类型没有要求,可以相同也可以不同,但不能通过返回类型是否相同去判断重载

public class Father {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Father s = new Father();
        s.sayHello();
        s.sayHello("wintershii");

    }

    public void sayHello() {
        System.out.println("Hello");
    }

    public void sayHello(String name) {
        System.out.println("Hello" + " " + name);
    }
}

重载总结

重载是一个类中多态性的一种表现

重载要求同名方法参数列表不同(参数类型,参数个数甚至是参数顺序)

重载的时候,返回值类型可以相同也可以不相同,不可以以返回值类型去判断作为重载函数的标准

面试时,问:重载(Overload)和重写(Override)的区别?

答:方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求,不能根据返回类型进行区分。

访问修饰符public,private,protected,以及不写(默认)时的 区别

定义:Java中,可以使用访问修饰符来保护对类、变量、方法和构造方法的访 问。Java 支持 4 种不同的访问权限。

private:在同一类内可见。使用对象:方法,变量。注意不能修饰类(外部类)

default:(即缺省,什么也不写,不使用任何关键字):在同一包内可见,不使用任何修饰符。使用对象:类,接口,变量,方法。

protect:对同一包内的类和所有子类可见。使用对象:变量,方法。注意不能修饰类(外部类)

public:对所有类可见。使用对象:类,接口,变量,方法。

==与equal的区别

==对于基本类型和引用类型的作用效果是不同的:对于基本数据类型来说,==比较的是值;对于引用类型来说,==比较的是对象的内存地址。

因为java只有值传递,所以,对于==来说,不管是比较基本数据类型还是引用数据类型的变量,其本质比较的都是值,只是引用类型变量存的值是对象的地址

equals()不能用于判断基本数据类型的变量,只能用来判断两个对象是否相等。equals()方法存在于Object类中,而Object类是所有类的直接或间接父类,所以所有的类都有equals()方法

equals()方法存在两种使用情况:

类没有重写equals()方法:通过equals()比较该类的两个对象时,等价于通过“==”比较这两个对象,使用的默认是Object类equals()方法

类重写了equals()方法:一般我们重写equals()方法来比较两个对象中的属性是否相等;若他们的属性相等,则返回true

String a = new String("ab"); // a 为一个引用
String b = new String("ab"); // b为另一个引用,对象的内容一样
String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
System.out.println(aa == bb);// true
System.out.println(a == b);// false
System.out.println(a.equals(b));// true
System.out.println(42 == 42.0);// true

String 中的 equals 方法是被重写过的,因为 Object 的 equals 方法是比较的对象的内存地址,而 String 的 equals 方法比较的是对象的值。

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;
}

hashCode() 有什么用?

hashCode() 的作用是获取哈希码(int 整数),也称为散列码。这个哈希码的作用是确定该对象在哈希表中的索引位置。

&和&&的区别

用法: &&和&都是表示 与
区别是:&&若第一个条件不满足,后面条件就不再判断。而&要对所有的条件都进行判断
返回值:true/false

| 和 || 的区别

用法:|| 和 | 都是表示 或
区别: || 若第一个条件满足,后面条件就不再判断。而 | 要对所有的条件都进行判断
返回值:true/false

String、StringBuffer、StringBuilder的区别

三者共同之处:都是final类,不允许被继承,主要是从性能和安全性上考虑的,因为这几个类都是经常被使用着,且考虑到防止其中的参数被参数修改影响到其他的应用。

StringBuffer是线程安全,可以不需要额外的同步用于多线程中;
StringBuilder是非同步,运行于多线程中就需要使用着单独同步处理,但是速度就比StringBuffer快多了;
StringBuffer与StringBuilder两者共同之处:可以通过append、indert进行字符串的操作。
String实现了三个接口:Serializable、Comparable、CarSequence

执行速度由快到慢:StringBuilder > StringBuffer > String

  • 如果要操作少量的数据用 String;
  • 多线程操作字符串缓冲区下操作大量数据 StringBuffer;
  • 单线程操作字符串缓冲区下操作大量数据 StringBuilder。

反射

定义:在运行过程中,对于任何一个类都能获取它的属性和方法,任何一个对象都能调用其方法,动态获取信息和动态调用,就是反射

java获取反射的三种方法:

通过new对象实现反射机制

通过路径实现反射机制

通过类名实现反射机制

抽象类和接口的区别

抽象类只能单继承,接口可以实现多个

抽象类有构造方法,接口没有构造方法

抽象类可以有实例变量,接口中没有实例变量,有常量

抽象类可以包含非抽象方法,接口在java7之前所有方法都是抽象的,java8之后可以包含非抽象方法

抽象类中方法可以是任意修饰符,接口中java8之前都是public,java9支持private

小记:普通类是亲爹,手把手教你怎么学,抽象类(多个类具有想相同的东西,拿出来放抽象类)是师傅,教你一部分秘籍,然后告诉你怎么学。接口(规范了某些行为)是干爹,只给你秘籍,怎么学全靠你

Error和Exception有什么区别

Error:程序无法处理,比较严重的问题,程序会立即崩溃,jvm停止运行

Exception:程序本身可以处理(向上抛出或者捕获)。编译时异常和运行时异常

final关键字有哪些用法?

修饰类:不能被继承

修饰方法:不能被重写

修饰变量:声明时给定初始值,只能读取不能修改。如果是对象引用不能改,但是对象的属性可以修改

用最有效率的方法计算 2 乘以 8

2 << 3(左移 3 位相当于乘以 2 的 3 次方,右移 3 位相当于除以 2 的 3 次 方)。

final、finally、finalize区别

final可以修饰类,变量,方法;修饰类表示该类不能被继承,修饰方法表示该方法不能被重写,修饰变量表示该变量是一个常量不能被重新赋值

finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码

finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调用,当我们调用System.gc()方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的最后判断

this关键字的用法

this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。

this的用法在java中大体可以分为3种:

普通的直接引用,this相当于是指向当前对象本身

形参与成员名字重名,用this来区分

引用本类的构造函数

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇