基础概念
Java特点
- 面向对象:继承,封装(把数据和操作数据的方法捆绑在一起,比如
setName
和getName
),多态(多态是指一个引用变量到底会调用哪个类的方法,由具体的类型决定。一个变量如果声明为父类的类型,但实际引用的是子类的对象,那么该变量可以调用父类的所有方法,也可以调用子类重写父类的方法,但不能调用子类独有的方法。) - Java的平台无关性:编译一次到处运行。主要通过两个技术实现:字节码(
.class
文件,可以在任何JVM
执行)和JVM(Java虚拟机解释执行字节码) - 可靠性:自动内存管理机制(Java 中的对象不需要程序员手动释放,当它们不再被使用时,垃圾收集器(Garbage Collector)会自动回收其占用的内存。主要是两个部分:堆内存管理(当new创建对象时JVM会在堆区为该对象分配内存,不再被引用时就变成垃圾)和垃圾收集(当一个对象没有任何引用指向它时,垃圾收集器就会认定它是垃圾,然后在适当的时机自动清理掉它))(过度使用静态变量可能导致内存溢出或内存泄漏)
- .......
JVM vs JDK vs JRE
JVM
Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。字节码(.class
)和不同系统的 JVM 实现是 Java 语言“一次编译,随处可以运行”的关键所在。
JVM 并不是只有一种!只要满足 JVM 规范,每个公司、组织或者个人都可以开发自己的专属 JVM。
JDK 和 JRE
JDK(Java Development Kit),它是功能齐全的 Java SDK,是提供给开发者使用的,能够创建和编译 Java 程序。他包含了 JRE,同时还包含了编译 java 源码的编译器 javac 以及一些其他工具比如 javadoc(文档注释工具)、jdb(调试器)、jconsole(基于 JMX 的可视化监控⼯具)、javap(反编译工具)等等。
JRE(Java Runtime Environment) 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有内容的集合,主要包括 Java 虚拟机(JVM)、Java 基础类库(Class Library)。
字节码
.java -> javac编译 -> .class -> 解释器&JIT -> 机器代码
当JIT编译之后会把字节码对应的机器码保存下来下次直接使用
AOT
(Ahead of Time Compilation),它是直接将字节码编译成机器码
编译与解释并存
编译型:编译型语言会通过编译器将源代码一次性翻译成可被该平台执行的机器码。一般情况下,编译语言的执行速度比较快,开发效率比较低。常见的编译性语言有 C、C++、Go、Rust 等等
解释型:解释型语言会通过解释器一句一句的将代码解释(interpret)为机器代码后再执行。解释型语言开发效率比较快,执行速度比较慢。常见的解释性语言有 Python、JavaScript、PHP 等等。
Java 程序要经过先编译,后解释两个步骤
基本语法
移位运算符
<<
:左移运算符,向左移若干位,高位丢弃,低位补零。x << 1
,相当于 x 乘以 2(不溢出的情况下)。
>>
:带符号右移,向右移若干位,高位补符号位,低位丢弃。正数高位补 0,负数高位补 1。x >> 1
,相当于 x 除以 2。
>>>
:无符号右移,忽略符号位,空位都以 0 补齐。因此一定会得到一个正值
以上针对的是整型,double和float不行
对于正数,其二进制补码与原码相同;对于负数,其二进制补码是该数的绝对值的二进制表示按位取反后加 1。
基本数据类型
Java 里使用 long
类型的数据一定要在数值后面加上 L,否则将作为整型解析
八种基本类型都有对应的包装类分别为:Byte
、Short
、Integer
、Long
、Float
、Double
、Character
、Boolean
泛型
泛型是一种编程语言的特性,允许程序员在强类型编程语言中编写具有不特定数据类型的代码。泛型提供了代码可重用性和类型检查的优势。你可以将任何类型的数据传递给泛型结构,因此可以避免为每种数据类型编写单独的代码。同时,由于在编译时进行类型检查,所以运行时出错的可能性降低。
基本类型和包装类型的区别
- 用途:除了定义一些常量和局部变量之外,我们在其他地方比如方法参数、对象属性中很少会使用基本类型来定义变量。并且,包装类型可用于泛型,而基本类型不可以。
- 存储方式:基本数据类型的局部变量存放在 Java 虚拟机栈中的局部变量表中,基本数据类型的成员变量(未被
static
修饰 )存放在 Java 虚拟机的堆中,静态类存放在方法区的静态域。包装类型属于对象类型,我们知道几乎所有对象实例都存在于堆中 - 占用空间:相比于包装类型(对象类型), 基本数据类型占用的空间往往非常小。
- 比较方式:对于基本数据类型来说,
==
比较的是值。对于包装数据类型来说,==
比较的是对象的内存地址。所有整型包装类对象之间值的比较,全部使用equals()
方法。 - 默认值:成员变量包装类型不赋值就是
null
,而基本类型有默认值且不是null
。
包装类型的缓存机制
Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能
Byte
,Short
,Integer
,Long
这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character
创建了数值在 [0,127] 范围的缓存数据,Boolean
直接返回 True
or False
。浮点数没有实现缓存
如果是在缓存范围内去比较==
返回值会是true
,如果超范围的话会返回false
,因为会创建新的对象
自动装箱与拆箱
Integer i = 10; //装箱
int n = i; //拆箱
频繁拆装箱的话,会严重影响系统的性能
浮点数运算的精度丢失
我们可以通过以下步骤将十进制的小数转换为二进制:
- 把小数部分乘以2。
- 将得到的结果的整数部分(结果可能为1或者0)写下来作为二进制的下一位。
- 将结果的小数部分再乘以2。
- 重复步骤2和步骤3,直至结果的小数部分为0,或者达到所需的精度。
计算机是二进制的,而且计算机在表示一个数字时,宽度是有限的,无限循环的小数存储在计算机时,只能被截断
BigDecimal
可以实现对浮点数的运算,不会造成精度丢失。通常情况下,大部分需要浮点数精确运算结果的业务场景(比如涉及到钱的场景)都是通过 BigDecimal
来做的
超过 long 整型的数据应该如何表示
BigInteger
内部使用 int[]
数组来存储任意大小的整形数据。这是一个对象,加减乘除使用的是方法调用
变量
成员变量与局部变量
- 语法形式:从语法形式上看,成员变量是属于类的,而局部变量是在代码块或方法中定义的变量或是方法的参数;成员变量可以被
public
,private
,static
等修饰符所修饰,而局部变量不能被访问控制修饰符及static
所修饰;但是,成员变量和局部变量都能被final
所修饰。final赋值即为常量 - 存储方式:从变量在内存中的存储方式来看,如果成员变量是使用
static
修饰的,那么这个成员变量是属于类的,如果没有使用static
修饰,这个成员变量是属于实例的。而对象存在于堆内存,局部变量则存在于栈内存 - 生存时间:从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动生成,随着方法的调用结束而消亡。
- 默认值:成员变量如果没有被赋初始值,则会自动以类型的默认值而赋值(一种情况例外:被
final
修饰的成员变量也必须显式地赋值),而局部变量则不会自动赋值。
字符型常量和字符串常量的区别
字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)
方法
静态方法为什么不能调用非静态成员
- 静态方法是属于类的,在类加载的时候就会分配内存,可以通过类名直接访问。而非静态成员属于实例对象,只有在对象实例化之后才存在,需要通过类的实例对象去访问。
- 在类的非静态成员不存在的时候静态方法就已经存在了,此时调用在内存中还不存在的非静态成员,属于非法操作。
静态方法和实例方法
调用静态方法可以无需创建对象,一般不建议使用 对象.方法名
的方式来调用静态方法。这种方式非常容易造成混淆,静态方法不属于类的某个对象而是属于这个类。
重载和重写
重载就是同样的一个方法能够根据不同的传参做出不同的处理
重写就是当子类继承自父类的相同方法,输入数据一样,但要做出有别于父类的响应时,你就要覆盖父类方法
- 方法名、参数列表必须相同,子类方法返回值类型应比父类方法返回值类型更小或相等,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。
- 如果父类方法访问修饰符为
private/final/static
则子类就不能重写该方法,但是被static
修饰的方法能够被再次声明 - 构造方法无法被重写
方法的重写要遵循“两同两小一大“
- “两同”即方法名相同、形参列表相同;
- “两小”指的是子类方法返回值类型应比父类方法返回值类型更小或相等,基本数据类型必须保持不变,子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等;
- “一大”指的是子类方法的访问权限应比父类方法的访问权限更大或相等。(即不能设为更严格的访问级别,比如父类是public子类必须也是public)
可变长参数
在调用方法时传入不定长度的参数,可变参数只能作为函数的最后一个参数,但其前面可以有也可以没有任何其他参数
遇到方法重载的情况会优先匹配固定参数的方法,因为固定参数的方法匹配度更高。
标签:Java,变量,基础,JVM,类型,父类,方法 From: https://www.cnblogs.com/xccx-0824/p/17594319.html