秦疆的JavaSE课程笔记:73 面向对象 static关键字详解
1.秦疆的JavaSE课程笔记:01-04 前言2.秦疆的JavaSE课程笔记:05-08 预科 上3.秦疆的JavaSE课程笔记:09-12 预科 下4.秦疆的JavaSE课程笔记:13-16 入门 上5.秦疆的JavaSE课程笔记:17-20 入门 下6.秦疆的JavaSE课程笔记:21 基础 注释7.秦疆的JavaSE课程笔记:22 基础 标识符和关键字8.秦疆的JavaSE课程笔记:23 基础 数据类型9.秦疆的JavaSE课程笔记:24 基础 数据类型扩展及面试题讲解10.秦疆的JavaSE课程笔记:25 基础 类型转换11.秦疆的JavaSE课程笔记:26 基础 变量 常量 作用域12.秦疆的JavaSE课程笔记:27 基础 基本运算符13.秦疆的JavaSE课程笔记:28 基础 自增自减运算符 初识Math类14.秦疆的JavaSE课程笔记:29 基础 逻辑运算符 位运算符15.秦疆的JavaSE课程笔记:30 基础 三元运算符及小结16.秦疆的JavaSE课程笔记:31 基础 包机制17.秦疆的JavaSE课程笔记:32 基础 JavaDoc生成文档18.秦疆的JavaSE课程笔记:33 流程控制 Scanner19.秦疆的JavaSE课程笔记:34 流程控制 Scanner进阶使用20.秦疆的JavaSE课程笔记:35 流程控制 顺序结构21.秦疆的JavaSE课程笔记:36 流程控制 if选择结构22.秦疆的JavaSE课程笔记:37 流程控制 switch选择结构23.秦疆的JavaSE课程笔记:38 流程控制 while循环详解24.秦疆的JavaSE课程笔记:39 流程控制 do...while循环25.秦疆的JavaSE课程笔记:40 流程控制 For循环详解26.秦疆的JavaSE课程笔记:41 流程控制 打印九九乘法表27.秦疆的JavaSE课程笔记:42 流程控制 增强For循环28.秦疆的JavaSE课程笔记:43 流程控制 break、continue、goto29.秦疆的JavaSE课程笔记:44 流程控制 打印三角形及Debug30.秦疆的JavaSE课程笔记:45 方法 什么是方法31.秦疆的JavaSE课程笔记:46 方法 方法的定义和调用32.秦疆的JavaSE课程笔记:47 方法 方法的重载33.秦疆的JavaSE课程笔记:48 方法 命令行传递参数34.秦疆的JavaSE课程笔记:49 方法 可变参数35.秦疆的JavaSE课程笔记:50 方法 递归讲解36.秦疆的JavaSE课程作业:50 方法 编写简易Scanner计算器37.秦疆的JavaSE课程笔记:51-52 数组 什么是数组&数组的声明和创建38.秦疆的JavaSE课程笔记:53 数组 三种初始化及内存分析39.秦疆的JavaSE课程笔记:54 数组 下标越界及小结40.秦疆的JavaSE课程笔记:55 数组 数组的使用41.秦疆的JavaSE课程笔记:56 数组 二维数组42.秦疆的JavaSE课程笔记:57 数组 Arrays类讲解43.秦疆的JavaSE课程笔记:58 数组 冒泡排序44.秦疆的JavaSE课程笔记:59 数组 稀疏数组45.秦疆的JavaSE课程笔记:60 面向对象 什么是面向对象46.秦疆的JavaSE课程笔记:61-62 面向对象 回顾方法的定义&回顾方法的调用47.秦疆的JavaSE课程笔记:63 面向对象 类与对象的创建48.秦疆的JavaSE课程笔记:64 面向对象 构造器详解49.秦疆的JavaSE课程笔记:65-66 面向对象 创建对象内存分析&简单小结类与对象50.秦疆的JavaSE课程笔记:67 面向对象 封装详解51.秦疆的JavaSE课程笔记:68 面向对象 什么是继承52.秦疆的JavaSE课程笔记:69 面向对象 Super详解53.秦疆的JavaSE课程笔记:70 面向对象 方法重写54.秦疆的JavaSE课程笔记:71 面向对象 什么是多态55.秦疆的JavaSE课程笔记:72 面向对象 instanceof和类型转换
56.秦疆的JavaSE课程笔记:73 面向对象 static关键字详解
57.秦疆的JavaSE课程笔记:74 面向对象 抽象类58.秦疆的JavaSE课程笔记:75 面向对象 接口的定义与实现59.秦疆的JavaSE课程笔记:76 面向对象 N种内部类60.秦疆的JavaSE课程笔记:77 异常 Error和Exception61.秦疆的JavaSE课程笔记:78 异常 捕获和抛出异常62.秦疆的JavaSE课程笔记:79 异常 自定义异常及经验小结- 先看变量
public class Student {
private static int age; //静态变量
private double score; //非静态变量
public static void main(String[] args) {
System.out.println(Student.age);
System.out.println(Student.score); //报错“无法从static上下文引用非static字段”
Student s1 = new Student();
System.out.println(s1.age); //IDEA提示,“通过实例引用访问static成员OOP.demo.Student.age。可改成:System.out.println(age);
System.out.println(s1.score);
}
}
-
推荐使用类名访问静态变量,比如这里就是用
Student.age
访问静态变量age
。 -
但在静态方法中使用类名访问非静态变量就会出错,比如这里
main
方法是静态的,访问非静态变量score
就报错了。 -
我的看法:如果分析内存的话,类静态成员是在和类一起加载的,这时非静态变量应该是尚未加载,所以无法调用。而通过
Student s1 = new Student();
语句实例化对象之后,非静态变量才完成加载,这时才可以调用。 -
将类型实例化之后,通过对象调用对象属性就没有任何限制,比如这里的
s1.age
和s1.score
。 -
s1.age
那个提示,实际是在说走了弯路,因为静态成员可以直接调用,没必要再通过对象调用。当然这里只是作为示例。 -
再看看方法
public class Student {
public void run() {} //非静态方法
public static void go() {} //静态方法
public static void main(String[] args) {
go();
run(); //报错,无法从static上下文引用非static方法
Student s2 = new Student();
s2.run();
s2.go(); //IDEA提示:通过实例访问static成员
}
}
-
报错和提示的原因都是和上面一样的。
-
代码块和静态代码块
public class Demo {
//代码块(匿名代码块)
//程序在运行时并不能主动调用这些匿名代码块
//在构造器之前执行
{
}
//加上static关键词,就是静态代码块了
//类加载时,就会执行且只执行一次。
static {
}
}
- 演示如下:
public class Person {
//匿名代码块
{
System.out.println("匿名代码块");
}
//静态代码块
static {
System.out.println("静态代码块");
}
//构造方法
public Person() {
System.out.println("构造方法");
}
//主程序方法
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("***********");
Person person2 = new Person();
}
}
====运行结果如下====
静态代码块
匿名代码块
构造方法
***********
匿名代码块
构造方法
-
静态代码块和类一起加载,所以最早执行。
-
第二个时匿名代码块,会在构造方法之前执行。
-
构造方法执行最晚,是在主程序中创建实例对象
person
时才执行的。 -
之前说过,静态代码块仅在类加载时执行一次,和是否调用构造方法无关。
-
但是匿名代码块似乎每次创建对象时,就会先执行匿名代码块,再执行构造方法。
-
静态导入包
//import java.lang.Math; 一般导入的写法
//import java.lang.Math.random; 若直接导入一个类会报错
import static java.lang.Math.random; //但是可以加关键词static导入,这就是静态导入包
import static java.lang.Math.PI; //查看源码可知,PI是一个由final修饰的double类型常量
public class Test {
public static void main(String[] args) {
//一般情况下,调用Math类中的方法和变量
System.out.println(Math.random());
System.out.println(Math.PI);
//静态导入包后,调用Math类的方法和变量
System.out.println(random());
System.out.println(PI);
}
}
- 秦疆老师提到一个话题之外的小细节,用
final
修饰的类,是无法被继承的。
合集:
JavaSE课程笔记
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)