day_06笔记:继承、重写、多态(面向对象三大特点下)

1 .StringBuilder

  • 一个可变的字符序列。

  • 但不保证同步。

可以将StringBuilder看成是一个容器,这里的可变指的是StringBuilder对象的内容是可变的。

1.1 StringBuilder和String的区别

String : 内容是不可变的

StringBuilder : 内容是可变的

1.2 StringBuilder 的构造方法

    • StringBuilder() 构造一个没有字符的字符串构建器,初始容量为16个字符。
      StringBuilder(int capacity) 构造一个没有字符的字符串构建器,由 capacity参数指定的初始容量。
      StringBuilder(String str) 构造一个初始化为指定字符串内容的字符串构建器。

1.3 StringBuilder的常用方法

    • StringBuilderappend(int i)int参数的字符串表示法附加到此序列。
      StringBuilderappend(long lng)long参数的字符串表示法附加到此序列。
      StringBuilderappend(Object obj) 追加 Object参数的字符串 Object形式。
      StringBuilderappend(String str) 将指定的字符串附加到此字符序列。
    • StringBuilderinsert(int offset, String str) 将字符串插入到此字符序列中。
      intlastIndexOf(String str) 返回指定子字符串最右边出现的字符串内的索引。
      intlastIndexOf(String str, int fromIndex) 返回指定子字符串最后一次出现的字符串中的索引。
    • Stringsubstring(int start) 返回一个新的 String ,其中包含此字符序列中当前包含的字符的子序列。
      Stringsubstring(int start, int end) 返回一个新的 String ,其中包含此序列中当前包含的字符的子序列。
      StringtoString() 返回表示此顺序中的数据的字符串。
      voidtrimToSize() 尝试减少用于字符序列的存储。
         public static void main(String[] args) {
              //StringBuilder对象的创建  底层本质依然是字节数组
              StringBuilder sb1 = new StringBuilder();
              StringBuilder sb2 = new StringBuilder(32);//构建一个容量为32的字节数组
              StringBuilder sb3 = new StringBuilder("abcdef");
              sb1.append("abc").append(123).append(true);//链式编程
              String str = sb1.toString();
              System.out.println(str);
              System.out.println(sb1.length());
              sb1.insert(3,"hello");
              System.out.println(sb1.toString());
              System.out.println(sb1.reverse().toString());//字符串的反转  逆序
              sb1.setCharAt(0,'A');
              System.out.println(sb1.toString());// 修改指定位置的字符
          }

      1 实现一个将String和Stringbuilder两个对象之间的相互转换

      1 将StringBuilder 转换为String

      String toString() 返回表示此顺序中的数据的字符串。

      2 将String转换为StringBuilder

      StringBuilder(String str) 构造一个初始化为指定字符串内容的字符串构建器。

      2 StringBuilder和String的使用场景

      如果只是单纯的使用到一个字符串,则直接使用String

      如果字符串的内容是需要动态改变(动态拼接)则是用Stringbuilder

      StringBuffer 和Stringbuilder的区别:

      Stringbuffer 线程同步的 线程安全的

      Stringbuilder线程不同步 线程不安全的

      在一般情况下 使用StringBuilder ,在多线程环境下 进行字符串的拼接操作 此时就需要考虑使用StringBuffer

      2.继承

      是面向对象三大特征之一。

      2.1 继承的格式:

      public  class  子类名  extends  父类名{
      
      }

      将继承了其他类的类 称为子类 派生类 衍生类

      被继承的类 称为父类 超类 基类

      2.2 继承中子类的特点:

      1 子类可以继承父类非私有成员;

      2 子类还可以有自己特有的成员

      2.3 继承所产生的影响:

      1 继承似的类与类之间产生了关系,父子类关系,产生父子类关系后,子类可以使用父类中非私有的成员。

      2 子类继承了父类,就继承了父类的非私有的方法和属性

      3 在子类中,可以使用父类中定义的方法和属性,也可以创建新的属性和方法

      4 在java中,继承的关键字用的是extends 及子类不是父类的自己 而是对父类的"扩展"

      public class Person {
          private String name;
          private int age;
          String county="中国";
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
          public void eat(){
              System.out.println("在餐厅用餐...");
          }
      }
      public class Student extends Person {
          String school = "中北大学";
          public Student() {
          }
      
          public void study(){
              System.out.println("努力敲代码.....");
          }
      
      }
      public class Teacher  extends Person{
      
      
          public Teacher() {
          }
          public  void teach(){
              System.out.println("认真讲课....");
          }
      
      }
      
      public class ExtendsTest {
          public static void main(String[] args) {
              Student  stu = new Student();
              stu.setName("小明");
              stu.setAge(18);
              System.out.println(stu.getName() +"--"+stu.getAge() +"--"+stu.county);
              stu.eat();
              stu.study();
          }
      }

      2.4 继承规则

      1 子类不能直接访问父类的私有的成员变量和方法

      public class ExcentsDemo {//测试类
          public static void main(String[] args) {
              Fu f = new Fu();
              f.show();
              Zi z = new Zi();
              z.method();
              z.show();
          }
      }
      class Fu{
          public void  show(){
              System.out.println("show方法被调用....");
          }
      }
      class Zi extends  Fu{
          public  void  method(){
              System.out.println("method方法被调用");
          }
      }

      2.5 继承的好处和弊端

      好处:

      1 提高了代码的复用性

      2 提高了代码的维护性

      弊端:

      继承使得类与类之间产生了关系,类的耦合性增强,当父类发生变化时,子类实现也不得不跟着变化,削弱了子类的独立性

      开发的原则:高内聚 低耦合

      什么时候使用继承?

      继承体现的是一种关系:is a

      继承的使用,一定是当两个类之间满足is a的关系的时候 才使用继承。不要为了继承而继承(不要仅仅为了减少代码的编写 ,提高代码的复用而去使用继承)

      2.6 继承中变量的访问特点

      public class ExcentsDemo {//测试类
          public static void main(String[] args) {
              Fu f = new Fu();
              f.show();
              System.out.println(f.num);//10
              Zi z = new Zi();
              System.out.println(z.num);//20
              z.method();//30
              z.show();
          }
      }
      class Fu{
          int num = 10;
          public void  show(){
              System.out.println("show方法被调用....");
          }
      }
      class Zi extends  Fu{
          int num = 20;
          public  void  method(){
              int num = 30;
              System.out.println(num);
              System.out.println("method方法被调用");
          }
      }

      1 在java中 变量的使用遵循就近原则

      2 在继承关系的类中,优先在子类的局部返回中找

      3 子类的成员范围中找

      4 父类的成员找

      5 如果以上都没有(不考虑的父类的父类) 则报错。

      2.7 super

      super的用法和this用法相似:

      1 this:代表本类的当前对象(代表本类对象的引用)

      2 super :代表本类的父类对象(代表父类存储空间的标识(引用))

      this:可以访问成员变量 访问成员方法 调用本类的其他构造方法

       public   int  add(int a,int b){
              return  a+b;
          }
          public int add(int a,int b , int c){
              return  this.add(a,b) +c;
          }

      super: 可以访问父类的成员变量 调用父类的成员方法 调用父类的构造方法

        public  Zi(){
              super();
          }
          public Zi(int num){
              super();
              this.num = num;
              System.out.println("子类的带参构造执行....");
          }

      构造方法调用,this和super不能同时出现。this和super调用构造方法 都必须出现在第一行

      使用super去访问成员变量或者方法 成员变量或者成员方法 一定是子类和父类拥有同名的变量和方法的时候

      2.8.继承中构造方法的访问特点

      在子类的构造方法中,默认会调用父类的无参构造

      为什么呢?

    • 因为子类会继承父类中的数据,可能还会使用父类的数据,所以 ,子类初始化之前 一定要先使用父类的数据的初始化

    • 每一个子类的构造方法中 第一条语句默认都是super();

    • 如果父类中没有无参构造 会发生什么?

    • 通过super区显式的调用父类的其他的带参构造

       super(num);

    • 在父类中提供一个无参构造

    • 推荐:自己提供无参构造

2.9.继承中成员方法的访问特点

public class ExcentsDemo {//测试类
    public static void main(String[] args) {
        Fu f = new Fu();
        f.show();//父类
        Zi z = new Zi(10);
        z.show();//子类的show
    }
}
class Fu{
    int num = 10;
    public Fu(){
        System.out.println("父类的无参构造执行....");
    }
    public Fu(int num){
    }
    public void  show(){
        System.out.println("父类的show方法被调用....");
    }
    public   int  add(int a,int b){
        return  a+b;
    }
    public int add(int a,int b , int c){
        return  this.add(a,b) +c;
    }
}
class Zi extends  Fu{
    int num = 20;
    int a ;
    String str;
    public  Zi(){

    }
    public Zi(int num){
        super(num);

        this.num = num;
        System.out.println("子类的带参构造执行....");
    }
    public Zi(int num , int a ,String str){
            super(num);
    }
    public  void  method(){
        int num = 30;
        System.out.println(super.num);
        System.out.println("method方法被调用");
    }
    public void show(){
        System.out.println("子类的show 方法...");
    }
}

通过子类对象访问子类和父类的同名方法:

  • 子类的范围中找

  • 父类范围找

  • 如果都没有 就报错。

子类对父类的扩展:子类可以有自己的特有的成员变量和成员方法,子类中还可以定义和父类同名的成员变量和方法。

2.10 方法的重写

方法重写,子类中出现和父类中一模一样的方法的声明。

方法重写的应用场景:当子类需要父类的功能的时候,而父类的功能又不能满足子类的需求,在方法中 ,子类有自己的特点。

public class OverrindeDemo {;
    public static void main(String[] args) {
        Son s = new Son();
        s.getMoney();
    }
}
class Father{
    public  void getMoney(){
        System.out.println("通过体力劳动来获取金钱....");
    }
 }
 class Son extends  Father{
    @Override//方法重写的检测标记
    public  void  getMoney(){
        System.out.println("通过脑力劳动来获取金钱....");
    }
 }

方法重写的注意事项:

1 私有的方法不能被重写。

2 子类重写的时候 不能采用比父类给加严格的访问修饰符(pulic > default > private)

3 当父类中的方法为私有时,如果子类出现了和父类一模一样的方法的时候,此时这两个方法之间没有任何关系。

2.11.java中继承的注意事项

1 java中类的继承只支持单继承,不支持多继承。一个类只能有一个直接的父类

2 java中的类的继承支持多层继承 不支持多重继承

class A{
    int a = 100;
}
class Father extends  A{
     void getMoney(){
        System.out.println("通过体力劳动来获取金钱....");
    }
 }
 class Son extends  Father{
    @Override//方法重写的检测标记
    public  void  getMoney(){
        System.out.println("通过脑力劳动来获取金钱....");
    }
 }

3 包

3.1 package

包: 本质就是文件夹,对类进行分类管理

包的命名格式: 包名采用多级格式,每一级之间使用.分割

一般情况下:包名采用公司域名的逆序:cn.lanqiao.模块名

3.2 导包(import)

String类位于java.lang包下,在使用String类的时候 不需要导包

凡是位于java.lang包下的类 在使用的时候都不需要导包。除此之外,其他的类在使用的时候,都需要进行导包操作

导包意义:

当一个类有包信息之后,此时类的类名就有了两种形式

全类名:包名.类名 java.util.Scanner

简单类名:类名 Scanner

导包的意义就在于,当我们在类的内部使用类的时候,可以直接使用类的简单类名来进行相应的操作

导包语法:import java.util.Scanner;

3.3.jdk的主要的包

java.lang 包含一些java语言的核心类 如:String Thread

java.awt 主要包含了一些图形化窗口相关操作的工具类

java.net 主要包含了一些和网络相关的操作

java.io 主要包含IO操作一些相关的类

java.util 主要包含的是一些使用的工具类

4.修饰符

4.1权限修饰符

修饰符同一个类同一个包中子类无关类不同包的子类不同包的无关类
private
默认不写【default】
protected
public

4.2状态修饰符

  • final(最终的)

  • static(静态)

4.2.1 final

final 是一个关键字 最终的意思,他可以修饰成员方法 成员你变量 类

final修饰的特点:

修饰方法: 修饰方法的时候 方法不能被重写

修饰变量:变量是常量,不能被再次赋值。只能被赋值一次

   // public final  int A =100;//在声明的同时赋值
   public final  int A ;
    public A(){//使用构造方法来赋值
        A = 100;
    }

修饰类:类不能被继承

public final class  A {
}

final修饰局部变量:

final修饰局部变量的时候 ,变量是基本类型,变量的值不能改变。

final修饰引用类型的局部变量

 public static void main(String[] args) {
      final   Student stu = new Student();// 自定义引用类型的变量
        stu.setName("张三");
        stu.setAge(24);
        System.out.println(stu.getName()+"---"+stu.getAge());
       // stu= new Student(); 这个是不允许
        stu.setName("李四");//这个可以允许修改
        stu.setAge(26);
        System.out.println(stu.getName()+"---"+stu.getAge());
    }

final修饰的是引用类型的地址值是不能发生改变,但是引用地址指向的对象的属性却是可以改变的

4.2.2.static

static的意思是静态,可以修饰成员方法 成员变量

适用范围:

在java类中,可以使用static修饰属性,方法,代码块,内部类

被修饰的成员的特点:

1 随着类的加载而夹在

2 优先于对象存在

3 修饰的成员 被所有对象共享

4 访问权限允许时,可以不创建对象,直接被类调用,调用时可以使 类名.

 public static void main(String[] args) {
      Student stu1  = new Student();// 自定义引用类型的变量
        stu1.setName("张三");
        stu1.setAge(24);
        //为static修饰的变量赋值  推荐使用类名.的形式访问
        Student.university ="中北大学";
        System.out.println(stu1.getName()+"---"+stu1.getAge()+"--"+Student.university);
        Student  stu2= new Student();
        stu2.setName("李四");//这个可以允许修改
        stu2.setAge(26);
        Student.university ="青岛大学";
        System.out.println(stu2.getName()+"---"+stu2.getAge()+"--"+Student.university);
        Student  stu3= new Student();
        stu3.setName("王五");//这个可以允许修改
        stu3.setAge(22);
        System.out.println(stu3.getName()+"---"+stu3.getAge()+"--"+Student.university);
    }

static的访问特点;

public   class  A {
    int a = 100;//非静态成员变量
    static int b =200;//静态成员变量
    public static void main(String[] args) {//
     // show();  静态方法不能直接调用非静态方法
        A a = new A();//在静态方法中 如果要访问非静态的成员  必须通过对象来访问
        a.show();
        int aa = a.a;
        print();
    }
    public  void show(){//非静态方法
        System.out.println(a);//
        System.out.println(b);
    }
    public static void print(){//静态方法
      //  System.out.println(a);
        System.out.println(b);
    }
}

非静态成员方法:

  • 能访问静态的成员变量

  • 能访问非静态的成员变量

  • 能访问静态的成员方法

  • 能访问非静态的成员方法

静态的成员方法:

  • 能访问静态的成员变量

  • 能访问静态的成员方法

    用一句话来概括:静态成员方法只能访问静态成员;非静态成员方法 不但可以访问非静态也可以访问静态

    4.2.3 static修饰的对象运行时的内存分配(掌握)

    jvm方法区:

    所有的方法区在逻辑上是属于堆的一部分,但是一些简单的实现可能不会选择区进行垃圾收集或者进行压缩。但是对于 HopSpot jvm而言,方法区还有一个别名 non-heap(非堆)。目的就在于和堆分开。

    方法区可以看做是一块独立于java堆的内存空间

    方法区主要存放的是Class(类信息),而堆中主要存放的是实例化的对象

    HopSpot中方法区的演变

    • jdk7及以前 习惯把方法区称为永久代

    • jdk8 以后 使用元空间取代了永久代

      jdk8以后 永久代不存在了,存储的类信息,编译后的代码数据都应移动到了元空间,元空间并没有处于堆内存,而是直接占用的本地内存。

      元空间的本质和永久代是类似,都是对jvm规范中方法区的实现,元空间与永久代最大区别在于:元空间不在虚拟机设置的内存中,而是使用本地内存。永久代,元空间二者并不仅仅是名字变了,内部结构也调整了。

      方法区存储的信息:类型信息 常量 静态变量以及编译后的代码数据等

      类型信息:包名 类名 父类等

      方法信息;方法名称 方法的返回值类型 方法的形参。方法的修饰符

      non-final的类变量(static)

      静态变量和类关联在一起的,随着类的加载而加载,他们成了类数据在逻辑上的一部分,类变量被类的所有实例对象共享,存在于方法区,即使没有实例对象,你也可以访问他。

      5 单例设计模式

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

      所谓的单例设计模式,就是采取一定的方法保证在整个系统运行中,对某一个类只能存在一个对象实例,并且该类只提供一个获取该类实例的方法。

      单例设计模式的--饿汉式

      public class Singleton {
          //1 私有化构造方法
          private Singleton(){
          }
          // 2 创建本类的一个静态对象
          private static  Singleton singleton = new Singleton();
          //3   获取该类实例对象的方法
          public static  Singleton getInstance(){
              return  singleton;
          }
      }
      

      单例设计模式的--懒汉式

      public class Singleton {
          //1 私有化构造方法
          private Singleton(){
          }
          // 2 创建本类的一个静态对象
          private static  Singleton singleton ;
          //3   获取该类实例对象的方法
          public static  Singleton getInstance(){
              if(singleton == null){
                  singleton = new Singleton();
              }
              return  singleton;
          }
      }

      单例模式的优点:

      由于单例模式只生成一个实例,减少了系统的开销,当一个对象的产生需要较多的资源时,比如读取配置文件,产生其他的依赖对象时,则可以通过在应用启动的时候直接产生一个单例对象,然后让其永驻内存的方式来解决

6.多态

6.1多态的概述

什么是多态?

同一个对象,在不同的时刻表现出来的不同形态。

我们可以说 猫是猫 : 猫 cat = new 猫();

也可以说猫是动物: 动物 animal = new 猫();

这里的猫在不同的时刻表现出不同的形态 称为多态

多态的前提条件:

1 要有继承关系(实现关系)

2 要有方法的重写

3 要有父类的引用指向子类对象。

多态要点:

1 多态是方法的多态,不是属性的多态(多态和属性无关)

2 多态的存在要有三个必要条件

  • 要有继承关系(实现关系)

  • 要有方法的重写

  • 要有父类的引用指向子类对象。

    3 父类的引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。

具体来讲: 多态指的是同一个方法调用,由于对象不同可能会有不同的行为。

6.2 多态中的成员的访问特点

public class Animal {
    public int age = 3;
    public void eat(){
        System.out.println("动物进食.....");
    }
}
public class Cat  extends  Animal{
    public int age = 2;
    public int weight = 10;
    @Override
    public void eat(){
        System.out.println("猫吃鱼...");
    }
    public void palyGame(){
        System.out.println("猫抓老鼠玩....");
    }
}
public class Dog  extends  Animal{
    public int age = 4;
    public String name = "旺财";
    @Override
    public void eat(){
        System.out.println("狗吃骨头....");
    }
    public void work(){
        System.out.println("狗看家....");
    }
}

测试类

public class AnimalTest {
    public static void main(String[] args) {
        // 父类引用指向子类对象
        Animal a1 = new Cat();
        a1.eat();// 猫吃鱼
        //a1.palyGame();//访问不到
        System.out.println(a1.age);//3
        Animal a2 = new Dog();
        a2.eat();//狗吃骨头
        System.out.println(a2.age);//3
    }
}

如果在编译时和运行时类型不一致,就出现了对象的多态性。

多态情况下成员方法,看左边: 看的是父类的引用(父类中不具有子类特有的方法)

看右边 看的是子类的对象(实际运行时的子类重写父类的方法)

成员变量:不具备多态性,只要看引用变量声明的类型即可。

总结:

成员方法:编译看左边 运行看右边

成员变量:编译看左边 运行看左边

6.3 多态的好处和弊端

好处

提高了代码的扩展性。定义方法的时候,使用的是父类型作为参数,在使用是的时候,可以使用具体的子类作为真是的操作对象

弊端:不能访问子类特有的成员。

public class Person {

    public void seedAnimal(Animal animal){
        animal.eat();
    }
}
   public static void main(String[] args) {
        Person person = new Person();
        person.seedAnimal(new Cat());
        person.seedAnimal(new Dog());
    }

6.4 虚拟方法调用

        Animal a = new Animal();
        a.eat();//动物进食
        // 父类引用指向子类对象
        Animal a1 = new Cat();
        a1.eat();// 猫吃鱼
        //a1.palyGame();//访问不到
        System.out.println(a1.age);//3
        Animal a2 = new Dog();
        a2.eat();//狗吃骨头
        System.out.println(a2.age);//3

子类中定义了与父类同名同参数的方法,在多态的情况下,将此事父类的方法称为虚拟方法。父类根据赋给他的不同的子类对象,动态调用属于子类的该方法,这样的方法 的调用在编译器是无法确定的。

Animal a1 = new Cat();
a1.eat();// 猫吃鱼 

编译时类型和运行时类型

编译时 a1 是Animal类型,而方法调用时在运行时确定的,所以表用的是Cat类的eat方法。这种称为动态绑定。

6.5 重写和重载的区别

重载:是指允许存在多个同名方法,而这些方法的参数不同。编译器根据方法不同的参数列表,对同名方法的名称做修饰。对于编译器而言,这些方法变成了不同的方法。他们的调用地址在编译期就绑定了。java重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法,所以,对于重载而言,在方法调用之前,编译器就已经确定了要调用的方法,这种称为早绑定或静态绑定

而对于多态,只有等到方法调用时,执行器才会确定所要调用的具体的方法,这种称为晚绑定或动态绑定。

重载:可以使本类方法的重载,子类也可以重载父类的方法。重载的要求是方法名称相同,参数列表不同(个数不同,类型不同,顺序不同)

重写:一定是子类对父类的重写,重写要求方法的声明形式必须完全一致。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值