Java基础知识八股

1.面向对象基础

1.面向对象和面向过程的区别?

面向对象和面向过程是一种软件开发思想。

两者的主要区别在于解决问题的方式不同:

  • 面向过程把解决问题的过程拆成一个个方法,通过一个个方法的执行解决问题。
  • 面向对象会先抽象出对象,然后用对象执行方法的方式解决问题。

2.创建一个对象用什么运算符?对象实体与对象引用有何不同?

new 运算符,new 创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。

  • 一个对象引用可以指向 0 个或 1 个对象(一根绳子可以不系气球,也可以系一个气球);
  • 一个对象可以有 n 个引用指向它(可以用 n 条绳子系住一个气球)

3.对象的相等和引用相等的区别

  • 对象的相等一般比较的是内存中存放的内容是否相等。
  • 引用相等一般比较的是他们指向的内存地址是否相等。
String str1 = "hello";
String str2 = new String("hello");
String str3 = "hello";
// 使用 == 比较字符串的引用相等
System.out.println(str1 == str2);
System.out.println(str1 == str3);
// 使用 equals 方法比较字符串的相等
System.out.println(str1.equals(str2));
System.out.println(str1.equals(str3));
false
true
true
true

4.方法重载和重写的区别?

同个类中的多个方法可以有相同的方法名称,但是有不同的参数列表,这就称为方法重载。参数列表又叫参数签名,包括参数的类型、参数的个数、参数的顺序,只要有一个不同就叫做参数列表不同。

重载是面向对象的一个基本特性。

方法的重写描述的是父类和子类之间的。当父类的功能无法满足子类的需求,可以在子类对方法进行重写。方法重写时, 方法名与形参列表必须一致。

如下代码,Person为父类,Student为子类,在Student中重写了dailyTask方法。

public class Person {
    private String name;
    
    public void dailyTask() {
        System.out.println("work eat sleep");
    }
}


public class Student extends Person {
    @Override
    public void dailyTask() {
        System.out.println("study eat sleep");
    }

5.构造方法有哪些特点?是否可被 override?

构造方法特点如下:

  • 名字与类名相同。
  • 没有返回值,但不能用 void 声明构造函数。
  • 生成类的对象时自动执行,无需调用。

构造方法不能被 override(重写),但是可以 overload(重载),所以你可以看到一个类中有多个构造函数的情况。

public class MyClass {
    private int myVariable;

    public MyClass(int myVariable) {
        this.myVariable = myVariable;
    }
}

6.面向对象三大特性

面向对象三大特性:封装,继承,多态

1.封装

1、封装就是将类的信息隐藏在类内部,不允许外部程序直接访问,而是通过该类的方法实现对隐藏信息的操作和访问。 良好的封装能够减少耦合。

2.继承

2、继承是从已有的类中派生出新的类,新的类继承父类的属性和行为,并能扩展新的能力,大大增加程序的重用性和易维护性。在Java中是单继承的,也就是说一个子类只有一个父类。

3.多态

多态是同一个行为具有多个不同表现形式的能力。在不修改程序代码的情况下改变程序运行时绑定的代码。实现多态的三要素:继承、重写、父类引用指向子类对象。

  • 静态多态性:通过重载实现,相同的方法有不同的參数列表,可以根据参数的不同,做出不同的处理。
  • 动态多态性:在子类中重写父类的方法。运行期间判断所引用对象的实际类型,根据其实际类型调用相应的方法。

举例:有一个动物类和他的2个子类猫和狗,他们都有一个名为makesound的方法,但是每种动物发出的声音是不同的。

7.接口和抽象类有什么共同点和区别?

接口和抽象类都是用于实现多态性的机制,它们在定义上有一些共同点,但也有一些关键的区别。具体分析如下:

  • 共同点
  1. 两者都不能直接实例化,需要由具体的子类或实现类来进行实例化。
  2. 都可以包含抽象方法,这些抽象方法需要由继承或实现它们的类来提供具体的实现。
  • 不同点
  1. 语法和声明方式:接口使用interface关键字进行声明,而抽象类使用abstract关键字进行声明。
  2. 成员变量:接口只能定义公共静态最终字段(即常量),不能定义普通成员变量;而抽象类可以定义各种类型的成员变量。
  3. 构造函数:接口没有构造函数,而抽象类可以有构造函数。
  4. 方法实现:接口中的方法默认都是公共的抽象方法,不包含具体的实现代码;而抽象类可以包含抽象方法和非抽象方法,其中抽象方法没有具体的实现,而非抽象方法有具体的实现代码。
  5. 继承与实现:一个类可以实现多个接口,但只能继承一个抽象类。
  6. 访问修饰符:抽象方法必须为public或者protected,默认为public;接口中的方法默认为public abstract。
  7. 静态成员:接口中可以定义默认方法和静态方法(JDK 8及以上版本),而抽象类可以有静态代码块和静态方法。

总的来说,接口主要用于定义全局的规范,而抽象类则用于描述具有部分实现的共性。选择使用接口还是抽象类取决于具体的设计需求。

8.面向对象编程的六大原则?

  • 对象单一职责:我们设计创建的对象,必须职责明确,比如商品类,里面相关的属性和方法都必须跟商品相关,不能出现订单等不相关的内容。这里的类可以是模块、类库、程序集,而不单单指类。
  • 里式替换原则:子类能够完全替代父类,反之则不行。通常用于实现接口时运用。因为子类能够完全替代基(父)类,那么这样父类就拥有很多子类,在后续的程序扩展中就很容易进行扩展,程序完全不需要进行修改即可进行扩展。比如IA的实现为A,因为项目需求变更,现在需要新的实现,直接在容器注入处更换接口即可.
  • 迪米特法则,也叫最小原则,或者说最小耦合。通常在设计程序或开发程序的时候,尽量要高内聚,低耦合。当两个类进行交互的时候,会产生依赖。而迪米特法则就是建议这种依赖越少越好。就像构造函数注入父类对象时一样,当需要依赖某个对象时,并不在意其内部是怎么实现的,而是在容器中注入相应的实现,既符合里式替换原则,又起到了解耦的作用。
  • 开闭原则:开放扩展,封闭修改。当项目需求发生变更时,要尽可能的不去对原有的代码进行修改,而在原有的基础上进行扩展。
  • 依赖倒置原则:高层模块不应该直接依赖于底层模块的具体实现,而应该依赖于底层的抽象。接口和抽象类不应该依赖于实现类,而实现类依赖接口或抽象类。
  • 接口隔离原则:一个对象和另外一个对象交互的过程中,依赖的内容最小。也就是说在接口设计的时候,在遵循对象单一职责的情况下,尽量减少接口的内容

9.深拷贝和浅拷贝区别了解吗?什么是引用拷贝?

0.什么是深拷贝和浅拷贝?

浅拷贝

被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。

简而言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。

深拷贝

深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。

简而言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

1.浅拷贝示例代码

浅拷贝(Shallow Copy): 可以使用Object.clone()方法进行浅拷贝。需要注意的是,要使一个类支持浅拷贝,必须实现Cloneable接口并重写clone()方法。

class Address implements Cloneable{
    private String name;

    public Address(String s) {
        name = s;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    // 省略构造函数、Getter&Setter方法
    @Override
    public Address clone() {
        try {
            return (Address) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}
class Person implements Cloneable {
    private Address address;

    public Person(Address address) {
        this.address = address;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    // 省略构造函数、Getter&Setter方法
    @Override
    public Person clone() {
        try {
            Person person = (Person) super.clone();
            return person;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}
public class Test{
    public static void main(String[] args) {
        Person person1 = new Person(new Address("武汉"));
        Person person1Copy = person1.clone();
// true
        System.out.println(person1.getAddress() == person1Copy.getAddress());

    }
}

//person1 的克隆对象和 person1 使用的仍然是同一个 Address 对象。

2.深拷贝示例代码

  @Override
    public Person clone() {
        try {
            Person person = (Person) super.clone();
            person.setAddress(person.getAddress().clone());
            return person;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}
public class Test{
    public static void main(String[] args) {
        Person person1 = new Person(new Address("武汉"));
        Person person1Copy = person1.clone();
// false
        System.out.println(person1.getAddress() == person1Copy.getAddress());

    }
}
// person1 的克隆对象和 person1 包含的 Address 对象已经是不同的了

2.Java基础知识

0.什么是值传递和引用传递?

  • 值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。
  • 引用传递一般是对于对象型变量而言的,传递的是该对象地址的一个副本,并不是原对象本身,两者指向同一片内存空间。所以对引用对象进行操作会同时改变原对象。

java中不存在引用传递,只有值传递。即不存在变量a指向变量b,变量b指向对象的这种情况。

举例

public static void main(String[] args) {
    int num1 = 10;
    int num2 = 20;
    swap(num1, num2);
    System.out.println("num1 = " + num1);
    System.out.println("num2 = " + num2);
}

public static void swap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
    System.out.println("a = " + a);
    System.out.println("b = " + b);
}
a = 20
b = 10
num1 = 10
num2 = 20

1.c++和java的区别

C++和Java都是广泛使用的编程语言,但它们在多个方面存在显著差异。

  1. 面向对象性:Java是一种纯粹的面向对象编程语言,而C++既支持面向过程编程,也支持面向对象编程。在C++中,并非所有元素都必须是对象,你仍然可以有全局函数和全局变量。相比之下,Java中的所有代码(包括函数、变量)都必须在类中定义。
  2. 内存管理:C++允许程序员直接管理内存,包括使用指针和手动分配及释放内存。这提供了更高的控制能力,但也增加了出错的风险,如内存泄露和空悬指针等问题。相反,Java自动进行垃圾回收(GC),负责监控并自动回收不再被引用的对象的内存空间,简化了内存管理,但也可能导致不可预测的GC暂停时间。
  3. 跨平台能力:Java的一个主要优点是其跨平台能力,Java代码在任何安装了Java虚拟机(JVM)的系统上都可以运行不变。C++代码则通常需要针对每个目标平台重新编译,虽然C++代码也可以跨平台,但需要更多的工作来适应不同的系统和编译器。
  4. 执行速度:C++通常提供比Java更快的执行速度,因为Java代码在运行时需要通过JVM转换为机器码,这一中间步骤会引入性能开销。C++代码直接编译成机器码,因此通常执行更快,但这也意味着C++程序更接近硬件层面,给开发者更多优化的空间。
  5. 语言特性:C++拥有一些Java不支持的特性,例如运算符重载、多重继承和强制类型转换等。而Java设计上避免了这些可能导致混淆和错误的特性。
  6. 易用性和学习曲线:由于Java简化了内存管理和垃圾回收机制,通常认为Java比C++更容易学习和使用。C++的学习曲线更陡峭,因为它涉及更多底层的概念和复杂性。

综上所述,两种语言各有优势和用途。选择使用哪种语言通常取决于项目需求、开发环境和目标平台。C++适合需要高性能和紧密硬件集成的系统级应用,而Java适合快速开发跨平台的应用程序。

2.Java的特点

Java是一门面向对象的编程语言

Java具有平台独立性和移植性

  • Java有一句口号:Write once, run anywhere,一次编写、到处运行。这也是Java的魅力所在。而实现这种特性的正是Java虚拟机JVM。已编译的Java程序可以在任何带有JVM的平台上运行。你可以在windows平台编写代码,然后拿到linux上运行。只要你在编写完代码后,将代码编译成.class文件,再把class文件打成Java包,这个jar包就可以在不同的平台上运行了。

Java具有稳健性

  • Java是一个强类型语言,它允许扩展编译时检查潜在类型不匹配问题的功能。Java要求显式的方法声明,它不支持C风格的隐式声明。这些严格的要求保证编译程序能捕捉调用错误,这就导致更可靠的程序。
  • 异常处理是Java中使得程序更稳健的另一个特征。异常是某种类似于错误的异常条件出现的信号。使用try/catch/finally语句,程序员可以找到出错的处理代码,这就简化了出错处理和恢复的任务

3.Java是如何实现跨平台的?

Java是通过JVM(Java虚拟机)实现跨平台的。

JVM可以理解成一个软件,不同的平台有不同的版本。我们编写的Java代码,编译后会生成.class 文件(字节码文件)。Java虚拟机就是负责将字节码文件翻译成特定平台下的机器码,通过JVM翻译成机器码之后才能运行。不同平台下编译生成的字节码是一样的,但是由JVM翻译成的机器码却不一样。

只要在不同平台上安装对应的JVM,就可以运行字节码文件,运行我们编写的Java程序。

因此,运行Java程序必须有JVM的支持,因为编译的结果不是机器码,必须要经过JVM的翻译才能执行

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

先看看什么是编译型语言和解释型语言。

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

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

5.JDK/JRE/JVM三者的关系

JVM

英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。Java 能够跨平台运行的核心在于 JVM 。

所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。也就是说class文件并不直接与机器的操作系统交互,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。

针对不同的系统有不同的 jvm 实现,有 Linux 版本的 jvm 实现,也有Windows 版本的 jvm 实现,但是同一段代码在编译后的字节码是一样的。这就是Java能够跨平台,实现一次编写,多处运行的原因所在。

JRE

英文名称(Java Runtime Environment),就是Java 运行时环境。我们编写的Java程序必须要在JRE才能运行。它主要包含两个部分,JVM 和 Java 核心类库。

JRE是Java的运行环境,并不是一个开发环境,所以没有包含任何开发工具,如编译器和调试器等。

如果你只是想运行Java程序,而不是开发Java程序的话,那么你只需要安装JRE即可。

JDK

英文名称(Java Development Kit),就是 Java 开发工具包

可以看到,JDK目录下有个JRE,也就是JDK中已经集成了 JRE,不用单独安装JRE。

另外,JDK中还有一些好用的工具,如jinfo,jps,jstack等。

最后,总结一下JDK/JRE/JVM,他们三者的关系

JRE = JVM + Java 核心类库

JDK = JRE + Java工具 + 编译器 + 调试器

6.Java创建对象有几种方式?

Java创建对象有以下几种方式:

  • 用new语句创建对象。
  • 使用反射,使用Class.newInstance()创建对象。
  • 调用对象的clone()方法。
  • 运用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法。

7.说说类实例化的顺序

Java中类实例化顺序:

  1. 静态属性,静态代码块。
  2. 普通属性,普通代码块。
  3. 构造方法。

8.Java的4种引用类型

在java1.2之后,java对引用的概念进行了扩充,将引用分为强引用、软引用、弱引用、虚引用,这4种引用强度依次逐渐减弱。

  • 强引用(Strong Reference):在程序代码之中普遍存在的,类似 Object obj = new Object() 这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象
  • 软引用(Soft Reference):用来描述一些还有用但并非必需的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收。如果这次回收还没有足够的内存才会抛出内存溢出异常
  • 弱引用(Weak Reference):用来描述非必需对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象
  • 虚引用(Phantom Reference):它是最弱的一种引用关系。一个对象是否有虚引用存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知

3.Java数据类型

1.Java的基本数据类型有哪些?每个占多少位?

  • byte,8bit
  • char,16bit
  • short,16bit
  • int,32bit
  • float,32bit
  • long,64bit
  • double,64bit
  • boolean,只有两个值:true、false,可以使⽤用 1 bit 来存储
简单类型 boolean byte char short Int long float double
二进制位数 1 8 16 16 32 64 32 64
包装类 Boolean Byte Character Short Integer Long Float Double

在Java规范中,没有明确指出boolean的大小。在《Java虚拟机规范》给出了单个boolean占4个字节,和boolean数组1个字节的定义,具体 还要看虚拟机实现是否按照规范来,因此boolean占用1个字节或者4个字节都是有可能的。

2.了解Java的包装类型吗?为什么需要包装类?

Java包装类型有8种,分别是:1、Byte;2、Integer;3、Short;4、Long;5、Float;6、Double;7、Boolean;8、Character。

Java 是一种面向对象语言,很多地方都需要使用对象而不是基本数据类型。比如,在集合类中,我们是无法将 int 、double 等类型放进去的。因为集合的容器要求元素是 Object 类型。

为了让基本类型也具有对象的特征,就出现了包装类型。相当于将基本类型包装起来,使得它具有了对象的性质,并且为其添加了属性和方法,

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Java抽象带蓝子的笔记专栏 文章被收录于专栏

我的笔记专栏,内有自己整理的八股知识笔记和算法刷题笔记,我会不断通过他人和自己的面经来更新和完善自己的八股笔记。专栏每增加一篇文章费用就会上涨一点,如果你喜欢的话建议你尽早订阅。

全部评论
篮子哥算法咋准备的
点赞 回复
分享
发布于 03-25 20:16 浙江

相关推荐

点赞 评论 收藏
转发
8 49 评论
分享
牛客网
牛客企业服务