什么是字节码在 Java 中JVM 可以理解的代码就叫做字节码即扩展名为.class的文件它不面向任何特定的处理器只面向虚拟机。Java 语言通过字节码的方式在一定程度上解决了传统解释型语言执行效率低的问题同时又保留了解释型语言可移植的特点。所以 Java 程序运行时相对来说还是高效的不过和 C、 CRustGo 等语言还是有一定差距的而且由于字节码并不针对一种特定的机器因此Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。为什么说 Java 语言“编译与解释并存”这是因为 Java 语言既具有编译型语言的特征也具有解释型语言的特征。因为 Java 程序要经过先编译后解释两个步骤由 Java 编写的程序需要先经过编译步骤生成字节码.class文件这种字节码必须由 Java 解释器来解释执行。自增自减运算符和--运算符可以放在变量之前也可以放在变量之后1.前缀形式例如a或--a先自增/自减变量的值然后再使用该变量例如b a先将a增加 1然后把增加后的值赋给b。2.后缀形式例如a或a--先使用变量的当前值然后再自增/自减变量的值。例如b a先将a的当前值赋给b然后再将a增加 1。移位运算符高效、节省内存移位操作中被操作的数据被视为二进制数移位就是将其向左或向右移动若干位的运算。移位运算符最常用于快速乘以或除以 2 的幂次方。除此之外它还在以下方面发挥着重要作用位字段管理例如存储和操作多个布尔值。哈希算法和加密解密通过移位和与、或等操作来混淆数据。数据压缩例如霍夫曼编码通过移位运算符可以快速处理和操作二进制数据以生成紧凑的压缩格式。数据校验例如 CRC循环冗余校验通过移位和多项式除法生成和校验数据完整性。内存对齐通过移位操作可以轻松计算和调整数据的对齐地址。Java 中有三种移位运算符:左移运算符向左移若干位高位丢弃低位补零。x n相当于 x 乘以 2 的 n 次方不溢出的情况下。:带符号右移向右移若干位高位补符号位低位丢弃。正数高位补 0负数高位补 1。x n相当于 x 除以 2 的 n 次方。:无符号右移忽略符号位空位都以 0 补齐。移位操作符实际上支持的类型只有int和long编译器在对short、byte、char类型进行移位前都会将其转换为int类型再操作。continue指跳出当前的这一次循环继续下一次循环。break指跳出整个循环体继续执行循环下面的语句。return;直接使用 return 结束方法执行用于没有返回值函数的方法return value;return 一个特定值用于有返回值函数的方法Java 中有 8 种基本数据类型分别为6 种数字类型4 种整数型byte、short、int、long2 种浮点型float、double1 种字符类型char1 种布尔型boolean基本类型位数字节默认值取值范围byte810-128 ~ 127short1620-32768-2^15 ~ 327672^15 - 1int3240-2147483648 ~ 2147483647long6480L-9223372036854775808-2^63 ~ 92233720368547758072^63 -1char162u00000 ~ 655352^16 - 1float3240f1.4E-45 ~ 3.4028235E38double6480d4.9E-324 ~ 1.7976931348623157E308boolean1falsetrue、false基本类型和包装类型的区别基本类型和包装类型的区别基本类型和包装类型的区别用途除了定义一些常量和局部变量之外我们在其他地方比如方法参数、对象属性中很少会使用基本类型来定义变量。并且包装类型可用于泛型而基本类型不可以。存储方式基本数据类型的局部变量存放在 Java 虚拟机栈中的局部变量表中基本数据类型的成员变量未被static修饰存放在 Java 虚拟机的堆中。包装类型属于对象类型我们知道几乎所有对象实例都存在于堆中。占用空间相比于包装类型对象类型 基本数据类型占用的空间往往非常小。默认值成员变量包装类型不赋值就是null而基本类型有默认值且不是null。比较方式对于基本数据类型来说比较的是值。对于包装数据类型来说比较的是对象的内存地址。所有整型包装类对象之间值的比较全部使用equals()方法。装箱Boxing将基本类型用它们对应的引用类型包装起来拆箱Unboxing将包装类型转换为基本数据类型成员变量与局部变量的区别语法形式从语法形式上看成员变量是属于类的而局部变量是在代码块或方法中定义的变量或是方法的参数成员变量可以被public,private,static等修饰符所修饰而局部变量不能被访问控制修饰符及static所修饰但是成员变量和局部变量都能被final所修饰。存储方式从变量在内存中的存储方式来看如果成员变量是使用static修饰的那么这个成员变量是属于类的如果没有使用static修饰这个成员变量是属于实例的。而对象存在于堆内存局部变量则存在于栈内存。生存时间从变量在内存中的生存时间上看成员变量是对象的一部分它随着对象的创建而存在而局部变量随着方法的调用而自动生成随着方法的调用结束而消亡。默认值从变量是否有默认值来看成员变量如果没有被赋初始值则会自动以类型的默认值而赋值一种情况例外被final修饰的成员变量也必须显式地赋值而局部变量则不会自动赋值。成员变量有默认值核心原因是为了保证对象状态的安全和可预测性。成员变量和局部变量在这个规则上不同主要是因为它们的生命周期不一样导致了编译器对它们的“控制力”也不同。局部变量只活在一个方法里编译器能清楚地看到它是否在使用前被赋值所以编译器会强制你必须手动赋值否则就报错。成员变量是跟着对象走的它的值可能在构造函数里赋也可能在后面的某个setter方法里赋。编译器在编译时无法预测它到底什么时候会被赋值。并且如果一个变量没有被初始化它的内存里存放的就是“垃圾值”——之前那块内存遗留下的任意数据。如果程序读取并使用了这个垃圾值就会产生完全不可预测的结果比如一个数字变成了随机数一个对象引用变成了非法地址这会直接导致程序崩溃或出现诡异的 bug。为了避免你拿到一个含有“垃圾值”的危险对象Java 干脆为所有成员变量提供了一个安全的默认值如 null 或 0作为一种安全兜底机制。静态变量也就是被static关键字修饰的变量。它可以被类的所有实例共享无论一个类创建了多少个对象它们都共享同一份静态变量。也就是说静态变量只会被分配一次内存即使创建多个对象这样可以节省内存。字符型常量和字符串常量的区别形式 : 字符常量是单引号引起的一个字符字符串常量是双引号引起的 0 个或若干个字符。含义 : 字符常量相当于一个整型值ASCII 值可以参加表达式运算; 字符串常量代表一个地址值该字符串在内存中存放位置。占内存大小字符常量只占 2 个字节; 字符串常量占若干个字节。静态方法和实例方法有何不同调用方式调用静态方法无需创建对象访问类成员是否存在限制静态方法在访问本类的成员时只允许访问静态成员即静态成员变量和静态方法不允许访问实例成员即实例成员变量和实例方法而实例方法不存在这个限制对象的相等一般比较的是内存中存放的内容是否相等。引用相等一般比较的是他们指向的内存地址是否相等。区别点重载 (Overloading)重写 (Overriding)发生范围同一个类中。父类与子类之间存在继承关系。方法签名方法名必须相同但参数列表必须不同参数的类型、个数或顺序至少有一项不同。方法名、参数列表必须完全相同。返回类型与返回值类型无关可以任意修改。子类方法的返回类型必须与父类方法的返回类型相同或者是其子类。访问修饰符与访问修饰符无关可以任意修改。子类方法的访问权限不能低于父类方法的访问权限。public protected default private绑定时期编译时绑定或称静态绑定运行时绑定 (Run-time Binding) 或称动态绑定构造方法具有以下特点名称与类名相同构造方法的名称必须与类名完全一致。没有返回值构造方法没有返回类型且不能使用void声明。自动执行在生成类的对象时构造方法会自动执行无需显式调用。构造方法不能被重写override但可以被重载overload。因此一个类中可以有多个构造方法这些构造方法可以具有不同的参数列表以提供不同的对象初始化方式。封装是指把一个对象的状态信息也就是属性隐藏在对象内部不允许外部对象直接访问对象的内部信息。但是可以提供一些可以被外界访问的方法来操作属性。继承是使用已存在的类的定义作为基础建立新类的技术新类的定义可以增加新的数据或新的功能也可以用父类的功能但不能选择性地继承父类。通过使用继承可以快速地创建新的类可以提高代码的重用程序的可维护性节省大量创建新类的时间提高我们的开发效率。多态顾名思义表示一个对象具有多种的状态具体表现为父类的引用指向子类的实例。接口和抽象类的共同点实例化接口和抽象类都不能直接实例化只能被实现接口或继承抽象类后才能创建具体的对象抽象方法接口和抽象类都可以包含抽象方法。抽象方法没有方法体必须在子类或实现类中实现。接口和抽象类的区别设计目的接口主要用于对类的行为进行约束你实现了某个接口就具有了对应的行为。抽象类主要用于代码复用强调的是所属关系。继承和实现一个类只能继承一个类包括抽象类因为 Java 不支持多继承。但一个类可以实现多个接口一个接口也可以继承多个其他接口。成员变量接口中的成员变量只能是public static final类型的不能被修改且必须有初始值。抽象类的成员变量可以有任何修饰符private,protected,public可以在子类中被重新定义或赋值。方法Java 8 之前接口中的方法默认是public abstract也就是只能有方法声明。自 Java 8 起可以在接口中定义default默认 方法和static静态方法。 自 Java 9 起接口可以包含private方法。抽象类可以包含抽象方法和非抽象方法。抽象方法没有方法体必须在子类中实现。非抽象方法有具体实现可以直接在抽象类中使用或在子类中重写。浅拷贝浅拷贝会在堆上创建一个新的对象区别于引用拷贝的一点不过如果原对象内部的属性是引用类型的话浅拷贝会直接复制内部对象的引用地址也就是说拷贝对象和原对象共用同一个内部对象。深拷贝深拷贝会完全复制整个对象包括这个对象所包含的内部对象。对于基本类型和引用类型的作用效果是不同的对于基本数据类型来说比较的是值。对于引用数据类型来说比较的是对象的内存地址equals()不能用于判断基本数据类型的变量只能用来判断两个对象是否相等。equals()方法存在于Object类中而Object类是所有类的直接或间接父类因此所有的类都有equals()方法。hashCode()的作用是获取哈希码int整数也称为散列码。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode()定义在 JDK 的Object类中这就意味着 Java 中的任何类都包含有hashCode()函数。另外需要注意的是Object的hashCode()方法是本地方法也就是用 C 语言或 C 实现的。操作少量的数据: 适用String单线程操作字符串缓冲区下操作大量数据: 适用StringBuilder多线程操作字符串缓冲区下操作大量数据: 适用StringBufferString真正不可变有下面几点原因保存字符串的数组被final修饰且为私有的并且String类没有提供/暴露修改这个字符串的方法。String类被final修饰导致其不能被继承进而避免了子类破坏String不可变。StringBuilder对象是在循环内部被创建的这意味着每循环一次就会创建一个StringBuilder对象。字符串常量池是 JVM 为了提升性能和减少内存消耗针对字符串String 类专门开辟的一块区域主要目的是为了避免字符串的重复创建。Exception:程序本身可以处理的异常可以通过catch来进行捕获。Exception又可以分为 Checked Exception受检查异常必须处理 和 Unchecked Exception不受检查异常可以不处理。ErrorError属于程序无法处理的错误ClassNotFoundException是 Exception发生在使用反射等动态加载时找不到类是可预期的可以捕获处理。NoClassDefFoundError是 Error是编译时存在的类在运行时链接不到了比如 jar 包缺失是环境问题导致 JVM 无法继续。泛型一般有三种使用方式:泛型类、泛型接口、泛型方法Java 反射 (Reflection) 是一种在程序运行时动态地获取类的信息并操作类或对象方法、属性的能力。灵活性和动态性、解耦合和通用性、性能开销、安全性问题、代码可读性和维护性
JAVA基础知识
发布时间:2026/7/9 4:35:04
什么是字节码在 Java 中JVM 可以理解的代码就叫做字节码即扩展名为.class的文件它不面向任何特定的处理器只面向虚拟机。Java 语言通过字节码的方式在一定程度上解决了传统解释型语言执行效率低的问题同时又保留了解释型语言可移植的特点。所以 Java 程序运行时相对来说还是高效的不过和 C、 CRustGo 等语言还是有一定差距的而且由于字节码并不针对一种特定的机器因此Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。为什么说 Java 语言“编译与解释并存”这是因为 Java 语言既具有编译型语言的特征也具有解释型语言的特征。因为 Java 程序要经过先编译后解释两个步骤由 Java 编写的程序需要先经过编译步骤生成字节码.class文件这种字节码必须由 Java 解释器来解释执行。自增自减运算符和--运算符可以放在变量之前也可以放在变量之后1.前缀形式例如a或--a先自增/自减变量的值然后再使用该变量例如b a先将a增加 1然后把增加后的值赋给b。2.后缀形式例如a或a--先使用变量的当前值然后再自增/自减变量的值。例如b a先将a的当前值赋给b然后再将a增加 1。移位运算符高效、节省内存移位操作中被操作的数据被视为二进制数移位就是将其向左或向右移动若干位的运算。移位运算符最常用于快速乘以或除以 2 的幂次方。除此之外它还在以下方面发挥着重要作用位字段管理例如存储和操作多个布尔值。哈希算法和加密解密通过移位和与、或等操作来混淆数据。数据压缩例如霍夫曼编码通过移位运算符可以快速处理和操作二进制数据以生成紧凑的压缩格式。数据校验例如 CRC循环冗余校验通过移位和多项式除法生成和校验数据完整性。内存对齐通过移位操作可以轻松计算和调整数据的对齐地址。Java 中有三种移位运算符:左移运算符向左移若干位高位丢弃低位补零。x n相当于 x 乘以 2 的 n 次方不溢出的情况下。:带符号右移向右移若干位高位补符号位低位丢弃。正数高位补 0负数高位补 1。x n相当于 x 除以 2 的 n 次方。:无符号右移忽略符号位空位都以 0 补齐。移位操作符实际上支持的类型只有int和long编译器在对short、byte、char类型进行移位前都会将其转换为int类型再操作。continue指跳出当前的这一次循环继续下一次循环。break指跳出整个循环体继续执行循环下面的语句。return;直接使用 return 结束方法执行用于没有返回值函数的方法return value;return 一个特定值用于有返回值函数的方法Java 中有 8 种基本数据类型分别为6 种数字类型4 种整数型byte、short、int、long2 种浮点型float、double1 种字符类型char1 种布尔型boolean基本类型位数字节默认值取值范围byte810-128 ~ 127short1620-32768-2^15 ~ 327672^15 - 1int3240-2147483648 ~ 2147483647long6480L-9223372036854775808-2^63 ~ 92233720368547758072^63 -1char162u00000 ~ 655352^16 - 1float3240f1.4E-45 ~ 3.4028235E38double6480d4.9E-324 ~ 1.7976931348623157E308boolean1falsetrue、false基本类型和包装类型的区别基本类型和包装类型的区别基本类型和包装类型的区别用途除了定义一些常量和局部变量之外我们在其他地方比如方法参数、对象属性中很少会使用基本类型来定义变量。并且包装类型可用于泛型而基本类型不可以。存储方式基本数据类型的局部变量存放在 Java 虚拟机栈中的局部变量表中基本数据类型的成员变量未被static修饰存放在 Java 虚拟机的堆中。包装类型属于对象类型我们知道几乎所有对象实例都存在于堆中。占用空间相比于包装类型对象类型 基本数据类型占用的空间往往非常小。默认值成员变量包装类型不赋值就是null而基本类型有默认值且不是null。比较方式对于基本数据类型来说比较的是值。对于包装数据类型来说比较的是对象的内存地址。所有整型包装类对象之间值的比较全部使用equals()方法。装箱Boxing将基本类型用它们对应的引用类型包装起来拆箱Unboxing将包装类型转换为基本数据类型成员变量与局部变量的区别语法形式从语法形式上看成员变量是属于类的而局部变量是在代码块或方法中定义的变量或是方法的参数成员变量可以被public,private,static等修饰符所修饰而局部变量不能被访问控制修饰符及static所修饰但是成员变量和局部变量都能被final所修饰。存储方式从变量在内存中的存储方式来看如果成员变量是使用static修饰的那么这个成员变量是属于类的如果没有使用static修饰这个成员变量是属于实例的。而对象存在于堆内存局部变量则存在于栈内存。生存时间从变量在内存中的生存时间上看成员变量是对象的一部分它随着对象的创建而存在而局部变量随着方法的调用而自动生成随着方法的调用结束而消亡。默认值从变量是否有默认值来看成员变量如果没有被赋初始值则会自动以类型的默认值而赋值一种情况例外被final修饰的成员变量也必须显式地赋值而局部变量则不会自动赋值。成员变量有默认值核心原因是为了保证对象状态的安全和可预测性。成员变量和局部变量在这个规则上不同主要是因为它们的生命周期不一样导致了编译器对它们的“控制力”也不同。局部变量只活在一个方法里编译器能清楚地看到它是否在使用前被赋值所以编译器会强制你必须手动赋值否则就报错。成员变量是跟着对象走的它的值可能在构造函数里赋也可能在后面的某个setter方法里赋。编译器在编译时无法预测它到底什么时候会被赋值。并且如果一个变量没有被初始化它的内存里存放的就是“垃圾值”——之前那块内存遗留下的任意数据。如果程序读取并使用了这个垃圾值就会产生完全不可预测的结果比如一个数字变成了随机数一个对象引用变成了非法地址这会直接导致程序崩溃或出现诡异的 bug。为了避免你拿到一个含有“垃圾值”的危险对象Java 干脆为所有成员变量提供了一个安全的默认值如 null 或 0作为一种安全兜底机制。静态变量也就是被static关键字修饰的变量。它可以被类的所有实例共享无论一个类创建了多少个对象它们都共享同一份静态变量。也就是说静态变量只会被分配一次内存即使创建多个对象这样可以节省内存。字符型常量和字符串常量的区别形式 : 字符常量是单引号引起的一个字符字符串常量是双引号引起的 0 个或若干个字符。含义 : 字符常量相当于一个整型值ASCII 值可以参加表达式运算; 字符串常量代表一个地址值该字符串在内存中存放位置。占内存大小字符常量只占 2 个字节; 字符串常量占若干个字节。静态方法和实例方法有何不同调用方式调用静态方法无需创建对象访问类成员是否存在限制静态方法在访问本类的成员时只允许访问静态成员即静态成员变量和静态方法不允许访问实例成员即实例成员变量和实例方法而实例方法不存在这个限制对象的相等一般比较的是内存中存放的内容是否相等。引用相等一般比较的是他们指向的内存地址是否相等。区别点重载 (Overloading)重写 (Overriding)发生范围同一个类中。父类与子类之间存在继承关系。方法签名方法名必须相同但参数列表必须不同参数的类型、个数或顺序至少有一项不同。方法名、参数列表必须完全相同。返回类型与返回值类型无关可以任意修改。子类方法的返回类型必须与父类方法的返回类型相同或者是其子类。访问修饰符与访问修饰符无关可以任意修改。子类方法的访问权限不能低于父类方法的访问权限。public protected default private绑定时期编译时绑定或称静态绑定运行时绑定 (Run-time Binding) 或称动态绑定构造方法具有以下特点名称与类名相同构造方法的名称必须与类名完全一致。没有返回值构造方法没有返回类型且不能使用void声明。自动执行在生成类的对象时构造方法会自动执行无需显式调用。构造方法不能被重写override但可以被重载overload。因此一个类中可以有多个构造方法这些构造方法可以具有不同的参数列表以提供不同的对象初始化方式。封装是指把一个对象的状态信息也就是属性隐藏在对象内部不允许外部对象直接访问对象的内部信息。但是可以提供一些可以被外界访问的方法来操作属性。继承是使用已存在的类的定义作为基础建立新类的技术新类的定义可以增加新的数据或新的功能也可以用父类的功能但不能选择性地继承父类。通过使用继承可以快速地创建新的类可以提高代码的重用程序的可维护性节省大量创建新类的时间提高我们的开发效率。多态顾名思义表示一个对象具有多种的状态具体表现为父类的引用指向子类的实例。接口和抽象类的共同点实例化接口和抽象类都不能直接实例化只能被实现接口或继承抽象类后才能创建具体的对象抽象方法接口和抽象类都可以包含抽象方法。抽象方法没有方法体必须在子类或实现类中实现。接口和抽象类的区别设计目的接口主要用于对类的行为进行约束你实现了某个接口就具有了对应的行为。抽象类主要用于代码复用强调的是所属关系。继承和实现一个类只能继承一个类包括抽象类因为 Java 不支持多继承。但一个类可以实现多个接口一个接口也可以继承多个其他接口。成员变量接口中的成员变量只能是public static final类型的不能被修改且必须有初始值。抽象类的成员变量可以有任何修饰符private,protected,public可以在子类中被重新定义或赋值。方法Java 8 之前接口中的方法默认是public abstract也就是只能有方法声明。自 Java 8 起可以在接口中定义default默认 方法和static静态方法。 自 Java 9 起接口可以包含private方法。抽象类可以包含抽象方法和非抽象方法。抽象方法没有方法体必须在子类中实现。非抽象方法有具体实现可以直接在抽象类中使用或在子类中重写。浅拷贝浅拷贝会在堆上创建一个新的对象区别于引用拷贝的一点不过如果原对象内部的属性是引用类型的话浅拷贝会直接复制内部对象的引用地址也就是说拷贝对象和原对象共用同一个内部对象。深拷贝深拷贝会完全复制整个对象包括这个对象所包含的内部对象。对于基本类型和引用类型的作用效果是不同的对于基本数据类型来说比较的是值。对于引用数据类型来说比较的是对象的内存地址equals()不能用于判断基本数据类型的变量只能用来判断两个对象是否相等。equals()方法存在于Object类中而Object类是所有类的直接或间接父类因此所有的类都有equals()方法。hashCode()的作用是获取哈希码int整数也称为散列码。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode()定义在 JDK 的Object类中这就意味着 Java 中的任何类都包含有hashCode()函数。另外需要注意的是Object的hashCode()方法是本地方法也就是用 C 语言或 C 实现的。操作少量的数据: 适用String单线程操作字符串缓冲区下操作大量数据: 适用StringBuilder多线程操作字符串缓冲区下操作大量数据: 适用StringBufferString真正不可变有下面几点原因保存字符串的数组被final修饰且为私有的并且String类没有提供/暴露修改这个字符串的方法。String类被final修饰导致其不能被继承进而避免了子类破坏String不可变。StringBuilder对象是在循环内部被创建的这意味着每循环一次就会创建一个StringBuilder对象。字符串常量池是 JVM 为了提升性能和减少内存消耗针对字符串String 类专门开辟的一块区域主要目的是为了避免字符串的重复创建。Exception:程序本身可以处理的异常可以通过catch来进行捕获。Exception又可以分为 Checked Exception受检查异常必须处理 和 Unchecked Exception不受检查异常可以不处理。ErrorError属于程序无法处理的错误ClassNotFoundException是 Exception发生在使用反射等动态加载时找不到类是可预期的可以捕获处理。NoClassDefFoundError是 Error是编译时存在的类在运行时链接不到了比如 jar 包缺失是环境问题导致 JVM 无法继续。泛型一般有三种使用方式:泛型类、泛型接口、泛型方法Java 反射 (Reflection) 是一种在程序运行时动态地获取类的信息并操作类或对象方法、属性的能力。灵活性和动态性、解耦合和通用性、性能开销、安全性问题、代码可读性和维护性