学习java基础知识的第二天

1、java中==与equals的区别

在Java中,"=="运算符和"equals"方法都用于比较对象,但它们之间有一些重要的区别。

"==“运算符用于比较两个对象的引用(即它们在内存中的地址),以确定它们是否指向同一个对象。如果两个对象具有相同的引用,”"运算符将返回true,否则将返回false。例如:

String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2);  // true

在这个例子中,s1和s2指向同一个字符串对象,因为它们具有相同的值(“hello”)。

然而,如果使用new运算符创建两个对象,则它们的引用将不同,因此"=="运算符将返回false:

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2);  // false

“equals"方法在比较对象时比”=="运算符更灵活。它用于比较两个对象的内容,而不是它们在内存中的引用。如果两个对象具有相同的内容,"equals"方法将返回true,否则将返回false。例如:

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

在这个例子中,虽然s1和s2是不同的对象,但它们具有相同的内容,因此"equals"方法返回true。

需要注意的是,只有在类中覆盖了"equals"方法才能进行内容比较。如果未覆盖该方法,则默认实现将使用"=="运算符进行比较,即比较对象的引用。

2、java中hashCode与equals的区别

在Java中,hashCode()和equals()是两个非常重要的方法,它们都与对象的相等性相关,但是它们的作用不同:

hashCode() 方法返回一个整数值,该值可以作为该对象的哈希码(hash code)或散列值(hash value)。哈希码是一个用于确定对象在哈希表中位置的数字。当在哈希表中搜索对象时,hashCode()方法用于获取对象的哈希码,以快速定位该对象所在的位置。在Java中,如果两个对象相等,那么它们的hashCode()方法返回的值必须相等,但是反过来不一定成立。

equals() 方法用于比较两个对象是否相等。默认情况下,equals()方法比较的是对象的引用,即它们是否指向同一个对象。如果你想比较对象的内容是否相等,你需要重写equals()方法。在Java中,如果两个对象相等,那么它们的equals()方法必须返回true,但是反过来也不一定成立。

总之,hashCode()方法用于快速定位对象的位置,equals()方法用于比较两个对象的内容是否相等。在实现自定义的类时,重写这两个方法是非常重要的。如果你重写了equals()方法,那么一定要同时重写hashCode()方法,以保证对象的哈希码与相等性的一致性。

3、为什么java中只有值传递

Java中只有值传递,是因为Java中的方法调用机制采用的是值传递的方式。在Java中,所有的变量都是值传递,包括基本数据类型和对象引用类型。

在Java中,方法调用时传递的是实参的值,而不是实参本身。如果实参是一个对象引用类型,那么传递的是引用变量的值,也就是一个地址。在方法内部,这个地址会被复制到一个新的引用变量中,这个新的引用变量和原来的引用变量指向的是同一个对象。

由于Java中的对象是通过引用来操作的,所以在方法中操作对象时,实际上是通过引用来操作对象的。这也是为什么我们可以修改传递给方法的对象的属性,因为在方法中我们操作的是对象的引用,而不是对象本身。

总之,Java中只有值传递是因为Java的方法调用机制采用的是值传递的方式。即使是对象引用类型,也是传递的引用变量的值,而不是对象本身。

3、简述线程、程序、进程的基本概念以及它们之间的关系

程序是指一组指令数据的有序集合,用来完成特定的任务。它通常存储在磁盘或其他非易失性存储介质上,并需要被加载到内存中才能被执行。

进程是指一个正在运行的程序的实例,它包含了程序代码、数据、堆栈和程序计数器等信息。每个进程都有自己的内存空间和系统资源,可以独立地执行任务。

线程是进程的一个执行单元,一个进程可以包含多个线程,每个线程执行自己的代码,共享进程的数据和系统资源。线程是操作系统调度的基本单位,不同线程之间可以并发执行,可以提高程序的执行效率和资源利用率。

三者之间的关系是,一个进程可以包含多个线程,每个线程执行自己的任务,共享进程的数据和系统资源。一个程序需要被加载到内存中才能被执行,一个进程是程序的一个运行实例。因此,程序是静态的,进程和线程是动态的。程序是进程和线程的静态载体,进程和线程是程序的动态执行体。

4、java关键字“final”

在Java中,final是一个关键字,用于指示一个变量、方法或类不可改变的。

对于变量:如果一个变量被声明为final,那么它的值将在声明后不能再被改变。一般来说,final变量的命名规范是全部大写,使用下划线来分隔单词,例如:final int MAX_SIZE = 100;

对于方法:如果一个方法被声明为final,那么子类将不能覆盖它。一般来说,final方法被用于确保子类不能改变某个方法的行为。

对于:如果一个类被声明为final,那么该类将不能被继承。一般来说,final类被用于确保某个类的行为不能被改变或者防止该类被子类化。

final关键字的使用可以带来以下好处:

增加代码的可读性和可维护性。
避免变量被错误地重新赋值。
避免子类修改方法或类的行为。
提高程序的性能,因为编译器可以在编译时对final变量进行优化。

5、java的异常处理机制

java异常处理机制用来处理在程序执行期间出现的错误和异常情况。当Java程序出现异常时,它会抛出一个异常对象,该对象包含异常的详细信息。通过捕获和处理这些异常对象,程序可以避免崩溃,并进行适当的操作。
在java中,一般使用try-catch语句来处理异常。

try {
    // 可能会抛出异常的代码
} catch (Exception e) {
    // 异常处理代码
}

在Java中,异常类是由Throwable类派生出来的。异常分为两种类型:受检异常和非受检异常。受检异常必须在方法中声明,而非受检异常不需要声明。
Java中最常见的异常类型是NullPointerException(当尝试访问空引用时抛出)、ArrayIndexOutOfBoundsException(当尝试访问数组的无效索引时抛出)和IOException(当发生输入/输出错误时抛出)。

6、java中Throwable类的常用方法

Java中的Throwable类是所有可抛出异常的父类,它提供了一些常用的方法,包括:
(1)getMessage():返回Throwable对象的详细信息字符串
(2)toString():返回包含Throwable对象类名、详细消息和堆栈跟踪的字符串
(3)getLocalizedMessage() :返回异常对象的本地化信息。使⽤ Throwable 的⼦类覆盖这个⽅法,可以⽣成本地化信息。如果⼦类没有覆盖该⽅法,则该⽅法返回的信息与getMessage() 返回的结果相同。

7、java语言获取⽤键盘输⼊常⽤的两种⽅法

(1)使用Scanner类

import java.util.Scanner;

public class Example {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入一个整数: ");
        int num = scanner.nextInt();
        System.out.println("你输入的整数是:" + num);
    }
}

(2)使用BuffReader类

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Example {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        System.out.print("请输入一个字符串: ");
        String str = reader.readLine();
        System.out.println("你输入的字符串是:" + str);
    }
}

8、java中的io流

按照流的流向分,可以分为输⼊流和输出流;
按照操作单元划分,可以划分为字节流和字符流;
按照流的⻆⾊划分为节点流和处理流
Java I0 流的 40 多个类都是从如下 4 个抽象类基类中派⽣出来的。
InputStream/Reader: 所有的输⼊流的基类,前者是字节输⼊流,后者是字符输⼊流。
OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。
下面是一些常用的Java输入输出数据流类及其用途:

  • FileInputStream和FileOutputStream:用于从文件中读取数据或将数据写入文件。

  • ByteArrayInputStream和ByteArrayOutputStream:用于从字节数组中读取数据或将数据写入字节数组。

  • InputStreamReader和OutputStreamWriter:用于将字节流转换为字符流,以便读取和写入字符数据。

  • BufferedInputStream和BufferedOutputStream:用于提高读取和写入性能,它们会缓存数据以减少IO操作的次数。

  • DataInputStream和DataOutputStream:用于读取和写入基本数据类型(如int、double、boolean等)和字符串。

  • ObjectInputStream和ObjectOutputStream:用于读取和写入Java对象,可以将对象序列化为字节流以便存储或传输。

9、深拷贝VS浅拷贝

浅拷贝(Shallow Copy):浅拷贝是指在拷贝对象时,仅复制对象本身及其内部基本类型的成员变量,而不复制对象内部引用类型的成员变量所引用的对象。
深拷贝(Deep Copy):深拷贝是指在拷贝对象时,不仅复制对象本身及其内部基本类型的成员变量,而且还复制对象内部引用类型的成员变量所引用的对象。
若原对象的内部应用类型成员变量的值改变,则浅拷贝后的对象对应的成员变量的值则会改变,而深拷贝则不会改变。

10、List、Set、Map三者的区别

List(列表)是一种有序的集合,可以存储重复的元素。列表的元素可以通过下标访问,也可以通过添加或删除操作修改列表的内容。

**Set(集合)**是一种无序的集合,不允许存储重复的元素。集合中的元素不能通过下标访问,只能通过添加或删除操作修改集合的内容。

**Map(映射)**是一种键值对(key-value)的集合,每个键唯一对应一个值。通过给定的键,可以查找到对应的值。Map 中的键和值都可以是任意类型的对象,可以通过添加、删除、修改操作修改 Map 的内容。

简单总结:

List: 有序,可重复,支持下标访问
Set: 无序,不可重复,不支持下标访问
Map: 无序,键唯一对应一个值,支持键值访问

11、java中ArrayList和LinkedList的区别

数据结构:ArrayList是基于数组实现的动态数组,而LinkedList是基于链表实现的双向链表。
访问效率:ArrayList支持随机访问,通过索引访问,访问效率高于LinkedList,但插入、删除元素时需要移动其他元素,效率较低;inkedList在插入和删除时的效率较高,访问时效率低,需要遍历链表。
空间占用:ArrayList会预留一定的空间,当容量不足时需要扩容,因此可能会浪费一些空间;LinkedList不需要预留空间,每个元素都只占用自己的空间,因此不会浪费空间。
线程安全:ArrayList是非线程安全的,多个线程同时访问一个ArrayList可能会导致数据不一致;而LinkedList可以通过Collections.synchronizedList方法来创建一个线程安全的List。

综上所述,如果需要频繁访问元素而很少插入、删除元素,应该使用ArrayList;如果需要频繁插入、删除元素而很少访问元素,应该使用LinkedList。

12、java中ArrayList和Vector的区别

线程安全:ArrayList非线程安全,Vector线程安全。
初始大小和扩容:初始大小均为10,Vector自动扩容,扩容时增加原来容量的一倍;ArrayList扩容时,增加原来容量的一半。
综上所述,ArrayList比Vector更适合在单线程环境下使用,而Vector更适合在多线程环境下使用。

13、ArrayList的扩容机制

ArrayList是一种大小可变的数组实现的,可以自动扩容以容纳更多的元素。当添加元素时,如果数组已满,则会采用扩容机制:
扩容操作会创建一个新的数组,通常是原数组的1.5倍大小,然后将源数据中的所有元素复制到新的数组中。扩容完成后,ArrayList将使用新数组替代原数组。
因此,ArrayList 的扩容机制可以确保 ArrayList 具有足够的容量来存储元素,并且能够高效地进行添加操作。但是,频繁的扩容操作会导致性能下降,因此建议在创建 ArrayList 时就指定一个合适的初始容量,以减少扩容的次数。可以使用 ArrayList 的构造方法 ArrayList(int initialCapacity) 来指定初始容量。

14、java中HashMap和HashTable的区别

线程安全性:HashTable 是线程安全的,而 HashMap 不是。
效率: 因为线程安全的问题, HashMap 要⽐ HashTable 效率⾼⼀点。另外, HashTable
基本被淘汰,不要在代码中使⽤它;
对 Null key 和 Null value 的处理:HashTable 不允许键或值为 null,如果出现 null,会抛出 NullPointerException 异常。而 HashMap 允许键或值为 null。
初始容量⼤⼩和扩容 : ① 创建时如果不指定容量初始值, Hashtable
默认的初始⼤⼩为 11,之后每次扩充,容量变为原来的 2n+1。 HashMap 默认的初始化⼤⼩为 16。之后每次扩充,容量变为原来的 2 倍。② 创建时如果给定了容量初始值,那么Hashtable 会直接使⽤你给定的⼤⼩,⽽ HashMap 会将其扩充为 2 的幂次⽅⼤⼩总是使⽤ 2 的幂作为哈希表的⼤⼩。

15、HashMap和HashSet的区别

在这里插入图片描述

16、并发与并⾏的区别

并发: 同⼀时间段,多个任务都在执⾏ (单位时间内不⼀定同时执⾏);
并⾏: 单位时间内,多个任务同时执⾏。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值