3772 字
19 分钟
Views
面向对象高级
2025-08-02
无标签

static#

作用范围#

static不能修饰局部变量和构造器,可以修饰成员变量,成员方法,代码块,内部类,

类变量和类方法#

类变量#

在类里 public static int count = 0;这样的就是类变量,重点在于static关键词,使得同一个类的所有的对象(实例)都共享

类变量可以通过类名.类变量名访问或对象名.类变量名,推荐前一种(不违背访问修饰符的前提下)

实例变量不能通过类名.类变量名方式访问

类变量在类加载时就出初始化了,即使没有创建对象,只要类加载了,就可以使用类变量了

类变量的生命周期是随类加载开始,随着类消亡而销毁

类方法#

访问修饰符 static 数据返回类型 方法名(){}

调用:类名.类方法名或者对象名.类方法名

普通方法不能够通过类名.对象名的方式调用

类方法的使用场景:在不创建实例的情况下就可以调用某个方法(即当做工具类来使用),在实际开发中,把一些通用的方法设计成静态方法,这样可以直接使用

类方法和普通方法都是随着类的加载而加载,将结构信息储存在方法区

类方法不允许使用和对象有关的关键字,比如this和super,普通方法可以用

类方法无法通过继承来重写

类方法中只能访问静态变量或者静态方法,普通的都可以访问

理解main方法#

java虚拟机需要调用类的main方法,所以该方法的访问权限必须是public

java虚拟机在执行main()方法,所以该方法必须是static

该方法接受String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数

java 执行的程序 参数1 参数2 参数3 (java Hello.java 你好 你好 你好)-

在main()方法中,我们可以直接调用main方法所在类的静态方法或静态属性

但是,不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员

代码块#

基本介绍#

代码块又称初始化块,属于类中的成员,类似于方法,将逻辑语句封装在方法体内,通过{}包围起来。

但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显式调用,而是加载类时,或创建对象时隐式调用

基本语法#

[修饰符]{};

修饰符可选,要写的话,也只能写static

代码块分为两类,有static的叫静态代码块,没有static修饰的,叫普通代码块

逻辑语句可以为任何逻辑语句

;可以写也可以不写

作用#

另一种形式的构造器,可以做初始化的操作

不管调用哪个构造器,都会先调用代码块,代码块调用的顺序会高于构造器

场景:如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性

细节#

static代码块也叫静态代码块,作用就是对类进行初始化,而且它会随着类的加载而执行,并且只会执行一次,如果是普通代码块,没创建一个对象,就执行

普通的代码块,在创建对象实例时,会被隐式的调用,被创建一次,就会调用一次。如果只是使用类的静态成员时,普通代码块并不会执行

创建一个对象时,在一个类中的调用顺序是(详细对象与类关于创建过程的详细解释)

  • 调用静态代码块和静态属性初始化(都有按照定义顺序调用)
  • 调用普通代码块和普通属性的初始化(都有按照定义顺序调用)
  • 调用构造方法
  • 构造器的最前面其实隐含了super()和调用普通代码块(调用和初始化是两回事)

静态代码块只能调用静态成员,普通代码块可以调用任意成员

final关键字#

作用域#

final 可以修饰类,属性,方法和局部变量//属性其实就是一种局部变量

功能#

类不能被继承

方法不能被重写

属性的值不能被修改

注意事项和细节#

final修饰的属性又叫常量,用XX_XX_XX来命名

final修饰的属性,必须赋初值,并且以后不能再修改,赋值可以在如下位置之一

  • 定义时,public final double TAX_RATE = 0.08
  • 在构造器中
  • 在代码块中

如果final修饰的属性是静态的,则初始化的位置只能是

  • 定义时
  • 在静态代码块,不能在构造器中赋值

final类不能继承,但是可以实例化对象

如果类不是final类,但是含有final方法,则该方法虽然不能重写,但是可以被继承

一般来说,如果一个类已经是final类了,就没有必要再将方法修饰成final方法

final不能修饰构造器

final和static往往搭配处理,效率更高,底层编译器做了优化处理

包装类(Integer,Double,Float,Boolean)等都是final,String也是final类

抽象类#

当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类,抽象类是为了代码复用

概念#

所谓抽象方法就是没有实现的方法

所谓没有实现就是没有方法体

当一个类中存在抽象方法的时候,需要将该类声明为abstract类

一般来说,抽象类会被继承,由子类来实现抽象方法

语法#

访问修饰符 abstract 类名{}

访问修饰符 abstract 返回类型 方法名(参数列表);//没有方法体

继承的类需要重写方法(加上方法体)或者继承的子类也是abstract类

注意事项和细节#

抽象类不能被实例化

抽象类不一定要包含abstract 方法,抽象类可以没有抽象方法

抽象类可以作为编译类型,但是不能作为运行类型

一旦类中包含了abstract方法,那么这个类必须声明为abstract

abstract只能修饰类和方法,不能修饰属性和其他的

抽象类还是类,可以有任意成员

抽象方法不能有方法体

如果一个类继承了抽象类,那么它必须实现抽象类的所有抽象方法,除非它自己 也声明为abstract类

抽象方法不能使用private final 和static来修饰,因为这些关键字都是和重写相违背的

模版设计模式#

把通用的部分抽象出来做一个抽象的父类,子类继承父类并且补全抽象方法

接口#

接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,在根据具体情况吧这些方法写出来,接口是为了定义行为规范

语法#

interface 接口名{//属性,//方法}

  • 接口默认的方法都是抽象的,没必要写abstract

class 类名 implements 接口{//自己的属性,//自己的方法,//必须实现接口的抽象方法 }

在jdk7以前,接口里所有方法都没有方法体,jdk8.0后接口可以有静态方法,默认方法(必须写default)

使用细节#

接口不能被实例化

接口中所有方法是public方法,接口中抽象方法可以不用abstract来修饰

一个普通类实现接口,就必须将该接口的所有方法都实现,可以使用alt+enter 来解决

抽象类实现接口,可以不实现接口的方法

一个类可以实现多个方法

接口汇总的属性,只能是final的,而且是public static final, 比如int a = 1;实际上是public static final int a =1;(必须初始化)

接口汇总属性的访问形式:接口名.属性名

一个接口不能继承其他的类,但是可以继承多个别的接口

接口的修饰符只能是public和默认,和类是一样的(public class )

如果接口和继承的父类有同一个名称(x)属性的话,子类使用(x)必须要声明是哪个的

接口vs继承#

继承是 is a 的关系,接口是has a 的关系

接口是一种规范,继承是一种减少代码量的模版

继承只能单继承,接口可以有多个

接口在一定程度上实现代码解耦【接口规范性+动态绑定机制】

接口的多态特性#

接口同样可以有不同的“运行类型”“编译类型”

interface USB{
public void connect();
}
class MyUSB implements USB{
public void connect(){
System.out.println("USB connected");
}
}
class AnotherUSB extends MyUSB{
public void connect(){
System.out.println("Another USB connected");
}
}
MyUSB usb = new MyUSB();
usb = new AnotherUSB();

多态参数:一个接口可以接受多个实现了接口的类

interface USB{
public void connect();
}
class MyUSB implements USB{
public void connect(){
System.out.println("USB connected");
}
}
class MyPrinter implements USB{
public void connect(){
System.out.println("Printer connected");
}
}
class MyComputer{
private USB usb;
public MyComputer(USB usb){
this.usb = usb;
}
public void connect(){
usb.connect();
}
}

多态数组:同样可以用instance of来遍历数组,使用类特有的方法 接口的多态传递

interface USB{
public void connect();
}
interface usbFactory extends USB{
}

内部类#

介绍#

一个类的内部又完整的嵌套了另一个类就结构,被嵌套的类被称为内部类(inner class),嵌套其他类的类被称为外部类,是类的第五大成员(成员属性,成员方法,代码块,构造器,内部类),内部类最大的特点就是可以直接访问私有属性,并且可以提现类与类之间的包含关系

分类#

  • 定义在外部类局部位置上(比如方法内):

    • 局部内部类(有类名)
    • 匿名内部类(没有类名)
  • 定义在外部类的成员位置上:

    • 成员内部类(没有static修饰)
    • 静态内部类(使用static修饰)

局部内部类#

语法示例#

class Outer02{public void m1(){ class Inner02{ }}}

细节与使用#

局部内部类是定义在外部类的局部位置,比如方法中,并且有类名

可以直接访问外部类的所有成员,包括私有的

不能添加访问修饰符,因为它的地位就是一个局部变量,局部变量不能使用访问修饰符,但是可以使用final修饰,因为局部变量也可以使用final

作用域:仅仅在定义它的方法或代码块中

局部内部类——访问——外部类的成员【访问方式:直接访问】

外部类——访问——局部内部类的成员【访问方式:创建对象再访问,必须在作用域内】

外部其他类不能使用局部内部类,因为局部内部类地位是一个局部变量

如果外部类和局部内部类的成员重名时,遵循就近原则,如果想访问外部类的成员,可以使用外部类名.this.成员去访问

  • 外部类名.this本质上是外部类的对象,即哪个对象调用了这行代码,外部类名.this就是哪个对象

匿名内部类#

本质是类,内部类,该类没有名字,同时还是对象,继承了new 后面的对象

语法#

new 类或接口(参数列表){类体};

示例#

interface IA{
public void methodA();
}
public class Test {
public static void main(String[] args) {
IA obj = new IA() {
@Override
public void methodA() {
System.out.println("Method A");
}
};
obj.methodA();
}
}

作用#

用于只使用一次的类,简化开发

可以用来当做实参直接传递

本质#

jdk底层在创建匿名内部类的时候,立即就创建了实例,并且把地址返回给对象的引用

细节#

  1. 匿名内部类使用一次就不能再使用
  2. 可以访问外部类的所有成员,包括私有的
  3. 不能添加访问修饰符,因为它的地位就是一个局部变量
  4. 作用域:仅仅在定义它的方法或者代码块汇总
  5. 匿名内部类 直接访问 外部类成员
  6. 外部其他类 不能访问 匿名内部类(因为匿名内部类地位就是一个局部变量)
  7. 如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果访问外部类的成员,则可以使用外部类名.this.成员去访问

成员内部类#

成员内部类是定义在外部类的成员位置,并且没有static修饰

语法例子#

class Outer{
public class Inner{
}
}

细节#

可以直接访问外部类的所有成员,包括私有的

可以添加任意访问修饰符,因为它的地位就是一个成员

作用域:和外部类的其他成员一样,为整个类体

成员内部类 访问 外部类(直接访问)

外部类 访问 内部类(创建对象,再访问)

外部其他类 访问 成员内部类(两种方式)

  • 先创建外部类,然后创建内部类
  • 在外部类中,编写一个方法,可以返回Inner对象

如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用外部类名.this.成员去访问

静态内部类#

静态内部类是定义在外部类的成员位置,并且有static修饰

语法示例#

class Outer{
public static class Inner{
//静态成员只能访问静态方法或者变量
}
}

细节#

可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员

可以添加任意访问修饰符,因为它就是一个成员

作用域:和其他成员相同,是整个类体

静态内部类 访问 外部类(直接访问)

外部类 访问 静态内部类(创建对象,在访问)

外部其他类 访问 静态内部类(两种方式)

  • 创建对象后访问
  • 写一个方法来访问

如果外部类和静态内部类的成员重名时,静态内部类访问的时候,遵循就近原则,如果想访问外部类的成员,可以使用外部类名.成员去访问

评论