面向对象编程(高级)

面向对象编程(高级)

1、类变量和类方法

(1) 概念

类变量,也称为静态变量,是指在类级别声明的变量。它们与特定类相关联,而不是与类的实例(对象)相关联。每个类变量只有一份副本,它被类的所有实例共享。

static 变量保存在Class实例的尾部。而class对象确实存在堆中,所以,可以认为,static放在堆中

理解:

  • static变量是同一个类所有对象共享
  • static类变量,在类加载的时候就生成了

类方法(静态方法)是与类本身相关联的方法,而不是与类的实例(对象)相关联。它们可以直接通过类名调用不需要实例化对象。当方法中不涉及到任何对象相关的成员,就可以将方法设计成静态方法,提高开发效率。

举例:比如工具类里面的方法utils,Math类、Arrays类、Collections集合

(2)定义
类变量语法:1、 访问修饰符 static 数据类型 变量名;(推荐)2static 访问修饰符 数据类型 变量名;类方法语法:1、 访问修饰符 static 数据返回类型 方法名(){};(推荐)2static 访问修饰符 数据返回类型 方法名(){};
(3)访问
类变量访问:1、 类名.类变量名  (推荐)  静态变量的访问修饰符的访问权限和范围和普通变量是一样的。2、 对象名.类变量名类方法访问:1、 类名.类方法名  (推荐)  静态变量的访问修饰符的访问权限和范围和普通变量是一样的。2、 对象名.类方法名 

举例:

类变量:

public class StaticTest {public static void main(String[] args) {//类名.类变量名//类变量是随着类的加载而创建,不用创建对象也可以访问System.out.println(A.name);A a = new A();//通过对象名.类变量名也可以访问System.out.println(a.name);}
}class A{//类变量也需要遵循相关的访问权限public static String name = "你好";//普通属性/普通成员变量/非静态属性/非静态成员变量private int num = 10;
}

类方法:

public class Student {public static void main(String[] args) {//类.类方法进行调用Stu.Pay(100);Stu.Pay(200);Stu.Show();System.out.println(MyTools.calSum(10,30));}
}//开发自己的工具类,可以将方法做成静态的,方便调用
class MyTools{public static double calSum(double n1, double n2){return n1 + n2;}
}class Stu{public static double totalFee = 0;private String name;public Stu(String name) {this.name = name;}//1、方法使用static修饰时,该方法就为静态方法//2、静态方法只能访问静态变量public static void Pay(double fee){Stu.totalFee += fee;}public static void Show(){System.out.println("总学费为"+totalFee);}
}
(4)注意事项和细节
  1. 什么时候需要用类变量

    需要某个类的所有对象都共享一个变量时,就可以考虑使用类变量(静态变量)

  2. 类变量和实例变量(普通变量)的区别

    类变量时类的所有对象共享,实例变量是每个对象共享

  3. 实例变量不能通过 类名.类变量名,进行访问

  4. 静态变量是类加载的时候,就创建了,所以不需要实例化对象,也可以访问

  5. 类变量的声明周期是随着类的加载开始,随着类消亡而销毁

  6. 静态方法(类方法)只能访问静态成员

  7. 类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区,类方法中无this参数,普通方法中隐藏着this参数。普通方法主要不能直接通过类名.类方法进行调用

  8. 类方法中不允许使用和对象有关的关键字,比如thissuper,普通方法可以

(5)类方法与普通方法的对比
特点普通方法(实例方法)类方法(静态方法)
关联实例隶属于类的实例,通过实例化对象调用不隶属于特定对象实例,直接通过类名调用
访问实例变量可以访问和操作实例变量和实例方法,也可以访问静态方法、静态变量不能直接访问实例变量或实例方法,只能访问静态方法和静态变量
thissuper关键字可以在方法中使用 this 关键字、super关键字不能在方法中使用 thissuper 关键字
动态绑定支持动态绑定,根据对象类型执行方法不支持动态绑定,根据类类型执行方法
非静态上下文在对象实例上下文中执行在静态上下文中执行

2、理解main方法

public static void main(String[] args){}
  1. main方法是虚拟机调用的

  2. java虚拟机需要调用类的main方法(不同类、不同包),所以该方法的访问权限必须是public

  3. java虚拟机在执行main()方法的时候不用创建对象,所以该方法是static

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

    java 执行的程序 参数1 参数2 参数3
    
  5. main方法中,可以直接调用main所在类的静态方法和静态属性,但是不能使用非静态方法和属性,除非创建该类的实例对象之后,才能通过这个对象去访问类的

IDEA如果给main函数传参:

在这里插入图片描述

3、代码块

(1)概念

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

(2)语法
[修饰符]{代码
};
  1. 修饰符可选,要么不写,要么就是static写了static的代码块叫静态代码块,没有static修饰的,叫普通代码块/非静态代码块
  2. 最后面的分号可写可不写。里面的代码可以是任何的逻辑语句(比如:输入、输出、方法调用,循环,判断等等)
  3. 相当于另外一种形式的构造器(对于构造器的补充机制),可以做初始化的操作,如果多个构造器里面都有重复的雨具,可以抽取到初始化块当中,提高代码的重用性。
(3)注意事项
  1. 静态代码块(static),作用是对类进行初始化,随着类的加载而执行,并且 只会执行一次,如果是普通的代码块,每创建一个对象,就会执行。

  2. 类什么时候被加载?【重要】

    1. 创建对象实例时(new
    2. 创建子类对象实例,父类会被加载
    3. 使用类的静态成员时(静态属性、静态方法)
  3. 普通的代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会被调用一次。如果只是使用类的静态成员时,普通代码块并不会执行。

  4. 创建对象时,一个类的调用顺序【重点和难点】:

    1. 调用静态代码块和静态属性的位置(多个则按顺序来)
    2. 调用普通代码块和普通属性(多个按顺序来)
    3. 调用构造方法

    举例:

    package JavaEE.chapter08.CodeBlock;public class CodeBlockDetail02 {public static void main(String args[]){A a = new A();}
    }class A{private int n2 = getN2();private static int n1 = getN1();{System.out.println("A的普通代码块");}static {System.out.println("A的静态代码块");}public static int getN1(){System.out.println("getn1被调用");return 100;}public int getN2(){System.out.println("A普通方法被调用");return 200;}public A(){System.out.println("无参构造器");}}/*输出
    getn1被调用
    A的静态代码块
    A普通方法被调用
    A的普通代码块
    无参构造器
    */
    
  5. 构造器的最前面隐含了super()和调用普通代码块,静态相关的代码块,属性初始化在类加载的时,就执行完毕了,因此是优先于构造器和普通代码块执行的。

    举例:

    class A{public A(){	//构造器//隐藏的执行要求//(1)super();//(2)调用普通代码块System.out.println("无参构造器");}
    }
    
  6. 创建子类对象时,静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法调用顺序:

    1. 父类的静态代码块和静态属性
    2. 子类的静态代码和静态属性
    3. 父类的普通代码块和普通属性
    4. 父类的构造方法
    5. 子类的普通代码块和普通属性
    6. 子类的构造方法

    个人总结:

    1. 类加载(父类->子类)相关static代码执行
    2. 构造器
      1. super(父类)
      2. 普通代码块
      3. 构造方法
  7. 静态代码块只能调用静态成员,普通方法可以调用任意成员。

4、单例设计模式

(1)设计模式

设计模式是在大量的实践中总结和理论化之后优选的代码结构,编程风格,以及解决问题的思考方式。

(2)单例设计模式介绍
  1. 单例设计模式就是在整个的软件系统中,采取一定的方法保证某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法

  2. 实现方式

    1. 饿汉式(还没有用到对象,可能对象已经创建好)

      • 构造器私有化
      • 类的内部构造对象
      • 向外暴露一个静态的公共方法返回对象

      举例:

      class GirlFriend {private String name;//第一步:将构造器私有化private GirlFriend(String name){this.name = name;}//第二步,在类的内部直接创建静态对象private static GirlFriend gf = new GirlFriend("小红");//第三步:提供一个公共的static方法,返回gf对象public static GirlFriend getInstance(){return gf;}@Overridepublic String toString() {return "GirlFriend{" +"name='" + name + '\'' +'}';}
      }
      
    2. 懒汉式(只有当用户使用getInstance的时候,才返回对象,再次调用时,返回是上次创建的cat对象)

      • 第一步:构造器私有化
      • 第二步:定义一个新的static静态对象
      • 第三步:提供一个publicstatic方法,可以返回一个对象

      举例:

      //单例设计模式的懒汉式
      class Cat{private String name;public static int n1 = 999;//第一步:构造器私有化private Cat(String name) {System.out.println("类加载。。。。");this.name = name;}//第二步:定义一个新的static静态对象private static Cat cat;//第三步:提供一个public的static方法,可以返回一个Ca对象public static Cat getInstance(){//还没有对象,就创建对象if(cat == null){cat = new Cat("小花喵");}return cat;}@Overridepublic String toString() {return "Cat{" +"name='" + name + '\'' +'}';}
      }
      
(3)饿汉式和懒汉式对比
  1. 饿汉式是在类加载的时候就创建了对象实例,而懒汉式是在使用时才创建
  2. 饿汉式不存在线程安全问题,懒汉式存在线程安全问题
  3. 饿汉式存在浪费资源的可能,懒汉式不存在这个问题
  4. javaSE中,java.lang.Runtime是一个经典的单例模式

5、FINAL 关键字

final 是 Java 中的一个关键字,它可以确保常量的值不会被修改。对于方法和类,它可以确保方法实现或类结构不会被修改或继承改变,这在某些情况下有助于代码的安全性和性能优化。

(1)final应用场景
  1. 对变量使用 final
    • 当应用于变量时,final 关键字表示该变量只能被赋值一次。一旦赋值后,就不能再更改。这适用于基本数据类型和对象引用。
    • 例如:final int x = 10; 声明了一个只能被赋值一次的整数变量 x
  2. 对方法使用 final
    • 当应用于方法时,final 表示该方法不能被子类重写(覆盖)。
    • 例如:final void someMethod() { // do something } 定义了一个不能被子类重写的方法。
  3. 对类使用 final
    • 当应用于类时,final 表示该类不能被继承,即它是最终的,不能有子类。
    • 例如:final class MyClass { // class definition } 声明了一个不能被继承的类。
(2)注意事项
  1. final修饰的属性又叫做常量,一般用用XX_XX来命名(大写加下划线)

  2. final修饰的属性必须赋初值,并且以后不能被修改,赋值可以有以下三个地方可以进行:

    1. 定义,例如: public final double TAX_RATE = 0.5;
    2. 构造器中
    3. 代码块中
  3. 如果final修饰的属性是静态的,初始化的位置只能是:

    1. 定义中
    2. 静态代码块中
  4. 类不是final类,但是含有final方法,方法不能被重写,但是可以被继承

    举例:

    public class FinalDetail01 {public static void main(String[] args) {BB bb = new BB();bb.cal();}
    }
    class AA{final public void cal(){System.out.println("CAL方法");}
    }
    class BB extends AA{}
    
  5. 一般来说,一个类已经是final类了,没有必要再将方法修饰成final方法。(因为已经无法被继承了)

  6. final不能修饰构造方法(即构造方法)

  7. finalstaic往往搭配使用,效率更高,不会导致类加载,底层编译器做了优化处理

    举例:

    class Demo{public final static int n1 = 16;static {System.out.println("这里是类加载,不会被执行");}
    }
    
  8. 包装类(Integer,Double,Float,Boolean等都是final)String也是final类

6、抽象类

(1)介绍

当父类的一些方法不能确定时,可以用abstract关键字来修饰该方法,这个方法就是抽象方法,用abstract来修饰该类就是抽象类。抽象类通常用于当我们希望有一个通用的类定义,但其中的某些方法在基类中并不具备实际的实现,而是应该由具体的子类来实现。在框架和设计模式比较多

举例:

//抽象类不能被实例化,有抽象方法,这个类必须声明为abstract
abstract class AA{//抽象方法没有方法体public abstract void eat();
}
(2)注意事项
  1. 抽象类不能被实例化

  2. 抽象类可以没有抽象方法,但是有抽象方法的类一定是抽象类。

    举例:

    abstract class BB{public void cal(){System.out.println("抽象类可以没有抽象方法");}
    }
    
  3. 抽象类只能修饰类和方法,不能修饰属性和其他的类型。

  4. 抽象类可以有任意成员 (抽象类本质还是类),比如:非抽象方法、构造器、静态属性等。

    举例:

    abstract class BB{//属性private String name;//构造器public BB() {}//普通方法public void cal(){System.out.println("抽象类可以没有抽象方法");}//抽象方法,没有方法体abstract void hi();
    }
    
  5. 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract

    举例:

    abstract  class E{public abstract void hi();public abstract void sorry();
    }
    //子类必须实现父类的所有抽象方法
    class F extends E{public void hi(){System.out.println("hi");}public void sorry() {System.out.println("sorry");}
    }
    
  6. 抽象方法不能用private、final和static来修饰,因为这些关键字是与重写相违背的。

(3)抽象类实践-模版设计模式

抽象类体现的是一种模版模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展,改造,但子类总体会保留抽象类的行为模式。

可以解决的问题有:

  1. 当功能内部一部分是确定的,一部分是不确定的,这时可以把不确定的部分暴露出去,让子类去实现
  2. 编写一个抽象父类,父类提供多个子类的通用方法,并把一个活多个方法留给子类实现,这个就是模版设计模式。

举例:

abstract class Template{public abstract void job();//一部分抽象,一部分不抽象,可以转变为一个模板,提供给子类实现public void calculate(){long time = System.currentTimeMillis();job();long nowtime = System.currentTimeMillis();System.out.println("该任务执行时间为:"+(nowtime-time));}
}class Cat extends Template{//子类只需要负责实现抽象部分即可public void job(){long sum = 0;for (int i = 0; i < 8000000; i++) {sum += i*2;}}
}class Tiger extends Template{//子类只需要负责实现抽象部分即可public void job(){long sum = 0;for (int i = 0; i < 8000000; i++) {sum += i;}}
}

7、接口

(1) 基本介绍

接口就是给出一些没有实现的方法,封装到一起,到某个类需要使用的时候,在根据具体情况把这些方法写出来

语法:

interface 接口名{//属性//方法
}class 类名 implements 接口{//自己属性//自己方法//必须实现的接口的抽象方法
}
//Jdk7.0之前,接口里面的所有方法都没有方法体
//Jdk8.0之后,接口中可以有方法的具体实现(默认方法、或者静态方法)

接口是更加抽象的抽象的类,Jdk8.0之后,接口类里面可以用静态方法,默认方法,可以有具体方法的实现。

举例:

interface AInterface{public int n1 = 10;//抽象方法public void hi();//使用关键字default修饰之后,可以实现具体的方法default void ok(){System.out.println("这里可以声明方法");}//使用static修饰之后,也可以实现具体的方法static void you(){System.out.println("这里可以声明方法");}
}//需要实现接口类的所有抽象方法
class A implements AInterface{@Overridepublic void hi() {System.out.println("实现接口类的抽象方法");}
}
(2)注意事项
  1. 接口不能被实例化

  2. 接口中所有的方法都是public方法,接口中的抽象方法,可以不用abstract修饰

    void aaa();
    实际上等同于 public abstract void aaa();
    
  3. 一个普通类实现接口,就必须将该接口的所有方法都实现。而抽象类实现接口,就可以不用实现接口的方法。

    interface AInterface{//抽象方法public abstract void hi();
    }//抽象类可以不用实现抽象方法
    abstract class B implements AInterface{
    }
    
  4. 一个类可以实现多个接口

    interface  AI{}
    interface BI{}
    class BC implements AI, BI{}
    
  5. 接口中的属性,只能是final,而且是public static final修饰符,比如:int a = 1;实际上是 public static final int a = 1(必须初始化),属性访问形式:接口名.属性名

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

    interface  AI{}
    interface BI{}
    interface BD extends AI,BI{}
    
  7. 接口的修饰符,只能是public或者是默认的, 这里和普通的类一样

(3)接口对比继承

接口是对行为的抽象,而继承是对类的抽象。 当子类继承了父类,就自动拥有父类的功能。如果子类需要扩展功能,可以通过实现接口的方式扩展。可以理解为接口是对单继承机制的一种补充。

  1. 继承的价值:解决代码的复用性和可维护性(is - a关系)
  2. 接口的价值:设计好各种规范(方法),让这些类去实现这些诶方法,更加的灵活。(like -a 关系)
  3. 接口在一定程度上可以实现代码的解耦(接口规范性+动态绑定)
(4) 接口多态
  1. 接口的多态

  2. 多态数组

    以上两种举例:

    public class InterfacePolyParameter {public static void main(String[] args) {//接口的多态,//接口类型的变量 if01可以指向实现了IF接口的类的对象实例IF if01 = new Monster();if01 = new Car();//多态数组IF[] if02 = new IF[2];if02[0] = new Monster();if02[1] = new Car();}
    }interface IF{}
    class Monster implements IF {}
    class Car implements  IF{}
    
  3. 接口多态传递

public class InterfacePoly {public static void main(String[] args) {//接口类型变量可以指向,实现该接口的类的对象实例IG ig = new Teacher();//IG继承了IH接口,Teacher实现了IG接口,相当于Teacher实现了IH接口,这就是接口的多态传递现象IH ih = new Teacher();}
}
interface IH{}
interface IG extends IH{}
class Teacher implements IG{}

8、内部类【难点和重点】

(1)基本介绍

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

举例:

//类的五大成员
class Outer{//外部类//属性private int n1 = 100;//构造器public Outer(int n1) {this.n1 = n1;}//方法public void m1(){System.out.println("方法");}//代码块{System.out.println("代码块...");}//内部类class Inner{//内部类,在Outer类的内部}
}

内部类的种类:

  1. 在局部位置(方法/代码块):
    1. 局部内部类(有类名)
    2. 匿名内部类(没有类名,重点)
  2. 成员位置:
    1. 成员内部类(没有static修饰)
    2. 静态内部类(有static修饰)

基本语法:

class Outer{//外部类class Inner{//内部类}
}
(2)局部内部类

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

  1. 可以直接访问外部类的所有成员,包含私有成员
  2. 不能添加访问修饰符,因为这是一个局部变量,可以使用final,局部变量可以使用final
  3. 作用域:仅仅在定义它的方法或者代码块中
  4. 局部内部类—访问---->外部类的成员[访问方式:直接访问]
  5. 外部类—访问—>局部内部类的成员[访问方式:创建对象后,再访问(必须在作用域内)]
  6. 外部其他类—不能访问---->局部内部类
  7. 如果外部类与局部内部类的成员重名时,遵循就近访问原则,如果想访问外部类的成员可以使用[外部类名.this.成员]去访问

举例:

class Outer02{//外部类private int n1 = 10;private void m2(){}//私有方法public void m1(){//方法//1、局部内部类是定义在外部类的局部位置,通常实在方法里面//3、不能添加访问修饰符,但是可以使用final修饰(不能被继承)//4、作用域:仅仅在方法或代码块中class Inner02{  //局部内部类(本质仍为一个类)private int n1 = 800;public void f1(){//2、可以直接访问外部类的所有成员,包含私有的//5、局部内部类可以直接访问外部类的成员,比如n1,m2()//7、如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,可以使用 外部类名.this.成员去访问//Outer02.this 的本质就是外部类的对象,哪个对象调用了m1,Outer02.this就是哪个对象System.out.println("内部类n1= "+n1);System.out.println("外部类的n1 ="+Outer02.this.n1);m2();}}//6、外部类在方法中,可以创建Inner02对象,然后调用方法即可Inner02 inner02 = new Inner02();inner02.f1();}
}

注意事项:

  • 局部内部类定义在方法中/代码块中
  • 作用域在方法体或者代码块中
  • 本质仍然是一个类
(3)匿名内部类(重要)

匿名内部类是一个没有类名的内部类。如果一个内部类的对象在一个地方只需要用一次,那么我们可以使用匿名内部类,它可以简化代码,使得代码更易于阅读。匿名内部类在编译的时候由系统自动用其父类名加$1、$2这样的方式来命名。

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

基本语法:

new 类或接口(参数列表){类体
};
//参数列表会传给类的构造器

举例:

class Outer04{//外部类private int n1 = 10;//属性public void method(){//方法//基于接口的匿名内部类//1、需要A接口,并创建对象//2、传统方法,是写一个类,实现接口,并创建对象//3、只需要使用一次,后面不需要再使用//4、使用匿名内部类简化开发//5、匿名内部类tiger的运行类型为 Outer04$1,编译类型是A//6、匿名内部类的底层实现:/*class Outer04$ implement A{public void cry() {System.out.println("老虎在叫");}}*///7、jdk在底层创建匿名内部类Outer04$1,立马就创建了Outer04$01实例,并且把地址返回//8、匿名内部类使用一次就不再使用A tiger = new Tiger(){public void cry() {System.out.println("老虎在叫");}};tiger.cry();
//        A tiger = new Tiger();
//        tiger.cry();}
}interface A{//接口public void cry();
}class Tiger implements A{@Overridepublic void cry() {System.out.println("老虎在叫");}
}

注意事项:(与局部内部类类似)

  1. 语法比较不一样,既有定义类的特征,也有创建对象的特征。
  2. 可以直接访问外部类的所有成员,包含私有成员
  3. 不能添加访问修饰符,因为这是一个局部变量,可以使用final,局部变量可以使用final
  4. 作用域:仅仅在定义它的方法或者代码块中
  5. 外部其他类—不能访问---->局部内部类
  6. 如果外部类与局部内部类的成员重名时,遵循就近访问原则,如果想访问外部类的成员可以使用[外部类名.this.成员]去访问

实践:

public class AnonymousClassPractice {public static void main(String[] args) {//1、将匿名内部类直接当做实参传入函数当中f1(new Fot() {//软编码模式@Overridepublic void show() {System.out.println("匿名内部类重写show方法");}});//正常实现,比较麻烦Example example = new Example();f1(example);}public static void f1(Fot fot){fot.show();}
}interface Fot{void show();
}//硬编码模式
class Example implements Fot{@Overridepublic void show() {System.out.println("普通类重写show方法");}
}
(4)成员内部类

成员内部类是创建在外部类的成员位置,没有static修饰

注意事项

  1. 可以直接访问外部类的所有成员,包含私有成员
  2. 可以添加任意的修饰符(public、protected、private、默认),可以认为这个类就是一个成员
  3. 作用域是和其他类的成员一样,是整个类体
  4. 成员内部类-----访问----->外部类成员(比如:属性)【访问方式:直接访问】
  5. 外部类------访问------>成员内部类【访问方式:创建对象,再访问】
  6. 外部其他类-----访问----->成员内部类【两种方式:外部类名.new 内部类名,或者外部类名创建一个方法返回内部类】
  7. 如果外部类和内部类的成员重名时,内部类访问遵循就近原则,如果想访问外部类的成员,可以使用(外部类名.this.成员)去访问

举例:

public class MemberInnerClass {public static void main(String[] args) {Outer08 outer08 = new Outer08();outer08.t1();//外部其他类,访问成员内部类的两种种方式;//第一种方式:把内部类当做外部类的一个成员来使用Outer08.Inner08 inner08 = outer08.new Inner08();inner08.say();//第二种方式,在Outer里面创建一个方法,这个方法返回一个内部类地址Outer08.Inner08 inner081 = outer08.getInner08Instance();inner081.say();}
}class Outer08{private int n1 = 10;public String name = "张三";//1、内部类是定义在外部类的成员位置//2、可以用public、private、protected修饰//3、作用域在整个类体class Inner08{//成员内部类public void say(){//4、可以访问外部类的所有成员,包含私有的System.out.println("n1 = "+n1 + " name = "+name);}}public void t1(){//5、外部类使用内部类,创建对象,使用他的成员即可Inner08 inner08 = new Inner08();inner08.say();}public Inner08 getInner08Instance(){return new Inner08();}
}
(5)静态内部类

静态内部类是定义在外部类的成员位置,并且有static修饰,与成员内部类基本没有区别

注意事项:

  1. 可以直接访问外部类的所有成员,包含私有成员
  2. 可以添加任意的修饰符(public、protected、private、默认),可以认为这个类就是一个成员
  3. 作用域是和其他类的成员一样,是整个类体
  4. 成员内部类-----访问----->外部类成员(比如:属性)【访问方式:直接访问】
  5. 外部类------访问------>成员内部类【访问方式:创建对象,再访问】
  6. 外部其他类-----访问----->成员内部类【两种方式:外部类名.new 内部类名,或者外部类名创建一个方法返回内部类】
  7. 如果外部类和内部类的成员重名时,内部类访问遵循就近原则,如果想访问外部类的成员,可以使用(外部类名.成员)去访问 【不需要加this】

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

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

相关文章

JavaSE语法之十五:异常(超全!!!)

文章目录 一、异常的概念与体系1. 异常的概念2. 异常的体系结构3. 异常的分类 二、异常的处理方式1. 防御式编程&#xff08;1&#xff09;LBYL 事前防御型&#xff08;2&#xff09;EAFP 时候认错型 2. 异常的抛出3. 异常的捕获&#xff08;1&#xff09;异常声明的 throws&am…

工作流入门这篇就够了!

总概 定义&#xff1a;工作流是在计算机支持下业务流程的自动或半自动化&#xff0c;其通过对流程进行描述以及按一定规则执行以完成相应工作。 应用&#xff1a;随着计算机技术的发展以及工业生产、办公自动化等领域的需求不断提升&#xff0c;面向事务审批、材料提交、业务…

OpenCV中实现图像旋转的方法

OpenCV中实现图像旋转的方法 函数&#xff1a;cv2.flip() 功能&#xff1a;水平或者垂直翻转 格式&#xff1a;dst cv2.flip(src,flipCode[,dst]) 参数说明&#xff1a; src&#xff1a;输入图像 dst&#xff1a;和原图像具有相同大小、类型的目标图像。 flipCode&#…

【Hotspot源码】揭秘Java线程创建过程中的各种细节

近期准备给大家分享专题系列文章&#xff0c;聚焦Java多线程机制。会从hotspot源码角度&#xff0c;给大家揭秘平时学习多线程那些从来没有想过的问题&#xff0c;或者存在疑虑却又无法证明的理论。 今天是系列文章首篇&#xff0c;咱们来谈谈Java线程创建的一些细节问题&#…

Vue 中的 ref 与 reactive:让你的应用更具响应性(中)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

Lumerical Script------for语句

Lumerical------for语句 正文正文 关于 Lumerical 中 for 语句的用法这里不做过多说明了,仅仅做一个记录,具体用法如下: 通常我们用的比较多的形式是第一种步长值为 1 的情况。对于其他步长值的情况,我们可以使用第二种用法。对于 while 的类似使用方法可以使用第三种。 …

用Audio2Face驱动UE - MetaHuman

新的一年咯&#xff0c;很久没发博客了&#xff0c;就发两篇最近的研究吧。 开始之前说句话&#xff0c;别轻易保存任何内容&#xff0c;尤其是程序员不要轻易Ctrl S 在UE中配置Audio2Face 先检查自身电脑配置看是否满足&#xff0c;按最小配置再带个UE可能会随时崩&#x…

宏晶微 MS9125 USB 投屏控制芯片 VGAHDM输出 全新原装

1.基本介绍 MS9125 是一款 USB 单芯片投屏器,内部集成了 USB2.0 控制器和数据收发模块、视频 DAC、HDMI 接口和音视频处理模块&#xff0c;MS9125 可以通过 USB 接口显示或者扩展 PC、智能手机、平板电脑的显示信息到更大尺寸的显示设备上&#xff0c;支持 VGA 和 HDMI 视频接…

hcie datacom笔试考多少道题目?

华为认证的HCIE Datacom(数据通信)是网络工程师们向往的顶级认证之一。对于即将参加HCIE Datacom笔试的考生们&#xff0c;你们一定想知道笔试会考多少道题目。下面将为大家揭秘HCIE Datacom笔试的题目数量&#xff0c;并分享一些优秀的培训机构&#xff0c;帮助大家顺利通过考…

diffusers 源码待理解之处

一、训练DreamBooth时&#xff0c;相关代码的细节小计 ** class_labels timesteps 时&#xff0c;模型的前向传播怎么走&#xff1f;待深入去看 ** 利用class_prompt去生成数据&#xff0c;而不是instance_prompt class DreamBoothDataset(Dataset):"""A dat…

循环与基础函数

循环与函数 1.循环的三种方式2.循环的中断与空语句3.函数的定义与使用4.参数的作用域5.指针6.总结 1.循环的三种方式 我们最熟悉的循环为for和while&#xff0c;这两种循环方式在Python系列介绍过。在C中&#xff0c;循环的基本逻辑同Python是类似的。c中while循环的语法如下&…

力扣每日一题99:恢复二叉搜索树

题目 给你二叉搜索树的根节点 root &#xff0c;该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下&#xff0c;恢复这棵树 。 示例 1&#xff1a; 输入&#xff1a;root [1,3,null,null,2] 输出&#xff1a;[3,1,null,null,2] 解释&#xff1a;3 不能是 1 …

【linux】ufw 的基本使用

碎碎念 所有的云平台的网络流量的进出基本上有三层&#xff0c;首先是虚拟网的流量控制&#xff0c;一般是通过子网访问控制列表来控制vpc也好子网也好的流量出入&#xff0c;其次是安全组控制一层&#xff0c;通过安全组规则控制一类/一组主机&#xff08;指EC2/ECS/VM/CE这些…

c语言结构体学习

文章目录 前言一、结构体的声明1&#xff0c;什么叫结构体?2&#xff0c;结构体的类型3,结构体变量的创建和初始化4&#xff0c;结构体的类型5&#xff0c;结构体的初始化 二、结构体的访问1&#xff0c;结构体成员的点操作符访问2&#xff0c;结构体体成员的指针访问 三、结构…

rime中州韵小狼毫 inputShow lua Filter 输入字符透传滤镜

在 rime中州韵小狼毫 inputShow lua Translator 一文中&#xff0c;我们通过 inputShow.lua 定制了 inputShow_translator&#xff0c;这使得我们的输入方案可以将用户输入的字符透传到候选列表中来。如下&#x1f447;&#xff1a; &#x1f446;上图中我们在候选列表中看到了…

基于ssm+vue服装商城购物系统

摘要 在基于SSM框架和Vue.js的服装商城购物系统中&#xff0c;整合了多种先进的技术&#xff0c;为电子商务领域的发展提供了有力支持。该系统不仅仅是技术层面的整合&#xff0c;更是对于业务流程和用户体验的深入考虑。以下是对该系统扩展的一些关键方面的讨论&#xff0c;以…

synchronized锁

synchronized 类锁&#xff1a;给类的静态方法加上synchronized 关键字进行修饰&#xff0c; 锁的是当前类class&#xff0c;一个静态同步方法拿到锁&#xff0c;其他静态同步方法就会等待静态同步方法和普通同步方法间是没有竞争的 对象锁&#xff1a;给类的方法加上synchron…

elasticsearch如何操作索引库里面的文档

上节介绍了索引库的CRUD&#xff0c;接下来操作索引库里面的文档 目录 一、添加文档 二、查询文档 三、删除文档 四、修改文档 一、添加文档 新增文档的DSL语法如下 POST /索引库名/_doc/文档id(不加id,es会自动生成) { "字段1":"值1", "字段2&q…

基于头脑风暴算法优化的Elman神经网络数据预测 - 附代码

基于头脑风暴算法优化的Elman神经网络数据预测 - 附代码 文章目录 基于头脑风暴算法优化的Elman神经网络数据预测 - 附代码1.Elman 神经网络结构2.Elman 神经用络学习过程3.电力负荷预测概述3.1 模型建立 4.基于头脑风暴优化的Elman网络5.测试结果6.参考文献7.Matlab代码 摘要&…

Vue3 的 emit 该怎么写, vue2 对比

Vue3 的 emit 该怎么写&#xff0c; vue2 对比 这是个新手问题&#xff0c;从 vue2 转到 vue3 之后&#xff0c;一时间不知道该怎么用它了。 vue2 用法 vue2 在 template 中 和 在方法中的用法如下&#xff1a; <template><button click"$emit(clicked, 要传…