Skip to main content

关键字

Static关键字

成员变量

  • 静态变量,可以直接通过类名访问

成员方法

  • 静态方法,本类中直接访问,其他类直接通过类名访问

代码块

  • 静态代码,当Java虚拟机加载类时,就会执行该代码块

创建对象也叫做实例(真真实实存在的一个个例)化,对象级别也称之为实例级别。

修饰属性

static修饰属性,称之为静态属性,也叫静态变量,也叫类变量

被static修饰的属性,不属于任何对象,只属于当前类,可以被此类的所有对象共享,在内存中只存在一份

在类文件加载到方法区时创建变量并执行初始化。

静态属性:本类中直接访问(例如:name),其他类通过类名加点访问(例如:Drink.name)。

静态属性推荐使用类名加点访问(例如:Drink.name),因为静态属性不属于任何对象,不推荐使用对象名加点的方式访问(drink.name)

静态修饰属性 在idea中字体是倾斜的

package com.staticPart;

public class Drink {
String name;
// 静态修饰属性 在idea中字体是倾斜的
static int water = 100;
// 构造方法
public Drink(String name) {
this.name = name;
}

public Drink() {
}

// 喝水方法
public void getWater(){
if(water > 0 ){
water -= 2;
System.out.println(name + "接水2L,剩余" + water +"L");
}else{
System.out.println("没水了");
}
}
// 测试类
public static void main(String[] args) {
// 实例化1
Drink drink = new Drink("yousa");
drink.getWater(); // yousa接水2L,剩余98L
// 通过对象名访问 静态属性 (不推荐)
drink.water = 200;
// 通过类名访问静态属性,在本类中直接访问
water = 201;
// 通过类名访问静态属性
Drink.water = 202;

// 实例化2
Drink drink2 = new Drink("Reine");
drink2.getWater(); // Reine接水2L,剩余198L
}
}

在实例方法中不可以定义 static 属性变量。原因:实例方法是在创建对象后才可以调用,而static变量在加载类时就会被创建,不属于任何对象,两者的范围不同。

修饰方法

静态无法访问实例的属性和方法原因:
静态访问实例的属性前提是这个实例必须先要new出来,要先存在这个实例才可以访问到。有静态的时候不一定有对象。

同样原因:父类无法访问子类
父类需要在子类存在的情况下才能访问,父类是无法得知子类是否存在。

静态方法:本类中直接调用,其他类通过类名加点调用。

静态方法不同于静态属性,因为方法只有调用的过程才会执行,调用就会进栈。

静态方法可以被继承。

静态方法:可直接通过类名访问

  • 静态方法中不能使用this和super
  • 不能直接访问所属类的实例变量和实例方法
  • 可直接访问类的静态变量和静态方法

实例方法:通过实例访问

  • 可直接访问所属类的静态变量、静态方法、实例变量和实例方法
  • main()就是最常用的静态方法
package com.staticPart;

public class Eat {
// 属性
String name;
String food;
static int remain = 100;
// 构造方法
public Eat(){}
// 构造方法
public Eat(String name,String food){
this.name = name;
this.food = food;
}
// 实例方法
public void info(){
System.out.println(this.name + "吃了" + this.food + "现在剩余的事物数量为:"+ remain);
}
// 静态方法 drink
public static void eatFood(){
// 静态方法中使用静态属性
Eat.remain -= 1;
}
// 测试类
public static void main(String[] args) {
Eat eater = new Eat("九月","泡面");
// 实例调用静态方法:会出现警告,但是可以使用
eater.eatFood();
// 实例调用实例方法
eater.info();
// 实例调用静态属性:会出现警告,但是可以使用
System.out.println("现在剩余的事物数量"+eater.remain);
}
}

修饰代码块

什么是代码块
直接由{}包裹的代码块

静态代码块,普通代码块和方法的区别
静态代码块是随着JVM加载类时而执行,多个静态代码块按照书写顺序执行,每个只执行一次。
普通代码块会随着对象创建而执行,每创建一个对象,就执行一次。
方法只有在调用的时候才会执行。

什么时候会加载类
1. new对象
2. 访问类中的静态属性或者静态方法

静态代码块特性
1.静态代码块是随着JVM加载类时而执行。
2.多个静态代码块按照书写顺序执行。
3.每个只执行一次。
4.静态代码块的执行会在构造方法之前执行。

静态代码块的用途
1.当我们需要执行一些前置的操作,并且这个操作只需要执行一次(例如连接数据库操作,数据初始化等操作,读取硬盘数据到内存中)

创建对象过程

对象创建过程

image-20250701105433939

前提:
方法区:Java的Sun公司提出的一种规范,把这种格式的内存区域称之为方法区。
永久代和元数据,元空间分别指的是JDK7JDK8对方法区的一个命名。两者的关系例如学校和大学中学小学之间的关系。
方法区类比学校,永久代类比某某大学,元空间类比某某中学之类。

对象创建过程:
1. 将当前对象所属类对应的class文件加载到方法区
在加载类信息文件(class文件)之前,会先判断此类是否已经被加载过。
如果加载过,则直接执行第2步。
如果没有加载过,则先加载。
加载类的同时会在方法区的静态区初始化静态相关的信息,此时静态相关的信息将有初始值,但对象还没有创建完成。
2.在堆中开辟空间创建对象,此时实例级别的属性将有默认值
3.将堆中的地址赋值给栈中的引用,完成对象的创建。

注意:
类只加载一次。
静态属性只存在一份。

native关键字

在 Java 中,native 是一个 关键字,用于声明本地方法(native method)。它的作用是告诉 Java 编译器:这个方法的实现并不是用 Java 写的,而是由其他语言(通常是 CC++)在本地库中实现的。
调用非 Java 语言编写的代码,主要用于调用 C/C++ 编写的函数。
实现与操作系统、硬件、驱动等底层系统交互。
提供 性能优化 或访问 Java 无法直接访问的底层功能。

常见用途

常见用途:

与硬件或系统接口打交道(如串口通信、系统调用等)
利用已有的 C/C++
性能要求极高的代码(如图像处理、音视频处理)
操作 JVM 无法直接访问的资源

instanceof

instanceof 对象类型检查判断
参数:无
返回值:boolean

例子:
对象名 instanceof 类名
Person p1 = new Person()
boolean result = p1 instanceof Dog

super

见 封装和继承 章节

this

见 封装和继承 章节

final关键字

final可以用来修饰 属性、方法、类。

修饰属性

修饰属性:

被final修饰的属性称之为常量,名称全部大写,多个单词之间使用下划线分割,常量只能被赋值一次。

final修饰的属性特征

通常(99%)在定义的时候赋值,
或者在构造方法中赋值,这两种方式都是为了保证在使用常量之前是有值的。

基本数据类型:值不能被改变。
引用数据类型:地址不能被改变,地址中的内容(属性)是可以改变。

final关键字使用示例:

package com.finalFiled;

public class TestFinalFiled {
// 定义 圆周率 PI
final double PI = 3.14;
// 定义 座位数 基本数据类型
final int SEAT_COUNT;
// 定义 引用数据类型
final char [] SIGNS = new char[3];
double radius;

// 在构造方法中赋值
public TestFinalFiled() {
SEAT_COUNT = 60;
}
// 在构造方法中赋值
public TestFinalFiled(double radius) {
SEAT_COUNT = 70;
this.radius = radius;
}
// 测试类
public static void main(String[] args) {
// 创建实例
TestFinalFiled testFinalFiled = new TestFinalFiled();
// testFinalFiled.PI = 3.24; // 报错:final修饰的变量,仅允许被赋值一次
testFinalFiled.radius = 10; // 普通实例方法可以被赋值多次
System.out.println("圆的面积为" + testFinalFiled.radius * testFinalFiled.radius * testFinalFiled.PI);

// 引用数据类型地址不能改变
// testFinalFiled.SIGNS = new char[2]; // 报错:final修饰的变量,仅允许被赋值一次,数据类型是引用数据类型,地址不能改变。
// 引用数据类型内容可以改变
testFinalFiled.SIGNS[0] = 'a';
testFinalFiled.SIGNS[1] = 'b';
testFinalFiled.SIGNS[2] = 'c';
}
}

final修饰的属性,属于实例级别的,每new一个对象,就会在内存中存在一份。这样,又因为。。。,所以常常再加上public权限修饰符,加大使用范围。

被final修饰的属性称之为常量,表示其值或者地址不能被改变。

这样的数据通常也没有必要存在多份,所以实际开发中经常会用static,final修饰不允许被改变的数据。

因为只有一份 且,数据无法改变,所以通常也会再加上public修饰,称之为:全局 静态 常量。

静态常量:通常在定义的时候赋值,或者在静态代码块中赋值,这两种方式同样是为了保证在使用常量之前是有值的。

public static final 使用示例

package com.finalFiled;

/**
* 被final修饰的属性称之为常量 表示其值或者地址不能被改变
* 这样的数据通常也没有必要存在多份 所以实际开发中经常会用static final修饰不允许被改变的数据
* 因为只有一份 且 数据无法改变 所以通常也会再加上public修饰 称之为:全局 静态 常量
*
* 静态常量:通常在定义的时候赋值 或者 在静态代码块中赋值 这两种方式同样是为了保证在使用常量之前是有值的
*/

public class TestStaticFinalField {
// 定义 全局静态常量
public static final double PI = 3.14;
// 定义 静态常量
static final String COUNTRY_NAME;

// 在代码块中 给静态常量赋值
static{
COUNTRY_NAME = "中华人民共和国";
}
// 定义 构造方法
public TestStaticFinalField(){

}
}

修饰方法

final修饰的方法不能被子类重写

final修饰的方法特征

package com.finalFiled;

/**
* final修饰的方法不能被子类重写
*/
public class TestFinalMethod {
class A{
public final void m1(){
System.out.println("A类m1方法");
}

public void m2(){
System.out.println("A类m2方法");
}
}

class B extends A{
public void m2(){
System.out.println("A类m2方法重写");
}

// public void m1(){ // 报错,不能重写父类 final 修饰的方法
// System.out.println("A类m1方法重写");
// }

}
}

修饰类

被final修饰的类不能被继承,例如:String类就是使用final修饰的

final修饰的类特征

package com.finalFiled;

public class TestFinalClass {
// 静态方法
public static void main(String[] args) {

}
// final 修饰类
final class C{
public void print(){
System.out.println("我是final修饰的C类");
}
}

// class D extends C{ // 报错 final修饰的 类 不能被继承。
// public void print(){
// System.out.println("我是D类");
// }
// }
}