java基础

2023-12-13 23:16:41

Java基础


前言

基础不牢,地动山摇。要成为一名优秀的Java开发工程师,必须对Java基础掌握的非常牢固。学习在于日积月累,坚持不懈,以至熟能生巧尔。


java基本类型和包装类型的区别?

基本类型的特点是它们是直接存储在内存中的,占用固定的内存空间,并且没有对应的方法或属性。

包装类型是为了方便在基本类型和对象之间进行转换而引入的。每个基本类型都有对应的包装类型,包装类型的命名与对应的基本类型相似,但首字母大写。例如:

Byte:对应 byte
Short:对应 short
Integer:对应 int
Long:对应 long
Float:对应 float
Double:对应 double
Character:对应 char
Boolean:对应 boolean
包装类型是类,因此它们具有对应的方法和属性,可以进行更多的操作,比如进行数学计算、转换为字符串等。包装类型还提供了常量和静态方法来操作基本类型的数据。

另外,包装类型还具有自动装箱(Autoboxing)和自动拆箱(Unboxing)的功能。自动装箱是指将基本类型自动转换为对应的包装类型,而自动拆箱是指将包装类型自动转换为对应的基本类型。

总结起来,基本类型是简单的数据类型,直接存储在内存中,而包装类型是对基本类型的封装,提供了更多的功能和操作。在需要使用对象的场景下,可以使用包装类型,而在需要更高效的存储和计算时,可以使用基本类型。


包装类型的缓存机制了解么?

为了提高性能和节省内存,Java在某些情况下会对包装类型的对象进行缓存。具体来说,对于某些范围内的整数和一些常用的浮点数,Java会缓存对应的包装类型对象,以便重复使用,而不是每次都创建新的对象。

缓存机制适用于以下的情况:

整数缓存:对于byte和short范围内的整数(-128到127之间),以及Integer类中预先缓存的整数(-128到127之间),会被缓存为对象,以便重复使用。

Integer a = 10;
Integer b = 10;
System.out.println(a == b); // 输出 true

常用浮点数缓存:对于Float和Double类中预先缓存的一些常用浮点数(如0.0、1.0等),会被缓存为对象,以便重复使用。

Float a = 1.0f;
Float b = 1.0f;
System.out.println(a == b); // 输出 true

需要注意的是,缓存机制只适用于自动装箱的情况,即通过赋值操作或方法调用将基本类型转换为包装类型。如果使用显式的构造函数创建包装类型对象,那么不会使用缓存,而是每次都创建新的对象。

Integer a = new Integer(10);
Integer b = new Integer(10);
System.out.println(a == b); // 输出 false

因此,在比较包装类型对象时,应该使用.equals()方法而不是==运算符,以确保比较的是对象的值而不是引用。

Integer a = 10;
Integer b = 10;
System.out.println(a.equals(b)); // 输出 true

需要注意的是,缓存机制是Java虚拟机的实现相关的,不同的虚拟机实现可能会有不同的缓存策略。因此,在编写代码时,不应该依赖于包装类型的缓存机制,而应该始终使用.equals()方法来比较包装类型对象的值。


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

构造方法(Constructor)是用于创建对象并初始化对象的特殊方法。构造方法具有以下几个特点:

  1. 方法名与类名相同:构造方法的方法名必须与类名完全相同,包括大小写。

  2. 没有返回类型:构造方法没有返回类型,包括 void。它们的主要目的是初始化对象,而不是返回值。

  3. 可以有参数:构造方法可以接受参数,用于在创建对象时传递初始值。

  4. 可以重载:同一个类可以定义多个构造方法,只要它们的参数列表不同即可。这样可以根据不同的参数组合来创建对象。

  5. 默认构造方法:如果在类中没有显式定义任何构造方法,Java会自动提供一个无参的默认构造方法。默认构造方法不接受任何参数,执行的操作通常是对成员变量进行默认初始化。

构造方法在对象创建时被调用,用于初始化对象的状态。它们通常用于执行以下操作:

  1. 初始化成员变量:构造方法可以在对象创建时对成员变量进行初始化,为对象提供初始值。

  2. 执行必要的操作:构造方法可以执行一些必要的操作,如打开文件、建立数据库连接等。

构造方法可以被继承,但不能被直接重写(override)。子类可以定义与父类相同的构造方法,但并不是重写父类的构造方法,而是在子类中提供了一个独立的构造方法。在子类的构造方法中,可以通过使用 super() 关键字调用父类的构造方法来完成父类的初始化。

需要注意的是,如果父类中没有无参的构造方法,而子类又没有显式地调用父类的构造方法,那么编译器会报错。在这种情况下,子类需要显式地调用父类的构造方法,通过使用 super() 关键字来指定调用父类的特定构造方法。

总结起来,构造方法是用于创建对象并初始化对象的特殊方法,具有与类名相同、没有返回类型、可以有参数、可以重载的特点。它们在对象创建时被调用,用于执行对象的初始化操作。构造方法可以被继承,但不能被直接重写。

当父类中没有无参的构造方法,而子类又没有显式地调用父类的构造方法时,编译器会报错。这是因为在创建子类对象时,会隐式地调用父类的无参构造方法来完成父类的初始化操作。如果父类中没有无参构造方法可供调用,编译器无法确定如何正确地初始化父类,因此会产生编译错误。

是的,当在父类中定义了有参数的构造方法后,如果没有显式地定义无参构造方法,那么父类就不再具有默认的无参构造方法。下面是一个示例来说明这种情况:

class Parent {
    public Parent(int value) {
        // 父类构造方法接受一个int类型的参数
        // 其他代码...
    }
}

class Child extends Parent {
    public Child() {
        // 子类的构造方法没有显式地调用父类的构造方法
        // 其他代码...
    }
}

在上面的示例中,父类 Parent 中定义了一个带有一个 int 类型参数的构造方法,但没有无参构造方法。子类 Child 的构造方法没有显式地调用父类的构造方法。

当我们尝试创建 Child 类的对象时,编译器会报错,因为编译器无法找到合适的父类构造方法来初始化父类。此时,我们需要在子类的构造方法中显式地调用父类的构造方法,通过使用 super() 关键字来指定调用父类的特定构造方法。

修正后的示例代码如下:

class Parent {
    public Parent(int value) {
        // 父类构造方法接受一个int类型的参数
        // 其他代码...
    }
}

class Child extends Parent {
    public Child() {
        super(10); // 显式地调用父类的构造方法
        // 其他代码...
    }
}

在修正后的代码中,子类 Child 的构造方法使用 super(10) 调用了父类 Parent 的构造方法,传递了一个 int 类型的参数。这样就能够正确地初始化父类,并且编译器不会报错。


面向对象编程具有三大特征

  1. 封装(Encapsulation):封装是将数据和操作数据的方法封装在一起,形成一个独立的、可复用的类。通过封装,我们可以隐藏类的内部实现细节,只暴露必要的接口给外部使用。这样可以提高代码的安全性和可维护性,同时也方便了代码的复用和扩展。

  2. 继承(Inheritance):继承是通过定义一个新的类来继承已有类的属性和方法。继承可以建立类之间的层次关系,使得子类可以继承父类的特性,并且可以在此基础上进行扩展或修改。通过继承,我们可以实现代码的重用,减少重复编写类似的代码,同时也可以实现多态。

  3. 多态(Polymorphism):多态是指同一类型的对象在不同的情况下表现出不同的行为。多态可以通过继承和接口实现。在多态中,父类的引用可以指向子类的对象,通过父类的引用调用方法时,根据具体的对象类型,会执行对应子类的方法。多态提高了代码的灵活性和可扩展性,使得程序更易于扩展和维护。

这三大特征共同构成了面向对象编程的基础,通过封装、继承和多态,我们可以更好地组织和管理代码,提高代码的可读性、可维护性和可扩展性。


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

共同点:

  1. 都可以包含抽象方法:接口中的方法都是抽象的,而抽象类可以包含抽象方法和非抽象方法。
  2. 都不能直接实例化:既不能创建接口的实例,也不能创建抽象类的实例。
  3. 都可以被实现或继承:类可以实现接口,子类可以继承抽象类。
  4. 都可以有默认实现的?法(Java 8 可以? default 关键字在接?中定义默认?法)。

区别:

  1. 实现方式:一个类可以实现多个接口,但只能继承一个抽象类。接口使用 implements 关键字实现,抽象类使用 extends 关键字继承。
  2. 成员类型:接口中只能包含常量、抽象方法和默认方法,不能包含普通变量和具体实现的方法。抽象类可以包含普通变量、常量、抽象方法和具体实现的方法。
  3. 构造方法:接口不能有构造方法,因为接口不能被实例化。抽象类可以有构造方法,用于子类的实例化过程。
  4. 多继承限制:一个类可以实现多个接口,但一个类只能继承一个抽象类。这是因为Java中不支持多继承,但允许实现多个接口。
  5. 设计目的:接口用于定义一组相关的操作,强调类的行为。抽象类用于作为子类的模板,提供共享的属性和方法,并可以包含一些默认的实现。
  6. 接?中的成员变量只能是 public static final 类型的,不能被修改且必须有初始值,?抽象类的成员变量默认 default,可在?类中被重新定义,也可被重新赋值。

总的来说,接口更加抽象和规范,用于定义类的行为和能力,强调多态和约束;抽象类更加具体,用于作为子类的基类,提供共享的属性和方法,并可以包含一些默认的实现。选择使用接口还是抽象类,取决于具体的需求和设计目标。


深拷?和浅拷?区别了解吗?什么是引?拷??

浅拷?:浅拷?会在堆上创建?个新的对象(区别于引?拷?的?点),不过,如果原对象内部的属性是引?类型的话,浅拷?会直接复制内部对象的引?地址,也就是说拷?对象和原对象共?同?个内部对象。

深拷? :深拷?会完全复制整个对象,包括这个对象所包含的内部对象。

那什么是引?拷?呢? 简单来说,引?拷?就是两个不同的引?指向同?个对象。


== 和 equals() 的区别

对于基本数据类型来说,“ == ”?的是值。

对于引?数据类型来说,” == “?的是对象的内存地址。

equals() 不能?于判断基本数据类型的变量,只能?来判断两个对象是否相等。 equals() ?法存在于 Object 类中,? Object 类是所有类的直接或间接?类,因此所有的类都有 equals() ?法。
“ = = ” 运算符用于比较两个对象的引用是否指向同一个内存地址。它比较的是对象的引用值,即比较两个对象是否是同一个对象。当使用“ == ”比较两个对象时,它会检查它们的引用是否相等,如果引用指向同一个内存地址,则返回true,否则返回false。

equals()方法是Object类中定义的方法,用于比较两个对象的内容是否相等。默认情况下,equals()方法与” == “”运算符的行为相同,即比较两个对象的引用是否相等。但是,可以通过在类中重写equals()方法来改变其行为,使其比较对象的内容而不是引用。

重写equals()方法时,通常需要满足以下几个条件:

  1. 自反性:对于任意非空对象x,x.equals(x)应该返回true。
  2. 对称性:对于任意非空对象x和y,如果x.equals(y)返回true,则y.equals(x)也应该返回true。
  3. 传递性:对于任意非空对象x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)也应该返回true。
  4. 一致性:对于任意非空对象x和y,如果对象没有发生变化,多次调用x.equals(y)应该始终返回相同的结果。
  5. 非空性:对于任意非空对象x,x.equals(null)应该返回false。

总结:
“” == “比较的是对象的引用是否相等。
equals()比较的是对象的内容是否相等,可以根据需要重写该方法来改变比较的行为。
在使用equals()方法进行对象比较时,需要注意满足重写equals()方法的条件。

hashCode() 有什么??

hashCode()是Java中的一个方法,定义在Object类中,用于返回对象的哈希码(hash code)。哈希码是一个整数值,用于快速确定对象在哈希表等数据结构中的存储位置。

hashCode()方法的主要作用如下:

  1. 在哈希表中的使用:哈希表是一种常用的数据结构,如HashMapHashSet等,它们使用哈希码来确定对象在表中的存储位置。通过计算对象的哈希码,可以快速定位对象在哈希表中的存储位置,提高查找和插入的效率。

  2. 作为对象的标识符:哈希码在某些情况下可以作为对象的唯一标识符。如果两个对象的哈希码相同,不一定表示它们相等,但如果两个对象不相等,则它们的哈希码一定不同。因此,哈希码可以用于快速判断对象是否相等,从而提高对象比较的效率。

  3. 在集合中的使用:在使用集合类(如HashSetHashMap等)存储对象时,为了保证集合中的元素不重复,会使用hashCode()方法来判断两个对象是否相等。当向集合中插入元素或者从集合中查找元素时,会先比较对象的哈希码,如果哈希码相等再调用equals()方法进行进一步的比较。

需要注意的是,为了保证对象的一致性,当重写equals()方法时,通常也需要同时重写hashCode()方法,以满足以下规则:

  • 如果两个对象相等(根据equals()方法的定义),那么它们的哈希码必须相等。
  • 如果两个对象的哈希码相等,不一定表示它们相等(根据equals()方法的定义)。

总结:
hashCode()方法用于返回对象的哈希码,主要用于在哈希表中确定对象的存储位置和作为对象的标识符。在使用集合类存储对象时,通常需要同时重写equals()hashCode()方法,以确保对象的一致性和正确性。

文章来源:https://blog.csdn.net/MonochromeContrast/article/details/134982192
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。