4.13 一周总结(面向对象---初始化 )

一周总结 面向对象

面向对象分为几大模块

封装 继承 多态 称为面向对象的三大特征

之后学习了 静态 final 抽象 接口 代码块 类的初始化 实例初始化

封装

就是把一个功能 或者**封装起来

主要涉及到 public protected 缺省 private(这一块没有很好的理解,)

public 只要在本模块下中都可以访问,使用

protected 本包以及本模块下的其他包中非子类都可以使用(这一块有问题。需要重新的再理解)

缺省:默认的,只可以在本包下可以使用

private: 只可以在本类才可以使用

继承

有一个子类 有一个父类 ,

子类可以继承父类 的属性和方法

这一块主要是 继承之后的方法可以重写,重写之后子类对象调用方法,优先执行子类的重写方法

重写 与重载

方法 可以重写,也可以重载

重写

重写:子类继承父类可以重写父类的方法, 子类如果重写父类的方法,子类对象调用的时候优先调用本类 的重写方法,如果没有重写。

那么,会从父类中找 继承过来的 方法

如果调用了 父类继承过来的方法之后 ,方法体内用到了 实例变量—a ,那么此时的变量a 是父类的 a,

父类没有声明变量 a 子类声明了变量a 但是父类的方法使用了a,编译会报错,即使子类继承父类,那么也会报错

public class exer {
    public static void main(String[] args) {
        Student s = new Student();
        s.show();
    }
}
class Person {
    // int a= 10;
    void show() {
        System.out.println(a);   // 这块的a会报错  
    }
}

class Student extends Person {
    int a = 5;
    void show() {
        System.out.println(a);
    }

}

方法:追根溯源

变量:就近一致

子类继承父类 只要是子类调用的是父类的方法,那么就会就近使用父类的变量,

子类如果重写了父类的方法,那么 子类对象在调用方法时执行的是子类自己的方法,这个时候就会优先使用子类自己的变量。

子类如果没有这个变量,才会使用父类继承过来的变量。

public class exer {
    public static void main(String[] args) {
        Student s = new Student();
        s.show();
    }
}
class Person {
    int a= 10;
    void show() {
        System.out.println(a);
    }
}

class Student extends Person {
   // int a = 5;
    void show() {
        System.out.println(a);  // 这个时候使用的是自己的方法,会优先在本类中找a,发现没有,那么使用父类继承过来的a
    }

}

假如 方法体内声明了一个局部变量a 那么执行那个方法就会优先使用哪个方法体内的局部变量(就近一致


这边一个小插入

局部变量 和 全局变量

局部变量:声明在 方法体内 随着方法的调用出生 随着方法的结束 结束 局部变量 需要初始化才可以使用

全局变量:声明在类中方法外,随着对象的创建,开辟空间 有默认值

重载

构造器是方法的重载

重载代表的是方法根据 不同的需求 ,去写的不同的方法。 重写则完全的将方法修改,覆盖。


多态

我的理解:多态是一个叠加的状态 ,一个子类可以属于另一个父类, 父类可以创建子类的对象。

代码:

Person p = new Student;

多态的三种应用方式
1.多态应用在形参:父类类型做形参类型 可以接受任意子类对象

2.多态应用在数组: 父类类型做数组类型 可以接受任意子类对象

3.多态应用在返回值类型: 父类类型做返回值类型 可以接受任意子类对象

编译看左边 运行看右边

如果一个程序使用了多态,编译的时候一定是按照父类进行编译的,如果父类编译不通过,那么程序就会报错。

public class exer2 {
    public static void main(String[] args) {
        // 使用多态
        Person p = new Student();
        p.show; // 报错,因为编译的时候 Person类没有show方法。
    }
}
class Person {
}
class Student extends Person {
    void show() {
        System.out.println("this is show");
    }
}

如果 父亲编译通过之后 程序会优先执行子类中的重写父类方法 ,子类如果没有重写父类的方法,就会向上寻找父类。


假如方法有形参,那么

编译时 先优先寻找最匹配的方法,如果没有,只能退而求其次,使用一个父类或者其他可以接收实参的方法。

运行时 也同样优先调用子类重写的方法,如果没有会线上寻找父类。

package com.atguigu.homework3;

public class Test03 {
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new B();
        B b = new B();
        C c = new C();
        D d = new D();
        System.out.println("(1)" + a1.show(b));
        System.out.println("(2)" + a2.show(d));
        System.out.println("(3)" + b.show(c));
        System.out.println("(4)" + b.show(d));
    }
}
class A{
    public String show(D obj){
        return ("A and D");
    }
    public String show(A obj){
        return "A and A";
    }
}
class B extends A{
    public String show(B obj){
        return "B and B";
    }
    public String show(A obj){
        return "B and A";
    }
}
class C extends B{

}
class D extends B{

}

(1)A and A
(2)A and D
(3)B and B
(4)A and D
   

几个关键字的理解

static:

static 静态

static 可以修饰 变量 方法

修饰变量时:静态 变量保存在方法区内:所有对象共享一个数据,

​ 非静态的话,变量是保存在堆里边,每个对象在new 的时候都会在堆中创建一块空间,变量保存在自己的空间当中,对象之 间是彼此分离的。

修饰方法时:静态方法 类名.方法名 调用

​ 非静态: 对象名.方法名

static 修饰的 方法称为静态方法,不能调用静态的资源

原因:static修饰的方法是随着类的加载而开辟空间, 而非静态资源是随着对象的创建而创建的;

​ 所以在非静态资源还没有生成的时候可能类已经在加载了,这个时候肯定不能使用非静态的资源。

解决:

​ 创建对象,进行引用;

public class Test {
    public static void main(String[] args) {
       Person.sum();
    }
}
public class Person {
    int a=10;
    static void sum(){
       // System.out.println(a); 报错 静态方法不能直接使用非静态资源
        //  需要创建对象 才可以使用非静态资源
        Person p = new Person();
        System.out.println(p.a);
    }
}

静态方法 不能被重写 不能使用this super

final

最终的,不能被改变

final 可以修饰 类 方法 变量

final 修饰类

被修饰的类不能被继承

final修饰方法

修饰的方法不能被重写(重写意味着更改,final是最终的,不能更改)

final 修饰变量

修饰的变量变为常量, 不能再被更改

final修饰的变量必须初始化:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FmORjP2D-1681394285742)(C:\Users\任帅\AppData\Roaming\Typora\typora-user-images\image-20230413165216626.png)]

​ 初始化方式 :

public class Test {
    final int a = 10; // 显示赋值

    // 构造器赋值
    final int b;
    public Test(int b) {
        this.b = b;
    }
    
    //初始化 代码块赋值
    final int c;
    {
        c = 20;
    }

    /* final int d;
           d=25;   报错 这种方式不能给final赋值
   */


}

局部变量:
       基本数据类型: 数值不能改变
       引用数据类型: 地址值不能改变
成员变量:
       必须有赋值动作

抽象 abstract

抽象类

抽象类 可以拥有普通类的所有资源

包括: 变量和方法 使用

但是 抽象类不能创建对象

抽象方法

抽象方法 必须写在抽象类当中,抽象方法天生就是被重写的。不能被 private static final 修饰

抽象方法 写法 没有大括号

 public void show(); 

注意:

一个类如果继承了一个抽象类,那么这个类必须重写抽象类当中的所有抽象方法


接口

我的理解:接口是为了实现类多继承,一个儿子可以拥有多个父亲。

类实现接口可以看作是:类继承接口

那么:

既然是继承 那么就会拥有继承的所有特性 也可以使用多态

接口的成员
1.成员变量 (全局静态常量)

接口内的变量 默认被 public static final 修饰 。

即使我们 在接口中 int a=10;(final 修饰必须被赋值)

​ 那么也是默认有一个 public static final

   public static final int a=10;
2.抽象方法

在接口中声明一个方法默认被public abstract修饰

public interface Fly {
  public static final int a=10;
  
    void show(); //接口中的方法(抽象方法) 默认被 public abstract 修饰 所以没有{}
    //  public abstract void show();
    
}
3.静态方法

默认被 public 修饰 拥有静态方法的特性

4.默认方法

默认被public 修饰

publicdefault void show1(){
  
}
接口使用的注意:
       1.如果一个类实现了接口(一个或多个)那么就必须重写接口内所有的抽象方法
         否则此类要变为抽象类

       2.接口可以多继承

       3.如果实现的多个接口内有同名的抽象方法 只会重写一个

       4.如果实现的多个接口内有同名的默认方法 则 实现类必须重写此默认方法
         重写的方法内 想要调用父接口的默认方法 接口名.super.默认方法名()
          Start1.super.study();
          Start2.super.study();
       5.先继承再实现

       6.如果继承的类和实现的接口内有同名的方法 会优先使用 继承中的方法
        亲爹优先

       7.如果继承的类和实现的接口内有同名的属性 使用时必须指明来自于哪个类或者接口
内置接口
1.对象的克隆
package com.atguigu.clone05;
/*
对象的克隆
    1.实现接口 Cloneable
    2.重写 Object clone()
    3.对象调用方法进行克隆
 */
public class PersonTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person p1 = new Person("张三",20);
        System.out.println("p1 = " + p1);
       // Person p2 = p1;
        //多态
        Object clone = p1.clone();
        //todo 使用子类自己独有的属性 需要向下转型
        Person p = (Person)clone;
        p.name="安琪拉";
        System.out.println("p1 = " + p1);
    }
}
package com.atguigu.clone05;

public class Person implements Cloneable{
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    String name;
    int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
2.对象比较接口

内部比较器 Comparable

package com.atguigu.comparable06.c1;
/*
Comparable: 内部比较器 比较对象
            在比较对象类的内部制定比较规则
       步骤:
        1.让比较对象所在的类 实现  Comparable接口
        2.重写 int compareTo()方法制定比较规则
             会使用this
              前一个对象>后一个对象  返回正整数
              前一个对象<后一个对象  返回负整数
              前一个对象==后一个对象  返回0
            Double.compare(小数, 小数);
        3.对象调用比较方法获取结果

 */
public class StudentTest {
    public static void main(String[] args) {

        Student s1 = new Student("安琪拉",22,99.6);
        Student s2 = new Student("吕布",20,99.6);

        int compare = s1.compareTo(s2);

        System.out.println("compare = " + compare);


    }
}
package com.atguigu.comparable06.c1;

public class Student implements Comparable {
    private String name;
    private int age;
    private double score;

    @Override
    public int compareTo(Object o) {

        Student s = (Student) o;
     /*   if(this.score>s.score){
            return 1;
        }else if(this.score<s.score){
            return -1;
        }else{
            return 0;
        }*/
        //return (int)(this.score-s.score);
        int compare = Double.compare(this.score, s.score);
        return compare;
    }

    /**
     * 向上转型:Object o = s2
     *
     *
     * @return
     */
   /* public int compareTo(Object o) {
        //this: s1
        //使用子类自己独有资源 向下转型
        Student s = (Student) o;
        return this.age - s.age;
    }*/

    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }

}

外部比较器 Comparator

/*
外部/定制比较器:用来比较对象
   1.创建一个比较规则类 实现 Comparator接口
   2.重写方法 制定比较规则
         前一个对象>后一个对象   返回 正整数
         前一个对象<后一个对象   返回 负整数
         前一个对象==后一个对象  返回 0
   3.在需要比较对象的位置创建 比较规则类对象

   4.使用比较规则类对象调用方法比较要比较的对象

    Dog 类
       String name ;
       double height;

 */


package com.atguigu.comparator01.c1;

import java.util.Comparator;
//比较规则类
public class SortStudentByScore implements Comparator {
    /**
    多态的向上转型
     Object o1 = s1;
     Object o2 = s2;
     */
    public int compare(Object o1, Object o2) {
        //使用子类自己独有的资源 需要向下转型
        Student s = (Student) o1;
        Student s1 = (Student) o2;
        return Double.compare(s.score,s1.score);
    }
}
package com.atguigu.comparator01.c1;

public class Student implements Comparable{

    String name;
    int age;
    double score;

    @Override
    public int compareTo(Object o) {
        //按照年龄比较
        Student s = (Student) o;
        return this.age-s.age;
    }

    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }

}
@org.junit.Test
public void test02(){
    //todo 使用外部比较器
    Student s1 = new Student("安琪拉",20,98.6);
    Student s2 = new Student("妲己",19,98.8);
    //创建比较规则类对象
    SortStudentByScore sortStudentByScore = new SortStudentByScore();
    //使用比较规则类对象调用方法比较要比较的对象
    int compare = sortStudentByScore.compare(s1, s2);

    System.out.println("compare = " + compare);


}

内部类

内部类顾名思义就是生命在 类里面的类

内部类分为四种

1.成员内部类

成员内部类 就和类中的属性和方法同等地位

可以被 四种权限修饰符修饰 不能使用静态的资源(属性 和方法 ),但是可以存在静态的常量 (static final 在一块)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-izo7YlFD-1681394285743)(C:\Users\任帅\AppData\Roaming\Typora\typora-user-images\image-20230413211118434.png)]

内部类可以使用外部类 的资源

外部类也可以使用内部类的资源 : 需要先创建外部类对象 之后 外部类对象.内部类

外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
Outer.Inner inner =  new Outer().new Inner();

2.静态成员内部类

也是写在类中 只不过用static 修饰

可以存在静态的资源

内部类访问外部类

可以直接访问外部类的静态资源 外部类的非静态资源 需要创建外部类对象访问 (与静态方法访问非静态资源一个道理)

外部类访问内部类

访问静态资源 :外部类名.内部类名.资源名

非静态:内部类对象名.资源名

其他类访问内部类

    其他类使用内部类资源
    静态资源 外部类名.内部类名.资源名
    非静态资源
      外部类名.内部类名 对象名 = new 外部类名.内部类名();
      对象名.资源名

3.局部内部类

**6.如果局部内部类使用了所在方法的局部变量 则此变量默认+final *** 很重要

局部内部类:写在方法内的内部类
       位置: 方法内
       注意:
            1.权限修饰符只能是 缺省的
            2.局部内部类中 不能使用静态资源
            3.局部内部类使用外部类的资源类型 由所在方法决定
            4.局部内部类也有作用域限制
            5.局部内部类也会生成独立的字节码文件 命名方式
              外部类名$序号内部类名.class  序号从1开始
              OuterTest$1A.class
            6.如果局部内部类使用了所在方法的局部变量 则此变量默认+final *****
              jdk8及其以后 自动+final
              jdk8前 需要手动+final

4.匿名内部类 (重点)

记忆这种写法,就等于是创建了一个这个类的子类 和对象 因此也可以继承 多态

大括号后.资源 也可以调用资源

匿名内部类:没有名字的内部类
     场景: 简化显示创建对象操作
     创建匿名内部类的方式:
         1. new(){} 既可以是普通类也可以是抽象类
         2. new 接口(){}
     匿名内部类创建成功后的意义:
        1.创建了该类/接口的匿名[子类]
        2.完成了该匿名子类对象的创建
     注意:
        1.匿名内部类也会产生独立的字节码文件命名方式
          外部类名$序号.class
          Test$1.class Test$2.class
        2.匿名内部类是特殊的局部内部类 使用了所在方法的局部变量 变量会+final修饰

父类

public class Person {
    String name;
    int age;
    public Person() {
    }
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void show(){
        System.out.println("this is Person show");
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

子类



public void test03() {

    new Person() {
        @Override
        public void show() {
            System.out.println("匿名子类中重写的方法");
        }
    }.show();

}

代码块

在类中方法外 用 { } 包括的代码 在对象声明的时候编译运行 (创建一个对象执行一次)

成员代码块(构造代码块)

成员代码块/构造代码块:
        位置:类中方法外
        作用: 1.可以给成员变量赋值
              2.可以将构造器中重复的逻辑提取到代码块内
        注意:
            1.创建一次对象执行一次
            2.先于构造器执行
            3.有多个成员代码块时 从上到下依次执行
            4.代码块有作用域限制

静态代码块

加 static修饰的代码块 (只会执行一次 )

3.2静态代码块:
       位置: 类中方法外
       作用: 可以给静态成员变量赋值
            初始化作用
        注意:
           1.静态代码块只会执行一次
           2.静态代码块先于普通代码块执行

初始化

先父类初始化-----子类初始化-------实例初始化

实例初始化 的时候 要注意 顺序

尤其注意 每一个类构造器中 第一行的位置 都会默认存在一个 super();

super(); 会调用父类的构造器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XUf72ylY-1681394285744)(C:\Users\任帅\AppData\Roaming\Typora\typora-user-images\image-20230413214954211.png)]

四.初始化
    4.1类的初始化:
              目的: 给类中的静态成员变量赋值的过程
              内容:编译器会自动生成一个<clinit>
                       静态成员变量显示赋值语句
                       静态代码块内容
                       谁先写谁先执行
              注意:
                  0.只要使用了类中的静态资源
                     创建对象 会触发类的初始化
                  1.类的初始化只会执行一次
                  2.如果存在继承关系 会先执行父类初始化再执行子类初始化
    4.2实例初始化
             目的: 给类中的非静态成员变量赋值的过程
             内容:编译器会自动生成一个方法<init>
                 ①super()
                 ②普通成员变量显示赋值语句
                 ③普通代码块内容
                 ④构造器内容
             执行顺序: ①②③④
                      ①③②④
    4.3混合初始化
          类初始化 --> 实例初始化
          父类 --> 子类

块只会执行一次
2.静态代码块先于普通代码块执行






## 初始化

先父类初始化-----子类初始化-------实例初始化 

实例初始化 的时候 要注意 顺序  

**尤其注意 每一个类构造器中 第一行的位置 都会默认存在一个 super();**



**super(); 会调用父类的构造器**



[外链图片转存中...(img-XUf72ylY-1681394285744)]



```Java
四.初始化
    4.1类的初始化:
              目的: 给类中的静态成员变量赋值的过程
              内容:编译器会自动生成一个<clinit>
                       静态成员变量显示赋值语句
                       静态代码块内容
                       谁先写谁先执行
              注意:
                  0.只要使用了类中的静态资源
                     创建对象 会触发类的初始化
                  1.类的初始化只会执行一次
                  2.如果存在继承关系 会先执行父类初始化再执行子类初始化
    4.2实例初始化
             目的: 给类中的非静态成员变量赋值的过程
             内容:编译器会自动生成一个方法<init>
                 ①super()
                 ②普通成员变量显示赋值语句
                 ③普通代码块内容
                 ④构造器内容
             执行顺序: ①②③④
                      ①③②④
    4.3混合初始化
          类初始化 --> 实例初始化
          父类 --> 子类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值