Java知识总结(持续更新)

news2024/11/23 11:17:37

一、JDK、JRE、JVM三者之间的关系?

1. **JDK (Java Development Kit)**:
   JDK 是 Java 开发工具包,它包含了用于开发 Java 应用程序的所有必要工具和库。这包括 Java 编译器(javac)、Java 核心类库、开发工具(如调试器和监视器工具)以及其他一些实用工具。如果您希望编写、编译和运行 Java 程序,您需要安装 JDK。
2. **JRE (Java Runtime Environment)**:
   JRE 是 Java 运行时环境,它包括 Java 虚拟机(JVM)和 Java 核心类库。JRE 的主要作用是使您能够运行已经编译好的 Java 应用程序。如果您只想运行 Java 应用程序而不进行开发,那么安装 JRE 就足够了。
3. **JVM (Java Virtual Machine)**:
   JVM 是 Java 虚拟机,它是 Java 应用程序的运行环境。JVM 负责将 Java 字节码翻译成特定计算机架构的机器代码,并执行 Java 程序。每个 Java 应用程序在 JVM 中运行,它提供了跨平台的能力,使得相同的 Java 应用程序可以在不同操作系统上运行。
        简而言之,JDK 包含了开发 Java 应用程序所需的工具,JRE 包含了运行 Java 应用程序所需的环境,而 JVM 是 Java 应用程序的执行引擎。这三者之间的关系是 JDK 包含 JRE,而 JRE 包含 JVM。

 二、Java中创建对象的几种方式?

1. **使用 `new` 关键字**:
   这是最常见的创建对象的方式。使用new关键字后跟构造函数来创建一个新的对象实例。例如:

 MyClass obj = new MyClass();

2. **使用工厂方法**:
   某些类提供了静态工厂方法,用于创建对象。这种方法可以隐藏对象的创建细节。例如:

 Calendar cal = Calendar.getInstance(); // 使用工厂方法创建 Calendar 对象

3. **使用反射**:
   Java 反射允许在运行时动态地创建对象,即使您不知道对象的确切类型。您可以使用 `Class` 类的 `newInstance` 方法来创建对象。但请注意,反射可能会导致性能下降和安全性问题,因此应谨慎使用。

Class<?> myClass = Class.forName("com.example.MyClass");
   Object obj = myClass.newInstance();

4. **使用克隆**:
   如果一个类实现了 `Cloneable` 接口,您可以使用 `clone` 方法创建对象的副本。这被称为浅拷贝,因为它只复制对象的字段,而不会复制字段引用的对象。

 MyClass originalObj = new MyClass();
   MyClass clonedObj = (MyClass) originalObj.clone();

5. **使用序列化和反序列化**:
   您可以通过将对象序列化为字节流,然后反序列化来创建对象的副本。这种方法允许在不同的 Java 虚拟机之间传输对象,或者将对象保存到文件中并从文件中还原。

// 序列化对象
   ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.ser"));
   oos.writeObject(originalObj);
   oos.close();

   // 反序列化对象
   ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.ser"));
   MyClass newObj = (MyClass) ois.readObject();
   ois.close();

三、 final、finally、finalize的区别

1. **final**关键字:用于修饰类、方法、变量、入参和对象

  •  应用于类时,表示该类是最终类,不能被其他类继承。
  •  应用于方法时,表示该方法时最终方法,不能被其他类继承。
  •  应用于变量时,表示该变量时一个常量,只能赋值一次。
  •  应用于入参时,表示该入参在方法内无法被修改。
  •  应用于对象时,该对象的引用不能被修改,但对象本身的状态是可以改变的。

   示例:

final class FinalClass {
       // ...
   }
   
   class SubClass extends FinalClass { // 这是非法的,无法继承 final 类
       // ...
   }
   
   public void exampleMethod(final int value) {
       // value 是一个常量,不能在方法内部修改
   }

2. **finally**关键字:异常处理机制中的一部分,用于定义在try-catch-finally块中的finally块
   - 无论是否发生异常,`finally` 块中的代码都会被执行,通常用于释放资源或执行清理操作。

   示例:

 try {
       // 可能会引发异常的代码
   } catch (Exception e) {
       // 处理异常
   } finally {
       // 无论是否发生异常,都会执行这里的代码
       // 通常用于关闭文件、释放资源等操作
   }

3. **finalize**:是一个方法,它是 `java.lang.Object` 类中定义的一个方法。

  • 在垃圾回收器将对象回首之前调用。
  • 可以重写finalize方法,在其中编写对象在被回收钱需要进行的清理操作,如释放资源等。
  • 请注意,不推荐使用finalize方法进行内存资源的释放,它没有被及时执行的保证,也可能导致性能问题。

总结
- `final` 用于声明不可变的类、方法或变量。
- `finally` 用于与异常处理 (`try-catch`) 结构一起,确保代码块中的代码无论是否发生异常都会被执行。
- `finalize` 是一个过时的方法,用于在垃圾回收前执行对象的清理操作,不建议使用,现代 Java 有更好的垃圾回收方式。

 四、==和equals的区别?

在 Java 中,`==` 和 `equals` 是两个用于比较对象的操作符,它们具有不同的作用和用途:

1. **`==` 操作符**:

  •    `==` 用于比较两个对象的引用是否相同,即它们是否指向内存中的同一对象。
  •    当使用 `==` 来比较基本数据类型(如 `int`、`double`)时,它比较的是值是否相等。
  •    对于引用类型(对象),`==` 比较的是两个引用变量是否指向同一个对象,而不考虑对象的内容。

   示例:

String str1 = new String("Hello");
   String str2 = new String("Hello");
   
   System.out.println(str1 == str2); // false,因为它们是不同的对象

2. **`equals` 方法**:比较是否是同一个对象,equals方法存在于object类中,而object类时所有类直接或者间接的父类,在没有重写equals方法的类中,和==一样比较引用类型所只想的对象地址是否相等。重写equals方法就看各个类重写后的逻辑,比如String类,虽然是引用类型,但是String类重写了equals方法,方法内部比较的是字符串中的各个字符是否去哪不相等。

  •    `equals` 是一个方法,通常需要被重写以实现自定义的对象比较逻辑。在 `java.lang.Object` 类中,`equals` 方法默认行为与 `==` 相同,即比较对象的引用。
  •    通常,您应该在自定义类中重写 `equals` 方法,以根据对象的内容(属性值)来比较它们是否相等。

   示例:

 class Person {
       private String name;
       private int age;

       // 自定义 equals 方法,比较对象的属性值
       @Override
       public boolean equals(Object obj) {
           if (this == obj) {
               return true; // 同一对象
           }
           if (obj == null || getClass() != obj.getClass()) {
               return false; // 类型不同
           }
           Person person = (Person) obj;
           return age == person.age && Objects.equals(name, person.name);
       }
   }
   
   Person person1 = new Person("Alice", 30);
   Person person2 = new Person("Alice", 30);
   
   System.out.println(person1.equals(person2)); // true,因为属性值相同

总结:

  • `==` 操作符用于比较对象的引用,检查它们是否指向同一个内存位置。
  • `equals` 方法用于比较对象的内容,通常需要在自定义类中重写以实现属性值的比较。默认情况下,`equals` 方法在 `java.lang.Object` 中的行为与 `==` 相同。

五、两个对象的hashCode相同,则equals也一定为true吗?

 两个对象的hashCode相同,equals不一定为true;

两个对象的equals相同,则两个对象的hashCode一定为true;

六、&和&& 、 | 和 || 的区别?

1. **`&` 和 `&&`(逻辑与)**

  •    `&` 和 `&&` 都用于执行逻辑与操作,即在两个条件都为 `true` 时返回 `true`。
  •    主要区别在于短路性(short-circuiting behavior):
  •      `&` 是非短路操作,它会对两个条件都进行求值,无论第一个条件的结果如何。
  •      `&&` 是短路操作,它只在第一个条件为 `true` 时才会继续求值第二个条件,如果第一个条件为 `false`,则不会继续求值第二个条件。

   示例:

 boolean condition1 = false;
   boolean condition2 = true;
   
   // 对于 &,两个条件都会被求值,然后返回 false
   boolean result1 = condition1 & condition2; // result1 为 false
   
   // 对于 &&,由于第一个条件为 false,第二个条件不会被求值,直接返回 false
   boolean result2 = condition1 && condition2; // result2 为 false

2. **`|` 和 `||`(逻辑或)**:

  •    `|` 和 `||` 都用于执行逻辑或操作,即在两个条件中至少一个为 `true` 时返回 `true`。
  •    主要区别同样在于短路性:
  •      `|` 是非短路操作,它会对两个条件都进行求值,无论第一个条件的结果如何。
  •      `||` 是短路操作,它只在第一个条件为 `true` 时才会继续求值第二个条件,如果第一个条件为 `true`,则不会继续求值第二个条件。

   示例:

 boolean condition1 = true;
   boolean condition2 = false;
   
   // 对于 |,两个条件都会被求值,然后返回 true
   boolean result1 = condition1 | condition2; // result1 为 true
   
   // 对于 ||,由于第一个条件为 true,第二个条件不会被求值,直接返回 true
   boolean result2 = condition1 || condition2; // result2 为 true

总结

  • `&` 和 `|` 是非短路逻辑操作符,它们会对两个条件都进行求值。
  • `&&` 和 `||` 是短路逻辑操作符,它们在满足条件的情况下不会继续求值第二个条件。
  • 通常情况下,建议使用 `&&` 和 `||` 来执行逻辑操作,因为它们具有短路性,可以提高性能并避免不必要的计算。

七、Java中的参数传递时传值呢?还是传引用?

        在 Java 中,参数传递是按值传递(pass-by-value),而不是按引用传递(pass-by-reference)。这意味着在方法调用时,将参数的值(也就是参数引用的副本)传递给方法,而不是传递参数的实际引用。

        当你将一个原始数据类型(如 `int`、`double`、`char` 等)作为参数传递给方法时,你传递的是该数据的值的副本。任何对参数值的修改都不会影响原始值。

public void modifyValue(int x) {
    x = 10; // 修改局部变量 x 的值,不会影响原始值
}

public static void main(String[] args) {
    int num = 5;
    modifyValue(num);
    System.out.println(num); // 输出 5,原始值不变
}

        当你将一个对象作为参数传递给方法时,你传递的是对象的引用的副本,而不是对象本身。这意味着你可以通过引用访问和修改对象的状态,但不能通过修改引用来改变原始对象引用的对象。

class Person {
    String name;

    Person(String name) {
        this.name = name;
    }
}

public void modifyPersonName(Person person) {
    person.name = "Alice"; // 修改对象的状态,会影响原始对象
}

public static void main(String[] args) {
    Person person = new Person("Bob");
    modifyPersonName(person);
    System.out.println(person.name); // 输出 "Alice",原始对象状态被修改
}

        虽然传递的是引用的副本,但原始引用和方法中的引用指向的是同一个对象。所以,通过方法修改对象的状态会影响原始对象。但如果在方法中重新分配引用,原始引用不会受到影响。

        总结:Java 中的参数传递是按值传递原始数据类型传递值的副本,而对象类型传递引用的副本,允许修改对象的状态,但不允许修改原始引用

八、什么是Java的序列化,如何实现Java的序列化?

        Java 的序列化是一种将对象转换为字节流的过程,以便将其保存到文件、传输到网络或在不同 Java 虚拟机之间进行通信。序列化的主要目的是将对象的状态持久化或传输,以便在需要时能够还原对象。反序列化是序列化的逆过程,它将字节流重新转换为对象。

要实现 Java 的序列化,需要满足以下条件和步骤:

1. **实现 `Serializable` 接口**:
   要使一个类可序列化,它必须实现 `Serializable` 接口。这是一个标记接口,没有需要实现的方法。只要类声明实现了这个接口,编译器就知道这个类可以被序列化。   

 import java.io.Serializable;

   public class MyClass implements Serializable {
       // 类的成员和方法
   }

2. **使用 `ObjectOutputStream` 进行序列化**:
   要将对象序列化为字节流,您可以使用 `ObjectOutputStream` 类。首先,创建一个 `FileOutputStream` 或 `ByteArrayOutputStream` 来写入字节流,然后将其传递给 `ObjectOutputStream`。

import java.io.*;

   public class SerializationExample {
       public static void main(String[] args) {
           try {
               MyClass obj = new MyClass();
               FileOutputStream fileOut = new FileOutputStream("myObject.ser");
               ObjectOutputStream out = new ObjectOutputStream(fileOut);
               out.writeObject(obj);
               out.close();
               fileOut.close();
               System.out.println("Object serialized successfully.");
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
   }

3. **使用 `ObjectInputStream` 进行反序列化**:
   要从字节流中反序列化对象,您可以使用 `ObjectInputStream` 类。首先,创建一个 `FileInputStream` 或 `ByteArrayInputStream` 来读取字节流,然后将其传递给 `ObjectInputStream`。

 import java.io.*;

   public class DeserializationExample {
       public static void main(String[] args) {
           try {
               FileInputStream fileIn = new FileInputStream("myObject.ser");
               ObjectInputStream in = new ObjectInputStream(fileIn);
               MyClass obj = (MyClass) in.readObject();
               in.close();
               fileIn.close();
               System.out.println("Object deserialized successfully.");
           } catch (IOException | ClassNotFoundException e) {
               e.printStackTrace();
           }
       }
   }

4. **自定义序列化和反序列化**(可选):
   如果您需要更精细的控制序列化和反序列化过程,您可以在类中定义特殊方法 `writeObject` 和 `readObject`。这允许您在序列化和反序列化期间执行自定义逻辑。

private void writeObject(ObjectOutputStream out) throws IOException {
       // 自定义序列化逻辑
       out.defaultWriteObject(); // 调用默认序列化
   }

   private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
       // 自定义反序列化逻辑
       in.defaultReadObject(); // 调用默认反序列化
   }

        需要注意的是,不是所有的对象都可以序列化,例如,如果对象包含不可序列化的成员变量,那么它也不能被序列化,或者需要采取额外的措施来处理这些成员。此外,序列化可能会涉及到版本控制,以确保反序列化的兼容性。

        总之,Java 的序列化是将对象转换为字节流以实现持久化或传输的重要机制,通过实现 `Serializable` 接口并使用 `ObjectOutputStream` 和 `ObjectInputStream`,您可以轻松实现对象的序列化和反序列化。

九、Java中的反射怎么理解?

        Java的反射机制是指在运行状态中,对于一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能成为Java语言的反射机制。

        简单的说:在运行时动态的获取、操作和修改类或对象的属性、方法、构造函数等信息的能力,而不需要在编译时预先知道类的具体信息。

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/995554.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Day-33慢就是快】代码随想录-二叉树-二叉搜索树中的搜索

给定二叉搜索树&#xff08;BST&#xff09;的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在&#xff0c;则返回 NULL。 思路 什么是二叉搜索树&#xff1a; 二叉搜索树是一个有序树&#xff1a; 若它的左子树不空&a…

【NVIDIA CUDA】2023 CUDA夏令营编程模型(三)

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

yolov7增加mobileone

代码地址&#xff1a;GitHub - apple/ml-mobileone: This repository contains the official implementation of the research paper, "An Improved One millisecond Mobile Backbone". 论文地址&#xff1a;https://arxiv.org/abs/2206.04040 MobileOne出自Apple&am…

IP403参考资料和引脚图

特性 支持串并联双LED驱动和GPIO控制器 串并联LED驱动器 支持一个串行输入56个并行led或三串行输入16个并行ed为每个串行输入。 支持4-16mA可调电流源驱动&#xff0c;无限流电阻 支持LED熄灭模式&#xff0c;实现省电功能 提供级联能力&#xff0c;提供更多的LED驱动输出…

go语言基础---8

Http请求报文格式分析 package mainimport ("fmt""net" )func main() {//监听listener, err : net.Listen("tcp", ":8000")if err ! nil {fmt.Println("listener err", err)return}defer listener.Close()//阻塞等待用户的…

SAM + YOLOv8 图像分割及对象检测

SAM(Segment Anything Model&#xff09;是由 Meta 的研究人员团队创建和训练的深度学习模型。该创新成果发表在 2023 年 4 月 5 日发表的一篇研究论文中&#xff0c;它立即引起了公众的广泛兴趣——相关的 Twitter 帖子迄今为止已累积超过 350 万次浏览&#xff1a; 计算机视…

接口文档生成工具JAPiDocs

效果如下&#xff1a; 相比Swagger要写一堆注解&#xff0c;Spring RestDocs需要写测试用例&#xff0c;才能生成API文档。 要使得JApiDcos正确工作&#xff0c;代码应该是像下面的样子的&#xff1a; /*** 用户接口*/ RequestMapping("/api/user/") RestControll…

YOLO目标检测——口罩规范佩戴数据集+已标注xml和txt格式标签下载分享

实际项目应用&#xff1a;目标检测口罩佩戴检测数据集的应用场景涵盖了公共场所监控、疫情防控管理、安全管理与控制以及人员统计和分析等领域。这些应用场景可以帮助相关部门和机构更好地管理口罩佩戴情况&#xff0c;提高公共卫生和安全水平&#xff0c;保障人们的健康和安全…

C++数据结构X篇_10_C++栈的应用-中缀转后缀

中缀表达式就是我们平时运算表达式&#xff0c;其特点是运算符总是处于两个运算对象之间。但是该表达式计算机处理起来较为麻烦&#xff0c;会将其转写成后缀表达式&#xff0c;后缀表达式也叫逆波兰表达式&#xff0c;后缀表达式的特点是每个运算符都置于两个运算对象之后。此…

微信小程序AI类目-深度合成-AI问答/AI绘画 互联网信息服务算法备案审核通过教程

近期小程序审核规则变化后&#xff0c;很多使用人类小徐提供的chatGPT系统的会员上传小程序无法通过审核&#xff0c;一直提示需要增加深度合成-AI问答、深度合成-AI绘画类目&#xff0c;该类目需要提供互联网信息服务算法备案并上传资质&#xff0c;一般对企业来说这种务很难实…

SSH是如何配置的

目录 什么是SSH SSH可以做什么其他用途&#xff1f; ssh有几种连接方法吗 我应该用哪种方法连接SSH1或SSH2&#xff1f; 每天都在用SSH你知道SSH的原理吗 开启ssh后telnet会关闭吗 SSH的优缺点 SSH和Telnet之间优缺点的对比 SSH的配置实验 ensp Cisco H3C 1、什么是…

linux内核模块编译方法详解

文章目录 前言一、静态加载法1.1 编写驱动程序1.2 将新功能配置在内核中1.3为新功能代码改写Makefile1.4 make menuconfig界面里将新功能对应的那项选择为<*> 二、动态加载法2.1 新功能源码与Linux内核源码在同一目录结构下2.2 新功能源码与Linux内核源码不在同一目录结构…

0003号因子测试结果、代码和数据

这篇文章共分为四个部分:第一个部分是因子测试结果,第二个部分是因子逻辑,第三个部分是因子代码,第四个部分是整个因子测试用的数据、代码、分析结果的下载地址。 因子测试结果: 因子描述 因子属性-量价因子因子构建:计算成交量的变化率和日振幅率,计算两者在过去一定…

Solidity 小白教程:12. 事件

Solidity 小白教程&#xff1a;12. 事件 这一讲&#xff0c;我们用转账 ERC20 代币为例来介绍solidity中的事件&#xff08;event&#xff09;。 事件 Solidity中的事件&#xff08;event&#xff09;是EVM上日志的抽象&#xff0c;它具有两个特点&#xff1a; 响应&#x…

外传-Midjourney的局部重绘功能

今天在抄袭。。。啊不&#xff0c;借鉴 midjourney 官网教程的时候&#xff0c;发现多了一个 局部重绘的功能&#xff0c;意外发觉还不错&#xff0c;分享一下用法。 先给大家说一下&#xff0c;我这段时间都在学习 SD&#xff0c;局部重绘是基操&#xff0c;而 MJ 一直是次次…

react实现一个搜索部门(input + tree)

目录 react实现一个搜索部门(input tree)searchDept.jsxtreeData.js使用组件效果 react实现一个搜索部门(input tree) searchDept.jsx import React, { useState, useEffect } from "react"; import StyleDeptId from "styled-components"; import Spl…

数据链路层重点协议-以太网

以太网简介 "以太网" 不是一种具体的网络&#xff0c;而是一种技术标准&#xff1b;既包含了数据链路层的内容&#xff0c;也包含了 一些物理层的内容。例如&#xff1a;规定了网络拓扑结构&#xff0c;访问控制方式&#xff0c;传输速率等&#xff1b; 以太网数据帧…

用python使用pyautogui库实现按键精灵模拟鼠标键盘找图的功能

用到库pyautogui 目前只能在python2.7.13上使用。在python3上不能用。所以运行程序前要设置pycharm。 使用pyautogui当然首先要安装。在cmd的默认是python2的环境下安装。 可以上https://pypi.org/查看一下 因为好久没有安装新包了&#xff0c;看来新版本已经可以支持python3…

C++:类和对象(三)

本文主要介绍初始化列表、static成员、友元、内部类、匿名对象、拷贝对象时编译器的优化。 目录 一、再谈构造函数 1.构造函数体赋值 2.初始化列表 3.explicit关键字 二、static成员 1.概念 2.特性 三、友元 1.友元函数 2.友元类 四、内部类 五、匿名对象 六、拷…

代码随想录算法训练营day45|70. 爬楼梯(进阶版)|322. 零钱兑换|279.完全平方数

70. 爬楼梯(进阶版) 一步一个台阶&#xff0c;两个台阶&#xff0c;三个台阶&#xff0c;…&#xff0c;直到 m个台阶。问有多少种不同的方法可以爬到楼顶呢&#xff1f; 1阶&#xff0c;2阶&#xff0c;… m阶就是物品&#xff0c;楼顶就是背包。 每一阶可以重复使用&#…