static关键字
1、静态变量
静态变量,也称为类变量,是属于类而不是类的任何具体实例的。静态变量在所有实例中共享一份,它的生命周期与类的生命周期一致,即从类加载到卸载期间始终存在。
示例:
public class Counter {
// 静态变量
private static int count = 0;
public Counter() {
count++;
}
// 静态方法用于访问静态变量
public static int getCount() {
return count;
}
}
count是一个静态变量,所有Counter类的实例共享这一个count变量。每次创建Counter实例时,count值增加1。可以通过Counter.getCount()方法访问count变量,不需要创建Counter实例。
2. 静态方法
静态方法是属于类的方法,而不是属于对象的方法。静态方法不能访问实例变量和实例方法,只能访问其他静态变量和静态方法。静态方法通常用于操作静态数据或执行与类本身相关的操作。
示例:
public class MathUtils {
// 静态方法
public static int add(int a, int b) {
return a + b;
}
public static int multiply(int a, int b) {
return a * b;
}
}
在这个示例中,add和multiply是静态方法,你可以直接通过类名调用这些方法,例如MathUtils.add(5, 3),而无需创建MathUtils类的实例。
3. 静态块
静态块用于初始化静态变量。静态块在类加载时执行,且只执行一次。通常用于初始化静态数据或进行类级别的配置。
示例:
public class Config {
private static String environment;
static {
// 静态块初始化
environment = System.getenv("APP_ENV");
System.out.println("Environment variable set to: " + environment);
}
}
在这个例子中,静态块用于从环境变量中读取配置,并将其赋值给静态变量environment。静态块的代码在类加载时执行一次,为类的静态成员初始化。
4. 静态类
在Java中,你还可以定义静态内部类。静态内部类与外围类的实例无关,只能访问外围类的静态成员。
示例:
public class OuterClass {
private static String staticMessage = "Static Message";
static class InnerStaticClass {
void printMessage() {
// 访问外围类的静态成员
System.out.println(staticMessage);
}
}
}
在这个例子中,InnerStaticClass是OuterClass的一个静态内部类。它可以访问OuterClass的静态成员staticMessage,但不能访问OuterClass的实例成员。
多态
多态是面向对象编程中的一个核心概念,它允许对象以多种形式存在。在Java中,多态使得对象能够以不同的方式响应相同的方法调用,这种能力是Java语言的强大之处。通过多态,Java程序可以在运行时动态决定方法调用的具体实现,提高了代码的灵活性和可扩展性。
什么是多态?
多态是指同一操作作用于不同的对象,可以有不同的解释和不同的执行结果。换句话说,方法的调用根据对象的不同,可能会有不同的行为。Java中的多态主要体现在两个方面:
-方法重载
-方法重写
1. 方法重载
方法重载是指在同一个类中,允许有多个同名的方法,它们的参数列表不同(包括参数的类型、数量或顺序)。方法重载的主要目的是提高代码的可读性和简洁性。
public class OverloadExample {
// 方法1:无参数
public void display() {
System.out.println("Display without parameters");
}
// 方法2:一个int参数
public void display(int a) {
System.out.println("Display with int parameter: " + a);
}
// 方法3:两个int参数
public void display(int a, int b) {
System.out.println("Display with two int parameters: " + a + ", " + b);
}
}
在上述代码中,display方法有三个不同的版本,它们通过不同的参数列表区分开来。这就是方法重载的例子。
2. 方法重写
方法重写发生在子类中,当子类继承父类并提供父类方法的具体实现时,就会发生方法重写。通过方法重写,子类可以根据自身的需要修改父类的行为。Java实现运行时多态的主要机制是方法重写和父类引用指向子类对象。
基本语法:
class Parent {
// 被子类重写的方法
public void show() {
System.out.println("Parent's show method");
}
}
class Child extends Parent {
// 重写父类的方法
@Override
public void show() {
System.out.println("Child's show method");
}
}
public class TestPolymorphism {
public static void main(String[] args) {
// 父类引用指向子类对象
Parent obj = new Child();
obj.show(); // 调用子类的show方法
}
}
在上述代码中,Parent类有一个show方法,Child类重写了这个方法。当创建一个Parent类型的对象并指向Child实例时,调用show方法时实际上会调用Child类中的show方法。这就是运行时多态的体现。
程序的执行流程两个小示例
/*
* 流程:
* 0、程序被执行,main方法启动程序
* 1、扫描B类,结果B类除Object外无父类
* 2、B.class被加载到JVM栈内存,同时执行static
* 3、执行main语句,new A();A类构造器被触发
* 4、扫描A类,A类有父类B,但已经被加载到内存
* 5、将A.class加载到内存,同时执行static
* 6、执行A()构造方法,扫描A类有父类B,调用并执行直接父类构造器B
* 7、执行构造器A()
* 8、main方法结束,进程返回0
* */
public class A extends B {
static {
System.out.println("static A");
}
public A() {
System.out.println("constructor A");
}
}
class B {
static {
System.out.println("static B");
}
public B() {
System.out.println("constructor B");
}
public static void main(String[] args) {
new A();
}
}
/*
* 流程:
* 0、程序被执行,操作系统定向到main方法启动程序
* 1、扫描cday类,结果cday类有父类nday,先去扫描父类nday
* 2、扫描nday类,结果nday没有除Object类以外的父类,结束扫描
* 3、将nday.class二进制文件加载到方法区,此时执行static代码块
* 4、将cday.class二进制文件加载到方法区,此时执行static代码块
* 5、main方法执行语句new cday();
* 6、new申请内存后执行构造器cday(),构造器cday调用父类构造器nday
* 7、由于nday除Object外无父类,于是执行nday构造器
* 8、执行cday构造器
* 9、进程结束,返回给jvm为0,正常退出,jvm回收内存
* */
public class cday extends nday {
static {
System.out.println("I'm static output from cday");
}
public cday() {
System.out.println("I'm constructor of cday");
}
public static void main(String[] args) {
new cday();
}
}
class nday {
static {
System.out.println("I'm static output from nday");
}
public nday() {
System.out.println("I'm constructor of nday");
}
}