기초 없이 30일 만에 자바를 배운 한순핑 [제8장 객체지향 프로그래밍(고급)]

클래스 변수

P373~P423

클래스 변수는 정적 변수라고도 합니다.

정적 변수는 동일한 클래스의 모든 개체에서 공유됩니다.

정적 변수는 클래스가 로드될 때 생성됩니다.

클래스 변수를 정의하는 방법

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

클래스 변수에 접근하는 방법

  • 클래스명.클래스변수명
  • 개체 이름.클래스 변수 이름

정적 변수에 대한 액세스 수정자의 액세스 권한 및 범위는 일반 속성과 동일합니다.

클래스 변수 사용 내역

특정 클래스의 모든 개체가 변수를 공유하도록 해야 하는 경우 클래스 변수 사용을 고려할 수 있습니다.

클래스 방법

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

클래스 메서드 호출

  • 클래스명 클래스 메소드명
  • 객체명.클래스 메소드명

클래스 메서드 사용 사례

메서드가 개체 관련 멤버를 포함하지 않는 경우 메서드를 정적 메서드로 설계하여 개발 효율성을 높일 수 있습니다.

인스턴스를 생성하지 않으려면 메서드를 호출할 수도 있는데 이때 메서드를 정적 메서드로 만드는 것이 매우 적절합니다.

예: 도구 클래스의 메서드

Math 클래스, Arrays 클래스, Collections 컬렉션 클래스

수업 방법 고려 사항

  • 클래스 메소드와 일반 메소드 모두 클래스 로딩과 함께 로드되며 구조 정보는 메소드 영역에 저장됩니다.클래스 메소드에는 this 매개 변수가 없으며 일반 메소드에는 this 매개 변수가 내포되어 있습니다.
  • 클래스 메서드는 클래스 이름 또는 개체 이름으로 호출할 수 있습니다.
  • 일반 메서드는 개체와 관련이 있으며 개체 이름으로 호출해야 합니다.
  • this 및 super와 같은 개체 관련 키워드는 클래스 메서드에서 허용되지 않습니다.
  • 클래스 메서드에서는 정적 변수 또는 정적 메서드만 액세스할 수 있습니다.
  • 일반 멤버 메서드는 비정적 멤버와 정적 멤버 모두에 액세스할 수 있습니다.

주요 방법

public static void main(String[] args){}

  1. public: Java 가상 머신은 클래스의 main() 메서드를 호출해야 하므로 이 메서드의 액세스 권한은 public이어야 합니다.
  2. 정적: Java 가상 머신은 main() 메서드를 실행할 때 객체를 생성할 필요가 없으므로 메서드는 정적이어야 합니다.
  3. 이 메소드는 java 명령을 실행할 때 실행 중인 클래스에 전달된 매개변수를 저장하는 Sting 유형의 배열 매개변수를 허용합니다.

알아채다

메인 메소드에서 정적 메소드 또는 메인 메소드가 위치한 클래스의 정적 속성을 직접 호출할 수 있습니다.

그러나 클래스의 비정적 멤버에 직접 접근할 수는 없으며, 이 객체를 통해 클래스의 비정적 멤버에 접근하기 전에 클래스의 강도 개체를 생성해야 합니다.

코드 블록

코드 블록은 초기화 블록이라고도 하며 클래스의 구성원에 속하며 메서드와 유사하며 메서드 본문에 논리 문을 캡슐화하고 {}로 둘러쌉니다.

다만 메소드와 달리 메소드 이름도 없고, 리턴도 없고, 매개변수도 없고, 메소드 본체만 있고, 객체나 클래스를 통해 명시적으로 호출할 필요가 없고, 클래스가 로드될 때나 객체가 로드될 때 암묵적으로 호출된다. 생성된다

기본 문법

[修饰符]{
  代码
};

알아채다

  1. 수정자는 선택 사항이지만 작성 시 정적일 수만 있습니다.
  2. 코드 블록은 정적 코드 블록이라고 하는 정적 수정과 일반 코드 블록이라고 하는 정적 수정이 없는 두 가지 범주로 나뉩니다.
  3. 논리문은 모든 논리문(입력, 출력, 메서드 호출, 루프, 판단)이 될 수 있습니다.
  4. 세미콜론은 쓰거나 생략할 수 있습니다.

이해하다

  1. 초기화 작업을 수행할 수 있는 다른 형태의 생성자(생성자에 대한 보완 메커니즘)와 동일합니다.
  2. 여러 생성자에서 반복되는 문이 있는 경우 코드 재사용성을 향상시키기 위해 초기화 블록으로 추출할 수 있습니다.
  3. 객체를 생성하기 위해 어떤 생성자가 호출되더라도 코드 블록의 내용이 먼저 호출됩니다.
  4. 코드 블록 호출 순서가 생성자보다 우선합니다.

코드 블록 사용 세부 정보, com.codeBlock.CodeBlockDetail.java

  1. 정적 코드 블록은 정적 코드 블록이라고도 하며 클래스를 초기화하고 클래스가 로드되는 대로 실행하는 데 사용되며 한 번만 실행됩니다. 일반 코드 블록이라면 객체를 생성하여 한번 실행합니다.
  2. 클래스가 로드될 때
    1. 개체 인스턴스가 생성될 때(신규)
    2. 하위 클래스 개체 인스턴스를 생성하면 상위 클래스도 로드되고 상위 클래스가 먼저 로드되고 하위 클래스는 나중에 로드됩니다.
    3. 클래스의 정적 멤버를 사용하는 경우(정적 속성, 정적 메서드)
  3. 일반 코드 블록은 객체 인스턴스가 생성될 때 암시적으로 호출됩니다. 일단 생성되면 한 번 호출되며 이는 생성자의 보완과 같습니다. 클래스의 정적 멤버만 사용하면 일반 코드 블록이 실행되지 않습니다.
  4. 개체를 만들 때 클래스의 호출 순서는 다음과 같습니다.
    1. 정적 코드 블록 및 정적 속성 초기화 호출(참고: 정적 코드 블록 및 정적 속성 초기화 호출은 우선 순위가 동일하며 정적 코드 블록 및 정적 변수 초기화가 여러 개인 경우 정의된 순서대로 호출됨)
    2. 일반 코드 블록 및 일반 속성 초기화 호출(참고: 일반 코드 블록 및 일반 속성 초기화 호출의 우선 순위는 동일하며 일반 코드 블록 및 일반 속성 초기화가 여러 개 있는 경우 정의된 순서대로 호출됩니다. )
    3. 호출 생성자
  5. 생성자의 앞부분은 실제로 super()를 의미하며 일반 코드 블록을 호출합니다. 정적 코드 블록 및 속성 초기화는 클래스가 로드될 때 실행되므로 생성자 및 일반 코드 블록보다 먼저 실행됩니다. CodeBlockDetail03.java
  6. 서브클래스 생성 시 정적 코드 블록, 정적 속성 초기화, 공통 코드 블록, 일반 속성 초기화, 생성자의 호출 순서는 다음과 같습니다.
    1. 부모 클래스의 정적 코드 블록, 정적 속성 초기화
    2. 하위 클래스의 정적 코드 블록, 정적 속성 초기화
    3. 상위 클래스의 공통 코드 블록, 일반 속성 초기화
    4. 부모 클래스 생성자
    5. 하위 클래스에 대한 일반 코드 블록, 일반 초기화
    6. 서브클래스 생성자
  7. 정적 코드 블록은 정적 멤버만 직접 호출할 수 있으며 일반 코드 블록은 모든 멤버를 호출할 수 있습니다.
package com.codeBlock;

public class CodeBlockDetail {
    public static void main(String[] args) {
        //1. static代码块也叫静态代码块,作用是对类进行初始化,且随着类的加载而执行,并且只会执行一次。
        //如果是普通代码块,每创建一个对象,就执行。
        //2. 类什么时候被加载
            //1. 创建对象实例时(new)
            //2. 创建子类对象实例,父类也会被加载
//        AA aa = new AA();   // bb的静态代码块被执行
                             // aa的静态代码块被执行
                             // bb的普通代码块
            //3. 使用类的静态成员时(静态属性,静态方法)
//        System.out.println(Cat.name);   //cat的静态代码块被执行
                                            //mao
        //3. 普通的代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会调用一次。
        //如果只是使用类的静态成员,普通代码块并不会执行。
//        BB.show();    //bb的静态代码块被执行
                        //调用静态属性,普通代码块不调用
//        BB bb1 = new BB();  //bb的静态代码块被执行
                            //bb的普通代码块
    }
}

class BB {
    static {
        System.out.println("bb的静态代码块被执行");
    }
    {
        System.out.println("bb的普通代码块");
    }

    public static void show() {
        System.out.println("调用静态属性,普通代码块不调用");
    }
}

class AA extends BB {
    static {
        System.out.println("aa的静态代码块被执行");
    }
}
class Cat{
    public static String name="mao";
    static {
        System.out.println("cat的静态代码块被执行");
    }
}

디자인 패턴

디자인 패턴이란

  1. 정적 메서드 및 속성의 고전적인 사용
  2. 디자인 패턴은 수많은 실습에서 요약하고 이론화한 후 선호하는 코드 구조, 프로그래밍 스타일 및 문제 해결 사고 방식입니다.

싱글톤 패턴

  1. 클래스의 소위 싱글톤 설계 패턴은 전체 소프트웨어 시스템에서 특정 클래스에 대해 하나의 개체 인스턴스만 있을 수 있도록 특정 방법을 채택하는 것입니다. 이 클래스는 개체 인스턴스를 얻는 방법만 제공합니다.
  2. 싱글톤 모드에는 배고픈 사람 스타일과 게으른 사람 스타일의 두 가지 방법이 있습니다.

싱글톤 패턴 적용 예제

[배고픈 중국 스타일], com.single_.SingleTon01.java

클래스가 로드되어 있는 한 이 객체가 생성되는데, 클래스 변수만 사용할 수도 있고, 사용하지 않더라도 이 객체가 함께 생성되어 리소스를 낭비하게 됩니다.

단계:

  1. 생성자 사유화: 직접 신규 방지

  2. 클래스 내부에서 생성된 객체

  3. 정적 공용 메서드를 노출합니다. getInstance

    (정적인 이유는? 인스턴스를 생성하지 않고 클래스 메서드를 직접 호출하려는 경우 정적이며 메서드의 속성도 정적이기 때문입니다.)

    (getInstance가 여러 번 호출되고 다른 변수 이름으로 수신되는 경우 정적 속성은 한 번만 초기화되기 때문에 실제로는 동일한 객체를 가리킵니다.)

  4. 암호

public class SingleTon01 {
    public static void main(String[] args) {
//        GirlFriend xiaohong = new GirlFriend("xiaohong");
//        GirlFriend xiaobai = new GirlFriend("xiaobai");
        GirlFriend instance = GirlFriend.getInstance();
        System.out.println(instance);
    }
}

class GirlFriend {
    private String name;
    //如何保证只能有一个girlfriend
    //步骤:
    //1、构造器私有化
    //2、类的内部创建
    private static GirlFriend gf = new GirlFriend("xiaohong");
    private GirlFriend(String name) {
        this.name = name;
    }
    //3、提供一个公共静态方法
    public static GirlFriend getInstance() {
        return gf;
    }
    @Override
    public String toString() {
        return "GirlFriend{" + "name='" + name + '\'' + '}';
    }
}

[게으른 스타일], com.single_.SingleTon02.java

사용자가 getInstance 메서드를 호출해야만 객체가 생성되며, 이 메서드를 호출했다면 다시 호출하면 마지막으로 생성한 객체를 반환한다.

public class SingleTon02 {
    public static void main(String[] args) {
        System.out.println(Cat.getInstance());
    }
}
//希望程序运行过程中只能创建一个Cat
class Cat{
    private String name;
    private static Cat cat;
    //1、构造器私有化
    //2、定义一个static属性对象
    private Cat(String name) {
        this.name = name;
    }
    //3、提供公共static方法,返回cat对象
    
    public static Cat getInstance(){
        if(cat==null){
            cat= new Cat("xiaomao");
        }
        return cat;
    }

배고픈 남자 스타일과 게으른 남자 스타일의 차이점

  1. 이 둘의 주요 차이점은 객체 생성 시점에 있는데, hungry 스타일은 클래스가 로드될 때 객체 인스턴스를 생성하고 lazy 스타일은 사용할 때 객체 인스턴스를 생성합니다.
  2. Hungry 스타일에는 스레드 안전성 문제가 없지만 Lazy 스타일에는 스레드 안전성 문제가 있습니다(스레드 학습 참조).
  3. Hungry Style은 자원을 낭비할 가능성이 있는데, 프로그래머가 객체 인스턴스를 사용하지 않으면 Hungry Style로 생성된 객체가 낭비되고 Lazy Style은 사용할 때 생성되기 때문에 그런 것은 없다. 문제
  4. javaSE 표준 클래스에서 java.lang.Runtime은 고전적인 싱글톤 패턴입니다.
public class Runtime {
    private static Runtime currentRuntime = new Runtime();
    public static Runtime getRuntime() {
        return currentRuntime;
    }
    /** Don't let anyone else instantiate this class */
    private Runtime() {}
    }

최종 키워드

final은 클래스, 속성, 메서드 및 지역 변수를 수정할 수 있습니다.

사용법: com.final_.Final01.java

  1. 클래스 상속을 원하지 않는 경우 최종 수정을 사용할 수 있습니다.
  2. 상위 클래스의 메서드를 하위 클래스 [접근 한정자 최종 반환형 메서드 이름]으로 덮어쓰거나 덮어쓰지 않으려는 경우
  3. 클래스의 속성 값을 수정하고 싶지 않을 때 [public final double TAX_RATE=0.08]
  4. 지역변수 수정을 원하지 않을 때 [최종 이중 TAX_RATE=0.08]
package com.final_;
public class Final01 {
    public static void main(String[] args) {
        A a = new A();
        a.TAX_RATE=0.09;
    }
}
//如果要求A不能被其他类继承,使用final修饰A
//final class A{
class A{
    //    不希望类的某个属性的值被修改
//    public final double TAX_RATE=0.08;
    public double TAX_RATE=0.08;


    //    不希望方法被子类覆盖
//    public final void hi(){}
    public void hi(){
        //    不希望某个局部变量被修改
//        final int money=100;
        int money=100;
        money =101;
    }
}

class B extends A{
    @Override
    public void hi() {
        super.hi();
    }
}

최종 세부 사항

  1. 최종 수정된 속성은 XX_XX_XX로 명명된 상수라고도 합니다.
  2. 최종 수정된 속성은 정의될 때 초기 값을 할당해야 하며 더 이상 수정할 수 없습니다. 초기 값은 다음 위치에 할당할 수 있습니다.
    1. 정의할 때
    2. 생성자에서
    3. 코드 블록에서
class AA{
  public final double TAX_RATE=0.08;//定义时
  public final double TAX_RATE2;
  public final double TAX_RATE3;
  public AA(){//构造器中赋值
    TAX_RATE2=1.1;
  }
  {//代码块赋值
    TAX_RATE3=8.8;
  }
}
  1. 최종 수정 속성이 정적인 경우 초기화 위치는
    1. 정의할 때
    2. 정적 블록
class BB{
  public static final double TAX_RATE=0.08;//定义时
  public static final double TAX_RATE2;
  static {//代码块赋值
    TAX_RATE3=8.8;
  }
}
  1. 최종 클래스는 상속할 수 없지만 개체는 인스턴스화할 수 있습니다.
  2. 클래스가 최종 클래스가 아니지만 최종 메서드를 포함하는 경우 메서드를 재정의할 수 없지만 상속할 수 있습니다.
  3. 일반적으로 말해서, 클래스가 final이면 메서드를 final로 작성할 필요가 없습니다.
  4. final은 생성자를 수정할 수 없습니다.
  5. Final과 static은 종종 함께 사용되므로 더 효율적이고 클래스 로딩이 발생하지 않습니다.기본 컴파일러는 com.final_.FinalStatic.java를 최적화했습니다.
package com.final_;
public class FinalStatic {
    public static void main(String[] args) {

        System.out.println(AA.name);
    }
}

class AA {
    public static final String name = "aaa";
    static {
        System.out.println("静态代码块");
    }
}

  1. 래퍼 클래스(Integer, Double, Float, Boolean은 모두 최종 클래스), String도 최종 클래스입니다.

추상 클래스

com.abstract_.Abstract01.java

부모 클래스의 일부 메서드를 선언해야 하지만 구현 방법을 잘 모르는 경우 추상 메서드로 선언하면 이 클래스가 추상 클래스입니다.

package com.abstract_;

public class Abstract01 {
    public static void main(String[] args) {

    }
}

abstract class Animal {
    private String name;
    public Animal(String name) {
        this.name = name;
    }

    //eat实现了,但没什么意义
    //出现了父类方法不确定性的问题
    //考虑将该方法设计为抽象方法
    //所谓抽象方法就是没有实现的方法
    //所谓没有实现就是没有方法体{}
    //当一个类中存在抽象方法时,需要将该类声明为abstract类
    //一般来说,抽象类会被继承,由其子类来实现抽象方法
    public abstract void eat();
}

소개하다

  1. 추상 키워드로 클래스를 수정하면 해당 클래스를 추상 클래스라고 합니다.

    访问修饰符 abstract 类名{}

  2. 메서드를 수정하기 위해 abstract 키워드를 사용하는 경우 해당 메서드는 메서드 본문이 없는 추상 메서드입니다. {}

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

  3. 추상 클래스의 가치는 디자인에 더 있습니다.디자이너가 디자인한 후 하위 클래스가 추상 클래스를 상속하고 구현하도록 합니다.

추상 클래스 세부 정보

  1. 추상 클래스는 인스턴스화할 수 없습니다.
  2. 추상 클래스에 반드시 추상 메소드가 있는 것은 아닙니다. 즉, 추상 클래스에 추상 메소드가 없을 수도 있습니다.
  3. 그러나 클래스에 추상 메서드가 포함되어 있으면 해당 클래스를 추상으로 선언해야 합니다.
  4. 추상은 속성 및 기타가 아닌 클래스 및 메소드만 수정할 수 있습니다.
  5. 추상 클래스는 여전히 클래스이기 때문에 추상 클래스는 임의의 멤버를 가질 수 있습니다.
  6. 추상 메서드는 메서드 본문 {}을 가질 수 없습니다.
  7. 클래스가 추상 클래스를 상속하는 경우 해당 클래스 자체가 추상 클래스가 아닌 경우 추상 클래스의 모든 추상 메서드를 구현해야 합니다.
  8. 추상 메서드는 private, final 및 static으로 데코레이트할 수 없습니다. 이러한 키워드는 재작성에 반대되기 때문입니다.

연습, com.abstract_.AbstractExercise01.java

세 가지 특성(이름, ID, 급여)을 포함하는 추상 클래스로 선언된 Employee 클래스를 작성하고 필요한 생성자와 추상 메서드 work()를 제공합니다. Manager 클래스의 경우 직원일 뿐만 아니라 보너스 속성도 있습니다 상속 아이디어를 사용하여 CommonEmployee 및 Manager 클래스를 설계하고 속성 액세스에 필요한 메서드를 제공하고 work(), "Manager"를 구현하도록 클래스를 요구하십시오. , Common Employee name working..."

package com.abstract_;
public class AbstractExercise01 {
    public static void main(String[] args) {
        CommonEmployee xiaoming = new CommonEmployee("小明", 101, 1000);
        Manager daming = new Manager("大明", 99, 1100, 2000);
        xiaoming.work();
        daming.work();
    }
}
abstract class Employee {
    private String name;
    private int id;
    private double salary;
    public Employee(String name, int id, double salary) {
        this.name = name;
        this.id = id;
        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 double getSalary() {return salary;}
    public void setSalary(double salary) {this.salary = salary;}
    public abstract void work();
}
class Manager extends Employee {
    private double bonus;
    public Manager(String name, int id, double salary, double bonus) {
        super(name, id, salary);
        this.bonus = bonus;
    }
    public double getBonus() {return bonus;}
    public void setBonus(double bonus) {this.bonus = bonus;}
    @Override
    public void work() {
        System.out.println("经理 " + getName() + "工作中..");
    }
}
class CommonEmployee extends Employee {
    public CommonEmployee(String name, int id, double salary) {
        super(name, id, salary);
    }
    @Override
    public void work() {
        System.out.println("普通员工" + getName() + "工作中..");
    }
}

상호 작용

인터페이스는 구현되지 않은 일부 메서드를 제공하고 함께 캡슐화하고 특정 클래스에서 사용해야 하는 특정 상황에 따라 이러한 메서드를 작성하는 것입니다.

interface 接口名{
//属性
//方法(1抽象方法2默认方法3静态方法)
}
class 类名 implements 接口名{
  自己属性;
  自己方法;
  必须实现接口的抽象方法
}

JDK7.0 이전에는 인터페이스의 모든 메서드에 메서드 본문이 없습니다.

JDK8.0 이후 인터페이스 클래스는 정적 수정이 필요한 정적 메서드를 가질 수 있으며 기본 메서드는 기본 수정이 필요합니다. 즉, 인터페이스는 메서드의 특정 구현을 가질 수 있습니다.

빠른 시작, com.interface_.Interface01.java

package com.interface_;

public class Interface01 {
    public static void main(String[] args) {
        Computer computer = new Computer();
        Camera camera = new Camera();
        Phone phone = new Phone();
        computer.work(camera);
        computer.work(phone);
    }
}
interface UsbInterface {
    public void start();
    public void stop();
}

class Computer {
    public void work(UsbInterface usbInterface) {
        usbInterface.start();
        usbInterface.stop();
    }
}

class Camera implements UsbInterface {
    @Override
    public void start() {
        System.out.println("我是相机,开始工作");
    }

    @Override
    public void stop() {
        System.out.println("我是相机,结束工作");
    }
}

class Phone implements UsbInterface {
    @Override
    public void start() {
        System.out.println("我是手机,开始工作");
    }

    @Override
    public void stop() {
        System.out.println("我是手机,结束工作");
    }
}

인터페이스 세부 정보

  1. 인터페이스를 인스턴스화할 수 없습니다.

  2. 인터페이스의 모든 메서드는 공용 메서드이며 인터페이스의 추상 메서드는 추상으로 수정할 필요가 없습니다.

  3. 공통 클래스 구현 인터페이스는 인터페이스의 모든 메서드를 구현해야 합니다.

  4. 추상 클래스는 인터페이스를 구현하므로 인터페이스의 메서드를 구현할 필요가 없습니다.

  5. 클래스는 동시에 여러 인터페이스를 구현할 수 있습니다.

  6. 인터페이스의 속성은 최종 속성만 가능하며 공개 정적 최종 속성입니다. 예를 들어 int a=1;은 실제로 public static final int a=1입니다.

  7. 인터페이스에서 속성의 액세스 형식: 인터페이스 이름 속성 이름

  8. 인터페이스는 다른 클래스에서 상속할 수 없지만 다른 여러 인터페이스에서 상속할 수 있습니다.

    interface extends B,C{}

  9. 인터페이스 수정자는 클래스 수정자와 마찬가지로 공개 및 기본값만 될 수 있습니다.

인터페이스 구현과 클래스 상속

인터페이스와 상속은 다양한 문제를 해결합니다.

  • 상속의 가치는 다음과 같습니다. 코드 재사용성 및 유지보수성 해결
  • 인터페이스의 가치는 설계, 다양한 사양 설계 및 다른 클래스가 이러한 메서드를 구현하도록 하는 데 있습니다.

인터페이스는 코드 디커플링을 어느 정도 달성합니다.

추상 클래스와 인터페이스를 사용하는 경우

참고

클래스를 설계할 때 먼저 인터페이스를 사용하여 클래스의 특성을 추상화하는 것을 고려하고, 일부 메서드를 재사용할 수 있는 경우 추상 클래스를 사용하여 코드를 재사용할 수 있습니다. 간단히 말해서 인터페이스는 사물의 특성을 추상화하는 데 사용되고 추상 클래스는 코드 재사용에 사용됩니다.

물론 모든 클래스가 인터페이스에서 추상 클래스로, 그런 다음 클래스로 설계되는 것은 아닙니다. 프로그래밍이 따라야 할 절대적인 패러다임은 없습니다. 자신의 필요에 따라 디자인하십시오.

인터페이스 다형성

  1. 다형성 매개변수, InterfacePoParameter.java
  2. 다형성 배열, InterfacePloyArr.java
  3. InterfacePolyPass.java 인터페이스에 다형성 통과 현상이 있습니다.

요약

클래스의 다섯 멤버: 속성, 메서드, 생성자, 코드 블록, 내부 클래스

package 包名;
class 类名 extends 父类 implements 接口名{
  成员变量//属性
  构造方法//构造器
  成员方法//方法
  代码块
 }

내부 클래스

또 다른 클래스 구조는 클래스 내부에 완전히 중첩되어 있습니다. 중첩된 클래스를 내부 클래스라고 하고 다른 클래스를 중첩한 클래스를 외부 클래스라고 합니다.

이너 클래스의 가장 큰 특징은 전용 속성에 직접 접근할 수 있고, 클래스 간의 포함 관계를 반영할 수 있다는 점입니다.

기본 문법

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

내부 클래스의 분류

메소드에서와 같이 외부 클래스의 로컬 위치에서 정의됨

  • 로컬 내부 클래스(클래스 이름 포함)
  • 익명 내부 클래스(클래스 이름 없음)

외부 클래스의 멤버 위치에서 정의됩니다.

  • 멤버 내부 클래스(정적으로 수정되지 않음)
  • 정적 내부 클래스(정적 수정 사용)

외부 클래스에서 로컬로 정의됨:

로컬 내부 클래스, com.innerclass.LocalInnerClass.java

  • 로컬 내부 클래스는 메소드와 같이 외부 클래스의 로컬 위치에 정의되며 클래스 이름을 갖습니다.
  • 상태가 로컬 변수이므로 액세스 수정자를 추가할 수 없습니다. 지역 변수는 한정자를 사용할 수 없지만 final로 수정할 수 있습니다.
  • 범위: 이를 정의하는 메서드 또는 코드 블록에서만 클래스 유형의 지역 변수와 동일합니다.
  • 로컬 내부 클래스는 비공개 클래스를 포함하여 외부 클래스 멤버에 직접 액세스합니다.
  • 외부 클래스는 개체를 만든 다음 내부 클래스 멤버에 액세스해야 합니다.
  • 다른 외부 클래스는 로컬 내부 클래스에 액세스할 수 없습니다.
  • 외부 클래스와 로컬 내부 클래스의 이름이 같은 경우 기본적으로 근접성의 원칙을 따르며 모든 당사자로부터 외부 클래스의 멤버를 흡수하는 경우 외부 클래스 이름을 사용할 수 있습니다.이.멤버 액세스
public class LocalInnerClass {
    public static void main(String[] args) {
    }
}

class Outer {
    private int n1 = 100;
    private void m2() {}
    private void m1() {
        // 局部内部类是定义在外部类的局部位置,比如方法中,并且有类名
        // 不能添加访问修饰符,因为他的地位就是一个局部变量。
        // 局部变量不能使用修饰符,但是可以用final修饰
        class Inner { // 局部内部类
            // 局部内部类可以直接访问外部类成员,包括私有的
            public void f1() {
                System.out.println("n1=" + n1);
            }
        }
    }
}

  1. 로컬 내부 클래스는 메서드/코드 블록에서 정의됩니다.
  2. 범위는 메서드 본문/코드 블록에 있습니다.
  3. 본질은 수업이다

익명 내부 클래스, com.anonymousInner.AnonymousInnerClass.java

익명 내부 클래스는 메소드와 같은 외부 클래스의 로컬 위치에 정의되며 클래스 이름이 없으며 여전히 객체입니다.

익명 내부 클래스는 인터페이스를 구현하거나 부모 클래스를 상속하는 것과 같습니다.

익명 내부 클래스의 기본 구문

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

  1. 익명 내부 클래스는 클래스 정의뿐 아니라 객체이기도 하므로 문법적 관점에서 보면 클래스 특성과 객체 생성 특성을 모두 가지므로 익명 내부 클래스 메소드를 호출할 수 있다.
  2. 개인을 포함하여 외부 클래스의 모든 멤버에 직접 액세스할 수 있습니다.
  3. 상태가 로컬 변수이므로 액세스 수정자를 추가할 수 없습니다.
  4. 범위: 이를 정의하는 메서드 또는 코드 블록에서만
  5. 익명의 내부 클래스는 외부 클래스의 멤버에 직접 액세스합니다.
  6. 다른 외부 클래스는 익명의 내부 클래스에 액세스할 수 없습니다.
package com.anonymousInner;
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer04 outer04 = new Outer04();
        outer04.method();
    }
}
class Outer04 {//外部类
    private int n1 = 10;//属性
    public void method() {//方法
        //基于接口的匿名内部类
        //1、需求:想使用接口IA,并创建对象
        //2、传统方式:写一个类,实现该接口,然后创建对象
        //3、需求是Tiger类只使用一次,后面再不使用
//        IA tiger = new Tiger();
//        tiger.cry();
        //4、可以用匿名内部类来简化开发

        //演示基于接口的匿名内部类
        //tiger的编译类型:IA
        //tiger的运行类型:com.anonymousInner.Outer04$1
        //底层:class Outer04$1 implements IA{}
        IA tiger = new IA() {
            @Override
            public void cry() {
                System.out.println("老虎叫");
            }
        };
        tiger.cry();
        System.out.println("tiger的运行类型"+tiger.getClass());

        //演示基于类的匿名内部类
        //jack的编译类型:
        //jack的运行类型:com.anonymousInner.Outer04$2
        //底层:class Outer04$2 extends Father{}
        //和""Father jack = new Father("jack");"" 有区别,区别在于"{};",
        //实际是匿名内部类继承了Father类,应该是叫向上转型
        Father jack = new Father("jack") {};
        System.out.println("jack的运行类型"+jack.getClass());
    }
}
interface IA {
    public void cry();
}
// 传统方法:写一个类,实现该接口,然后创建对象
class Tiger implements IA {
    @Override
    public void cry() {
        System.out.println("老虎叫");
    }
}
class Father {
    public Father(String name) {super();}
    public void test() {}
}

내부 클래스 연습, com.anonymousInner.InnerClassExercise02.java

  1. 벨소리 방식을 가지고 있는 벨 인터페이스 벨이 있습니다.
  2. 알람시계 기능이 있는 핸드폰급 핸드폰이 있는데 알람시계는 벨타입
  3. 휴대 전화 클래스의 알람 시계 기능을 테스트하고 익명의 내부 클래스를 매개 변수로 사용하여 다음을 인쇄하십시오. 게으른 돼지가 깨어났습니다.
  4. 그런 다음 다른 익명의 내부 클래스를 전달하고 다음을 인쇄합니다. 작은 친구가 수업 중입니다.
//1. 有一个铃声接口Bell,里面有个ring方法
//2. 有一个手机类Cellphone,具有闹钟功能alarmclock,参数是Bell类型
//3. 测试手机类的闹钟功能,通过匿名内部类作为参数,打印:懒猪起床了
//4. 再传入另一个匿名内部类,打印:小伙伴上课了
public class InnerClassExercise02 {
    public static void main(String[] args) {
        new Cellphone().alarmclock(new Bell(){
            @Override
            public void ring() {
                System.out.println("懒猪起床了");
            }
        });
        new Cellphone().alarmclock(new Bell() {
            @Override
            public void ring() {
                System.out.println("小伙伴上课了");
            }
        });
    }
}

interface Bell{
    public void ring();
}
class Cellphone{
    public void alarmclock(Bell bell){bell.ring();}
}

외부 클래스의 멤버 위치에서 정의됩니다.

멤버 내부 클래스

  1. 개인을 포함하여 외부 클래스의 모든 멤버에 직접 액세스할 수 있습니다.
  2. 액세스 수정자 public, protected, default, private을 추가할 수 있으며 상태는 구성원과 동일합니다.
  3. 범위: 외부 클래스의 다른 구성원과 마찬가지로 전체 클래스 본문입니다.
  4. 멤버 내부 클래스는 외부 클래스에 직접 액세스합니다.
  5. 외부 클래스가 내부 클래스에 액세스: 액세스에서 객체 생성
  6. 외부 기타 클래스는 내부 클래스의 멤버에 액세스합니다.
  7. 외부 클래스의 구성원과 내부 클래스의 이름이 같은 경우 내부 클래스 액세스는 기본적으로 근접성의 원칙을 따르며 외부 클래스의 구성원에 액세스하려면 (외부 클래스 이름.이를 사용할 수 있습니다. .회원) 액세스

정적 내부 클래스

정적 내부 클래스는 외부 클래스의 멤버 위치에 정의되며 정적 수정이 있습니다.

  1. 전용 멤버를 포함하여 외부 클래스의 모든 정적 멤버에 직접 액세스할 수 있지만 비정적 멤버에는 직접 액세스할 수 없습니다.
  2. 임의 액세스 한정자를 추가할 수 있습니다.
  3. 범위: 전체 클래스 본문에 대해 다른 구성원과 동일
  4. 정적 내부 클래스는 외부 클래스에 직접 액세스합니다.
  5. 외부 클래스는 정적 내부 클래스에 액세스하기 위해 객체를 생성합니다.

추천

출처blog.csdn.net/weixin_65656674/article/details/126416751