Java基础知识(四) -- 面向对象(下)

1.类变量和类方法

1.1 类变量背景

有一群小孩在玩堆雪人,不时有新的小孩加入,请问如何知道现在共有多少人在玩?

思路分析: 核心在于如何让变量count被所有对象共享

public class Child {private String name;// 定义静态变量(所有Child对象共享)public static int count = 0;public Child() {}public Child(String name) {this.name = name;}public void join() {System.out.println(name + "加入游戏...");}
}public class ChildGame {public static void main(String[] args) {Child child1 = new Child("白骨精");child1.join();child1.count++;System.out.println("child1.count=" + child1.count);Child child2 = new Child("狐狸精");child2.join();child2.count++;System.out.println("child2.count=" + child2.count);Child child3 = new Child("老鼠精");child3.join();child3.count++;System.out.println("child3.count=" + child3.count);}
}

1.2 什么是类变量?

  类变量也叫静态变量/静态属性, 是该类的所有对象共享的变量, 是任何一个该类的对象访问该变量时, 获取的都是相同的值, 同样一个该类的对象去修改该变量时, 修改也是同一个变量。

1.3 如何定义类变量?

【访问修饰符】static 数据类型 变量名;

1.4 如何访问类变量?

类名.类变量名[推荐使用]
对象名.类变量名

1.5 类变量总结

    1. 当需要让某个类所有对象都共享一个变量时,就可以考虑使用类变量(静态变量)。
    1. 类变量是该类所有对象共享的, 而实例对象是每个对象独有的。
    1. 类变量的访问方式: 类名.类变量名 或者 对象名.类变量名, 但是推荐使用 类名.类变量名 的方式。
    1. 实例变量不可以使用 类名.类变量名 的方式访问。
    1. 类变量在类加载的时就初始化了, 即使没有创建对象, 只要类加载了, 就可以使用类变量了。
    1. 类变量的生命周期是随类的加载开始, 随着类消亡而销毁。

1.6 类方法介绍

  类方法也称为静态方法。

【访问修饰符】static 方法名(){}

1.7 类方法的调用

类名.方法名[推荐使用]
对象名.方法名

1.8 类方法总结

    1. 类方法和实例方法都是随着类的加载而加载, 将结构信息存储在方法区。
    1. 类方法可以通过类名调用, 也可以通过对象调用。
    1. 普通方法和对象有关,只能通过对象名.方法名调用。
    1. 类方法中不允许使用和对象相关的关键字, 比如this和super。
    1. 类方法(静态方法)中只能访问 静态变量 或者静态方法。
    1. 普通成员方法,既可以访问非静态成员,也可以访问静态成员。(遵守访问权限规则)
public class Test {static int count = 9;public void count() {System.out.println("count = " + ++count);}
}public class TestCount {public static void main(String[] args) {new Test().count();System.out.println(Test.count);//10}
}

2.理解main方法语法

public static void main(String args[]){}
  • ① main方法由虚拟机调用。
  • ② Java虚拟机需要调用main方法, 所以该方法的访问权限是public。
  • ③ Java虚拟机在执行main方法时不必创建对象, 所以该方法必须是static。
  • ④ 该方法接收String类型的数组参数, 该数组中保存执行Java命令时传递所运行的参数。
  • ⑤ Java执行程序 参数1 参数2 参数3
    在这里插入图片描述

注:

    1. 在main()方法中, 可以直接调用main方法所在类的静态方法或静态属性。
    1. 在main()方法中,不可以直接访问该类中的非静态成员,必须创建一个该类的实例对象后,才可以访问通过该对象去访问类中的非静态成员。
    public class Main01 {private static String name = "科比";public int n = 10000;public static void hi() {System.out.println("Main 01 的 hi 方法");}public void cry() {System.out.println("Main 01 的 cry 方法");}public static void main(String[] args) {//1.访问静态成员System.out.println("name=" + name);hi();// 访问非静态成员//System.out.println("n="+n);//报错//cry();//报错Main01 main01 = new Main01();System.out.println("n=" + main01.n);main01.cry();}
    }
    

3.代码块

3.1 概述

  代码块又称为初始化块, 属于类中的成员[即是类的一部分], 类似方法, 将逻辑语句封装在方法体中, 通过{}包围起来。但是和方法不同的是, 没有方法名, 没有返回值, 没有参数, 只有方法体, 而且不通过对象或者类显式调用, 而是在加载类时, 或者创建对象时隐式调用。

3.2 基本语法

【修饰符】{代码
}; 

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

② 代码块分两类, 使用 static 修饰的叫静态代码块, 没有static修饰的叫普通代码块或者非静态代码块。

③ 逻辑语句可以为任何逻辑语句(输入、输出、方法调用、循环、判断等)。

④ ; 可以写上, 也可以省略

3.3 代码块的好处

    1. 相当于另一种形式的构造器, 可以做初始化的操作。
    1. 如果多个构造器中有重复的语句, 可以抽取到初始化块中, 提高代码的复用性。
public class Movie {private String name;private double price;private String director;{System.out.println("电影屏幕打开...");System.out.println("广告开始...");System.out.println("电影正是开始...");};public Movie(String name) {System.out.println("Movie(String name) 被调用...");this.name = name;}public Movie(String name, double price) {System.out.println("Movie(String name, double price) 被调用...");this.name = name;this.price = price;}public Movie(String name, double price, String director) {System.out.println("Movie(String name, double price, String director) 被调用...");this.name = name;this.price = price;this.director = director;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}public String getDirector() {return director;}public void setDirector(String director) {this.director = director;}
}public class TestMovie {public static void main(String[] args) {Movie movie = new Movie("你好,李焕英");System.out.println("现在播放的电影是《"+movie.getName()+"》");System.out.println("===============");Movie movie2 = new Movie("唐人街探案3", 100, "陈思诚");System.out.println("现在播放的电影是由"+movie2.getDirector()+"导演拍摄的电影《"+movie2.getName()+"》,票价是:"+movie2.getPrice()+"元。");}
}

3.4 代码块总结

    1. static 代码块也叫静态代码块, 作用就是对类进行初始化, 而且随着类的加载而执行, 并且只会执行一次。如果是普通代码块, 每创建一个对象就执行。
    1. 类加载时机: ① 创建对象实例时(new) ② 创建子类对象实例, 父类也会加载 ③ 使用类的静态成员时(静态属性、静态方法)
    1. 普通的代码块, 在创建对象实例时, 会被隐式调用。被创建一次, 就会调用一次。如果只是使用类的静态成员时, 普通代码块并不会执行。
    1. 创建一个对象时, 在一个类的调用顺序是:
    • ① 调用静态代码块和静态属性初始化(两者优先级相同)
    • ② 调用普通代码块和普通属性初始化(两者优先级相同)
    • ③ 调用构造方法
    1. 构造器的最前面其实隐含了super()和调用普通代码块
    1. 创建一个子类对象(继承关系)时, 静态代码块、静态属性初始化, 普通代码块, 普通属性初始化, 构造方法的调用顺序:
    • ① 父类的静态代码块和静态属性(优先级一样, 按定义顺序执行)
    • ② 子类的静态代码块和静态属性(优先级一样, 按定义顺序执行)
    • ③ 父类的普通代码块和普通属性(优先级一样, 按定义顺序执行)
    • ④ 父类的构造方法
    • ⑤ 子类的普通代码块和普通属性(优先级一样, 按定义顺序执行)
    • ⑥ 子类构造方法
    1. 静态代码块只能调用静态成员(静态属性和静态方法), 普通代码块可以调用任意成员

4.单例设计模式

4.1 概述

  所谓类的单例设计模式, 就是采取一定的方法保证在整个的软件系统中, 对某个类只能存在一个对象实例, 并且该类只提供一个取得其对象实例的方法。单例设计模式有两种方式: ① 饿汉式 ② 懒汉式。

4.2 应用实例

4.2.1 饿汉式

步骤:

    1. 将构造器私有化
    1. 在类的内部直接创建对象(该对象是static)
    1. 提供一个公共的static 方法, 返回cat对象
public class TestSingle01 {public static void main(String[] args) {System.out.println(Cat.n);// 通过方法获取cat对象Cat instance = Cat.getInstance();System.out.println(instance);}
}class Cat {private String name;public static int n = 100;private static Cat cat = new Cat("小花");private Cat(String name) {System.out.println("有参构造器被调用");this.name = name;}public static Cat getInstance() {return cat;}@Overridepublic String toString() {return "Cat{" +"name='" + name + '\'' +'}';}
}
4.2.2 懒汉式

步骤:

    1. 将构造器私有化
    1. 定义一个static 静态属性对象
    1. 提供一个公共的static 方法, 返回cat对象
package JavaBase.single.lanhanshi;public class TestSingle02 {public static void main(String[] args) {Cat instance = Cat.getInstance();System.out.println(instance);}
}class Cat {private String name;private static Cat cat;private Cat(String name) {System.out.println("构造方法被调用....");this.name = name;}public static Cat getInstance() {if (cat == null) {cat = new Cat("小可爱");}return cat;}@Overridepublic String toString() {return "Cat{" +"name='" + name + '\'' +'}';}
}

4.2 饿汉式与懒汉式区别

    1. 二者最主要的区别在于创建对象的时机不同: 饿汉式是在类加载创建了对象实例, 而懒汉式是在使用时才创建
    1. 饿汉式不存在线程安全问题, 懒汉式存在线程安全问题
    1. 饿汉式存在资源浪费的问题, 如果对象实例没有使用, 饿汉式创建的对象就浪费了。
    1. 在JavaSE标准类中, java.lang.Runtime就是经典的单例模式

5.final关键字

5.1 概述

  final中文的意思是最后的、最终的。final可以修饰类、属性、方法和局部变量。在某些情况下, 会使用到final:

  • ① 当不希望类被继承时, 可以使用final修饰类。
  • ② 当不希望父类的某个方法被子类覆盖/重写(override),可以使用final修饰该方法。
  • ③ 当不希望类的某个属性值被修改, 可以使用final修饰该属性。
  • ④ 当不希望某个局部变量被修改, 可以使用final修饰该变量。

5.2 final使用细节

    1. final修饰的属性叫常量, 一般用 XX_XX_XX 来命名。
    1. final修饰的属性在定义时必须赋初始值, 且不能在修改, 赋值可以在如下位置:
    • ① 定义时: public final double TAX_RATE = 0.08
    • ② 在构造器中
    • ③ 在代码块中
    1. 如果final修饰的属性是静态的,则初始化的位置如下:
    • ① 定义时
    • ② 在静态代码块, 不能在构造器中赋值
    1. final修饰的类不能被继承, 但是可以实例化对象。
    1. 如果类不是final类, 但是含有final方法, 虽然该方法不能重写, 但是可以被继承。
    1. 如果一个类已经是final类, 就没必要再将方法修饰成final方法。
    1. final不能修饰构造方法。
    1. final和static往往搭配使用, 效率更高, 不会导致类加载, 底层编译器做了优化处理。
    1. 包装类(Integer,Double,Float,Boolean等都是final), String类也是final。

5.3 应用实例

/*** 编写程序,计算圆的面积,要求圆周率为3.14 赋值的位置:定义时/构造器/代码块*/
public class FianlExercise {public static void main(String[] args) {Circle circle = new Circle(5.0);System.out.println("面积=" + circle.Area());}
}class Circle {private double radius;private final double PI = 3.14;public Circle(double radius) {this.radius = radius;}public double Area() {return PI * radius * radius;}
}

6.抽象类

6.1 概述

  当父类的一些方法不能确定时, 可以用abstract关键字修饰该方法, 此方法即为抽象方法, 同理用abstract修饰的类即为抽象类。抽象类的价值在于设计, 在设计好之后让子类继承并实现抽象类。

6.3 语法格式

抽象类

访问修饰符 abstract 类名{}

抽象方法(无方法体)

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

6.3 使用细节

    1. 抽象类不能被实例化
    1. 抽象类不一定要包含abstract方法。
    1. 一旦类包含了abstract方法, 则这个类必须声明为abstract。
    1. abstract 只能修饰类和方法, 不能修饰属性和其他的。
    1. 抽象类可以有任意成员, 例如非抽象方法、构造器、静态属性等。
    1. 抽象方法不能有主体, 即不能实现。
    1. 如果一个类继承了抽象类, 则必须实现抽象类的所有抽象方法, 除非它自己声明为抽象类。
    1. 抽象类不能使用private、final和static关键字修饰, 因为它们与重写都是相违背的。

6.4 应用案例

编写程序员工类(抽象类), 经理继承员工类以及普通员工继承员工类。

// 员工抽象类
abstract public class Employee {private String name;private int id;private double salary;public Employee() {}public Employee(int id, String name, double salary) {this.id = id;this.name = name;this.salary = salary;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}// 经理类
public class Manager extends Employee {private double bonus;public Manager() {super();}public Manager(int id, String name, double salary) {super(id, name, salary);}public double getBonus() {return bonus;}public void setBonus(double bonus) {this.bonus = bonus;}@Overridepublic void work() {System.out.println("经理" + getName() + "工作中...");}
}// 普通员工类
public class CommonEmployee extends Employee {public CommonEmployee(int id, String name, double salary) {super(id, name, salary);}@Overridepublic void work() {System.out.println("普通员工" + getName() + "工作中...");}
}// 测试
public class TestAbstract01 {public static void main(String[] args) {Manager jack = new Manager(999,"jack",500);jack.setBonus(8000);jack.work();CommonEmployee tom = new CommonEmployee(111,"tom",300);tom.work();}
}

6.5 最佳实践

  抽象类体现的就是一种模板模式的设计, 抽象类作为多个子类的通用模板, 子类在抽象类的基础上进行扩展、改造, 但子类总体上会保留抽象类的行为方式。当功能内部一部分功能已确定, 另一部分不确定时, 可以将不确定的部分暴露出去, 让子类去实现。

需求:统计每个任务的完成时间

// 抽象类
abstract public class Template {//抽象方法public abstract void job();// 计算任务运行时间public void calculateTime() {// 开始时间long start = System.currentTimeMillis();// java的动态绑定机制job();// 结束时间long end = System.currentTimeMillis();System.out.println("任务执行时间为 " + (end - start) + " ms");}
}// Job1
public class Job1 extends Template{@Overridepublic void job()  {long num = 0;for (int i = 0; i < 1000000; i++) {num += i;}System.out.println("Job1 运行完成");}
}//Job2
public class Job2 extends Template{@Overridepublic void job() {long num = 1;for (int i = 0; i < 1000000; i++) {num *= i;}System.out.println("Job2 运行完成");}
}// 测试类
public class TestTemplate {public static void main(String[] args)  {Job1 job1 = new Job1();job1.calculateTime();Job2 job2 = new Job2();job2.calculateTime();}
}

7.接口

7.1 概述

  接口即为一些没有实现的方法封装到一起, 在某个类要使用时, 根据具体情况将这些方法写出来。接口体现了程序设计的多态和高内聚低耦合的设计思想。

7.2 语法格式

interface 接口名{//属性//抽象方法
}class 类名 implements 接口{// 属性(类)// 方法(类)// 实现接口的抽象方法
}
// 接口
public interface DBInterface {public void connect();public void close();
}public class MysqlDB implements DBInterface {@Overridepublic void connect() {System.out.println("连接mysql");}@Overridepublic void close() {System.out.println("关闭mysql");}
}public class OracleDB implements DBInterface{@Overridepublic void connect() {System.out.println("连接oracle");}@Overridepublic void close() {System.out.println("关闭oracle");}
}public class TestInterface {public static void main(String[] args) {MysqlDB mysqlDB = new MysqlDB();t(mysqlDB);OracleDB oracleDB = new OracleDB();t(oracleDB);}public static void t(DBInterface db){db.connect();db.close();}
}

7.3 使用细节

    1. 接口不能被实例化。
    1. 接口中所有的方法是public方法, 接口中的抽象方法, 可以不用abstract修饰。
    1. 一个普通类实现接口, 就必须将接口中所有的方法都实现。
    1. 抽象类实现接口, 可以不用实现接口的方法。
    1. 一个类同时可以实现多个接口。
    1. 接口的属性只能是final修饰, eg: public static final 变量名(必须初始化)。
    1. 接口中属性的访问方式: 接口名.属性名。
    1. 接口不能继承其他类, 但可以继承多个其他的接口。
    1. 接口的修饰符只能是public和默认。

7.4 实现接口与继承类的区别

  • ① 接口和继承解决的问题不同
    • 继承的价值在于:解决代码的复用性和可维护性。
    • 接口的价值在于:设计好各种规范, 提高灵活性。
  • ② 接口比继承更加灵活
    • 继承是满足 is-a 的关系。
    • 接口是满足 like-a 的关系
  • ③ 接口一定程度上实现代码解耦
    • 接口规范性+动态绑定机制
// 猴子
public class Monkey {private String name;public Monkey() {}public Monkey(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void climbing(){System.out.println(name + "会爬树...");}
}//接口
public interface Birdable {void flying();
}public interface Fishable {void swimming();
}public class LittleMonkey extends Monkey implements Fishable, Birdable {public LittleMonkey(String name) {super(name);}@Overridepublic void flying() {System.out.println(getName() + " 通过学习,可以像鱼儿一样游泳...");}@Overridepublic void swimming() {System.out.println(getName() + " 通过学习,可以像鸟儿一样飞翔...");}
}public class Test {public static void main(String[] args) {LittleMonkey wuKong = new LittleMonkey("孙悟空");wuKong.climbing();wuKong.swimming();wuKong.flying();}
}

注:当子类继承了父类, 就自动拥有父类的功能; 如果子类需要扩展功能, 可以通过接口的方式扩展。

7.5 接口的多态特性

    1. 接口的引用可以指向实现了接口的类对象
    1. 接口存在多态传递现象。

8.内部类

8.1 概述

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

8.2 基本语法

class Outer{ // 外部类class Inner{ // 内部类}
}
class Other{// 外部其他类
}

8.3 快速入门

public class InnerClass01 {public static void main(String[] args) {Outer outer = new Outer(10);outer.m1();}
}class Outer {private int n1 = 100;public Outer(int n1) {this.n1 = n1;}public void m1() {System.out.println("m1()被调用..." + "n1=" + n1);}{System.out.println("代码块...");}class Inner {private int n2 = 100;}
}

8.4 内部类分类

    1. 定义在外部类的局部位置上(eg:方法内)
    • ① 局部内部类(有类名)
    • ② 匿名内部类(无类名)
    1. 定义在外部类的成员位置上
    • ① 成员内部类(没用static修饰)
    • ② 静态内部类(使用static修饰)

8.5 局部内部类的使用

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

    1. 可以访问外部类的所有成员, 包含私有的
    1. 不能添加修饰符, 因为它是一个局部变量。局部变量不能使用修饰符, 但是可以使用final修饰。
    1. 作用域: 仅仅在定义它的方法或者代码块中。
    1. 局部内部类直接访问外部类的成员。
    1. 外部类需要先创建对象, 然后在通过对象访问局部内部类成员(必须在作用域内)。
    1. 外部其他类不能访问局部内部类。
    1. 如果外部类和局部内部类的成员重名时, 默认遵循就近原则, 如果想访问外部类的成员, 则可以使用(外部类名.this.成员)去访问。
    public class LocalInnerClass {public static void main(String[] args) {Outer02 outer02 = new Outer02();outer02.m1();System.out.println("outer02 的 hashcode=" + outer02);}
    }class Outer02 {private int n1 = 100;// 私有方法private void m2() {System.out.println("Outer02中的m2()方法被调用...");}public void m1() {// 局部内部类定义在外部类的局部位置,通常在方法内, 不能使用访问修饰,但是可以使用final修饰final class InnerClass02 {private int n1 = 80;public void f1() {//可以直接访问外部类的所有成员,包括私有的// 如果外部类和内部类的成员重名时,默认遵循就近原则, 使用外部类名.this.成员访问外部类的成员System.out.println("内部类的n1=" + n1 + " 外部类的n1=" + Outer02.this.n1);System.out.println("Outer02.this hashcode=" + Outer02.this);m2();}}// 外部类在方法中,可创建内部类对象,调用外部类的方法即可InnerClass02 innerClass02 = new InnerClass02();innerClass02.f1();}
    }
    

8.6 匿名内部类的使用

    1. 匿名内部类的语法
    new 类或接口(参数列表){类体
    }// 基于接口的匿名内部类
    public class AnonymousInnerClass {public static void main(String[] args) {Outer04 outer04 = new Outer04();outer04.method();}
    }class Outer04 {// 属性private int n1 = 10;// 方法public void method() {IA tiger = new IA() {@Overridepublic void cry() {System.out.println("老虎叫唤...");}};System.out.println("tiger 的运行类型=" + tiger.getClass());tiger.cry();tiger.cry();tiger.cry();}
    }// 基于类的匿名内部类
    public class Father {private String name;public Father(String name) {// 构造器this.name = name;System.out.println("接收到 name=" + name);}public void test() {//方法}
    }public class AnonymousInnerClass {public static void main(String[] args) {Outer04 outer04 = new Outer04();outer04.method();}
    }class Outer04 {private int n1 = 10;public void method() {Father father = new Father("jack") {@Overridepublic void test() {System.out.println("匿名内部类重写了 test 方法");}};System.out.println("father 对象的运行类型=" + father.getClass());//Outer04$2father.test();}
    }
    
    1. 匿名内部类既是一个类的定义, 同时它本身也是一个对象, 因此它既有类的特征, 也有对象的特征。
    1. 可以直接访问外部类的所有成员,包含私有的。
    1. 不能添加访问修饰符,因为它是一个局部变量。
    1. 作用域: 仅仅在定义它的方法或代码块中。
    1. 匿名内部类直接访问外部类成员, 外部其他类不能访问匿名内部类成员。
    1. 如果外部类和匿名内部类的成员重名时, 匿名内部类访问默认遵循就近原则, 如果想访问外部类的成员,则可以使用 [外部类名.this.成员] 去访问。
    //接口
    interface IL {void show();
    }//类->实现 IL => 编程领域 (硬编码)
    class Picture implements IL {@Overridepublic void show() {System.out.println("这是一副名画 XX...");}
    }public class InnerClassExercise01 {public static void main(String[] args) {//当做实参直接传递,简洁高效f1(new IL() {@Overridepublic void show() {System.out.println("这是一副名画~~...");}});//传统方法f1(new Picture());}//静态方法,形参是接口类型public static void f1(IL il) {il.show();System.out.println("静态方法已执行...");}
    }
    

8.7 成员内部类的使用

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

    1. 可以直接访问外部类的所有成员,包括私有。
    1. 可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。
    1. 作用域: 同其他成员一样, 为整个类体。
    1. 成员内部类直接访问外部类成员, 外部类通过创建对象的方式访问成员内部类。
    1. 外部其他类不能访问成员内部类。
    1. 如果外部类和内部类的成员重名时, 内部类访问默认遵循就近原则, 如果想访问外部类的成员, 则可以使用 外部类名.this.成员 访问。
    public class MemberInnerClass01 {public static void main(String[] args) {Outer05 outer05 = new Outer05();outer05.t1();Outer05.Inner05 inner05Instance = outer05.getInner05Instance();inner05Instance.say();}
    }class Outer05{private int n1 = 10;private String name = "张三";private void hi(){System.out.println("hi()方法被调用...");}// 成员内部类定义在外部类的成员位置上,可以使用任意访问修饰符修饰(它的位置就是一个成员)public class Inner05{private double sal = 99.8;private int n1 = 66;// 可以直接访问外部类的所有成员,包含私有的// 如果外部类和内部类的成员重名时,会遵守就近原则,内部类想访问外部类成员,可通过 外部类名.this.成员 访问public void say(){System.out.println("n1 = " + n1 + " name = " + name + " 外部类的 n1=" + Outer05.this.n1);hi();}}// 返回一个内部类实例public Inner05 getInner05Instance(){return new Inner05();}public void t1() {//创建成员内部类的对象,然后使用相关的方法Inner05 inner05 = new Inner05();inner05.say();hi();}
    }
    

8.8 静态内部类的使用

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

    1. 可以直接访问外部类的所有静态成员,包含私有的,不能直接反问非静态成员。
    1. 可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。
    1. 作用域: 同其他成员, 为整个类体。
    1. 静态内部类直接访问外部类的所有静态成员, 外部类通过创建对象的方式访问静态内部类的成员。
    1. 其他外部类不能访问静态内部类。
    1. 如果外部类和静态内部类的成员重名时, 静态内部类的访问遵循就近原则, 如果想访问外部类的成员, 则可以使用 外部类名.this.成员 访问。
    public class StaticInnerClass01 {public static void main(String[] args) {Outer10 outer10 = new Outer10();outer10.m1();Outer10.Inner10 inner10 = new Outer10.Inner10();inner10.say();}
    }class Outer10 {private int n1 = 10;private static String name = "张三";private static void cry() {}static class Inner10 {private static String name = "李四";public void say() {//如果外部类和静态内部类的成员重名时,静态内部类访问的时,//默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.成员)System.out.println(name + " 外部类 name= " + Outer10.name);cry();}}public void m1() { //外部类---访问------>静态内部类 访问方式:创建对象,再访问Inner10 inner10 = new Inner10();inner10.say();}public Inner10 getInner10() {return new Inner10();}public static Inner10 getInner10_() {return new Inner10();}
    }
    

9.总结

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/496718.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统之stat命令的基本使用

Linux系统之stat命令的基本使用 一、stat命令 介绍二、stat命令帮助2.1 查询帮助信息2.2 stat命令的帮助解释 三、stat命令的基本使用3.1 查询文件信息3.2 查看文件系统状态3.3 使用格式化输出3.4 以简洁形式打印信息 四、注意事项 一、stat命令 介绍 stat 命令用于显示文件或文…

雷池 WAF 搭配阿里云 CDN 使用教程

雷池 WAF&#xff08;Web Application Firewall&#xff09;是一款强大的网络安全防护产品&#xff0c;通过实时流量分析和精准规则拦截&#xff0c;有效抵御各种网络攻击。在部署雷池 WAF 的同时&#xff0c;结合阿里云 CDN&#xff08;内容分发网络&#xff09;可以显著提升网…

蓝桥杯速成教程{三}(adc,i2c,uart)

目录 一、adc 原理图​编辑引脚配置 Adc通道使能配置 实例测试 ​编辑效果显示 案例程序 badc 按键相关函数 测量频率占空比 main 按键的过程 显示界面的过程 二、IIC通信-eeprom 原理图AT24C02 引脚配置 不可用状态&#xff0c;用的软件IIC 官方库移植 At24c02手册 ​编辑…

Semantic Segmentation Editor标注工具

https://github.com/Hitachi-Automotive-And-Industry-Lab/semantic-segmentation-editor https://docs.meteor.com/about/install.html https://v2-docs.meteor.com/install.html 安装指定版本的meteor curl https://install.meteor.com/\?release\2.12 | sh ubuntu18 安…

攻防世界web新手第四题easyphp

<?php highlight_file(__FILE__); $key1 0; $key2 0;$a $_GET[a]; $b $_GET[b];if(isset($a) && intval($a) > 6000000 && strlen($a) < 3){if(isset($b) && 8b184b substr(md5($b),-6,6)){$key1 1;}else{die("Emmm...再想想&quo…

vxe-table 实现跨行按钮同时控制两行的编辑状态

vxe-table 写可编辑表格用起来很爽吧&#xff01;有没有遇到下面这种要用一个跨行按钮&#xff0c;控制两行编辑框是否可编辑的情况。是不是官网的方法不好实现了&#xff1f;那么这个应该怎么实现呢。最近刚好碰到这个问题。说下个人的实现思路。 其实也简单&#xff0c;既然官…

ES 磁盘使用率检查及处理方法

文章目录 1. 检查原因2. 检查方法3. 处理方法3.1 清理数据3.2 再次检查磁盘使用率 1. 检查原因 磁盘使用率在 85%以下&#xff0c;ES 可正常运行&#xff0c;达到 85%及以上会影响 PEIM 数据存储。 在 ES 磁盘分配分片控制策略中&#xff0c;为了保护数据节点的安全&#xff0…

论文解读 | EMNLP2024 一种用于大语言模型版本更新的学习率路径切换训练范式

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 点击 阅读原文 观看作者讲解回放&#xff01; 作者简介 王志豪&#xff0c;厦门大学博士生 刘诗雨&#xff0c;厦门大学硕士生 内容简介 新数据的不断涌现使版本更新成为大型语言模型&#xff08;LLMs&#xff…

【Linux 系统负载详情解析】

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把…

欲海航舟:探寻天性驱动下的欲望演变与人生驾驭

欲海航舟&#xff1a;探寻天性驱动下的欲望演变与人生驾驭。 欲望之源起&#xff0c;本乎天性。 鸿蒙初辟&#xff0c;生灵乍现&#xff0c;欲望即随人之性灵而生&#xff0c;如花木之根柢&#xff0c;虽隐匿于地下&#xff0c;却为生长之根基。 人之初诞&#xff0c;懵懂无…

WebRTC 环境搭建

主题 本文主要描述webrtc开发过程中所需的环境搭建 环境&#xff1a; 运行环境&#xff1a;ubuntu20.04 Node.js环境搭建 安装编译 Node.js 所需的依赖包: sudo apt-get updatesudo apt-get install -y build-essential libssl-dev下载 Node.js 源码: curl -sL https://…

QT-------认识QT

QT简介 QT是一个跨平台的C图形用户界面应用程序框架&#xff0c;由挪威Trolltech公司于1991年开发并发布。它为开发者提供了一套丰富的类库和工具&#xff0c;用于创建各种类型的应用程序&#xff0c;包括桌面应用、移动应用、嵌入式系统应用等。QT具有高度的可定制性和可扩展…

SpringBoot配置文件、热部署、YAML语法、配置文件值注入

SpringBoot的配置文件 文章目录 SpringBoot的配置文件1.SpringBoot的热部署2.配置文件2.1配置文件的作用2.2YAML配置文件&#xff1a;2.3YAML 与 JSON 和 XML 的对比 3.YAML语法3.1键值对3.2值的写法3.3对象、Map&#xff08;属性和值&#xff09;&#xff08;键值对&#xff0…

基于BiTCN双向时间卷积网络实现电力负荷多元时序预测(PyTorch版)

Bidirectional Temporal Convolutional Network \begin{aligned} &\text{\Large \color{#CDA59E}Bidirectional Temporal Convolutional Network}\\ \end{aligned} ​Bidirectional Temporal Convolutional Network​ Bidirectional Temporal Convolutional Network (BiTC…

【JavaEE】Spring Web MVC

目录 一、Spring Web MVC简介 1.1 MVC简介1.2 Spring MVC1.3 RequestMapping注解1.3.1 使用1.3.2 RequestMapping的请求设置 1.3.2.1 方法11.3.2.2 方法2 二、Postman介绍 2.1 创建请求2.2 界面如下&#xff1a;2.3 传参介绍 一、Spring Web MVC简介 官方文档介绍&#xff…

低成本Type - C单口便携屏的全方位解析

在科技迅猛发展的当下&#xff0c;便携式电子产品在日常生活中的地位愈发重要。Type - C单口便携显示器作为新兴显示设备脱颖而出。本文将简述其特点、应用场景、技术原理与发展趋势。 一、特点 Type - C单口便携显示器最大的优势是便携性。它以Type - C接口进行数据传输与供电…

TestMAX/DFT Compiler:时序单元的类型、连接顺序和后DFT优化

相关阅读 TestMAX/DFT Compilerhttps://blog.csdn.net/weixin_45791458/category_12865937.html?spm1001.2014.3001.5482 时序单元的状态 未映射的时序单元(Unmapped Sequential Cell) 在Design Compiler读取了一个RTL设计后&#xff0c;Design Compiler内置的HDL Compiler工…

「瑞仕云曜璟庭」多轨交通+成熟配套 杨浦滨江宜居之高地

1. 均价不足11w 内环内真正高性价比 作为顶级城市资源的集中地&#xff0c;内环向来是购房者争相角逐的重中之重。 但是&#xff0c;内环很小&#xff0c;价格很高。 目前内环的二手房最高挂牌价已经达到约31.95万/㎡&#xff0c;最高成交价已经达到约33.79万/㎡&#xff…

基于STM32的智能家居环境监控系统设计

目录 引言系统设计 硬件设计软件设计系统功能模块 环境监控模块控制模块显示模块系统实现 硬件实现软件实现系统调试与优化结论与展望 1. 引言 随着智能家居技术的发展&#xff0c;环境监控系统已经成为家居管理的重要组成部分。智能家居环境监控系统通过实时监测室内温度、湿…

游戏开发线性空间下PS工作流程

前言 使用基于物理的渲染&#xff0c;为了保证光照计算的准确&#xff0c;需要使用线性空间&#xff1b; 使用线性空间会带来一个问题&#xff0c;ui 在游戏引擎中的渲染结果与 PS 中的不一致&#xff1a; PS&#xff08;颜色空间默认是sRGB伽马空间&#xff09;&#xff1a…