Java基础--面向对象(Ⅲ)


活动地址:CSDN21天学习挑战赛

Java基础–数组和面向对象(Ⅰ)
Java基础–面向对象(Ⅱ)

在这里插入图片描述

面向对象

1.类的构造方法
  • 什么是类的构造方法 ----> 一个比较特殊的方法

    • 方法名和类名相同
    • 没有void
    • 构造方法可以重载
  • 分类

    • 无参构造方法(构造器)

      public 方法名(){
          
      }
      

      注意:

      • 方法名与类名一致

      • 没写构造方法是,系统默认为无参构造方法, 但是当如果提供有参构造方法时,系统就不会在提供无参构造方法

    • 有参构造方法(构造器)

      public 方法名(参数类型 参数名,...){
          
      }
      

      注意:

      • 方法名与类名一致
  • 构造方法的目的

    • 为了类的成员相关的数据,进行初始化
      • 系统默认初始化
      • 显示初始化
  • 一个标准类(JavaBean)的写法:

    •              成员变量私有化
      
    •              提供对外的公共访问方法,setXXX()/getXXX()
      
    •              提供无参构造/ 有参构造方法 (根据需求进行判断)
      
/*学生有姓名,年龄,性别属性,行为有学习,睡觉以及玩游戏的行为,

睡觉的行为,没有返回值类型; 玩游戏的行为:有一个字符串String类型的参数 gameName

请使用面向对象方式书写学生类并且进行测试(使用标准类完成并进行测试)*/
public class Student {
    String name;
    int age;
    String sex;

    //无参构造方法
    public Student() {
    }

    //有参构造方法
    public Student(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    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 String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public void study(){
        System.out.println(name + "正在学习中......");
    }
    public void sleep(){
        System.out.println(name + "正在睡觉......");
    }
    //玩游戏的行为:有一个字符串String类型的参数 gameName
    public void game(String gameName){
        System.out.println(gameName + "正在玩游戏......");
    }
}
//测试类
public class StudentTest {
    public static void main(String[] args) {
        //无参构造方法
        Student student = new Student();
        student.setName("天天");
        student.setAge(25);
        student.setSex("女");

        System.out.println("姓名:" + student.getName() + "\n" + "年龄:" + student.getAge() + "\n"  +"性别:" +
                student.getSex());
        student.study();
        student.sleep();
        student.game("DOTA");

        System.out.println("---------------------------------------------");
        //有参构造方法
        Student student1 = new Student("向向",25,"男");

        System.out.println("姓名:" + student1.getName() + "\n" + "年龄:" + student1.getAge() + "\n"  +"性别:" +
                student1.getSex());
        student1.study();
        student1.sleep();
        student1.game("DOTA");

    }
}

2.static关键字
  • 特点
    • 被静态修饰的,随着类的加载而加载,优先于对象存在
    • 不能和this共存
    • 本身含义就是共享,共用,可以多个对象共享共用
    • 被静态修饰的成员变量或者成员方法,叫做静态变量或者静态方法
public class Person {
    //属性:姓名,年龄和国籍,先不用私有
    String name ; //姓名
    int age ; //年龄
    static String country ;// 国籍

    //永远给出无参构造方法
    public Person(){}
    //给出有参构造方法  ---带两个参数
    public Person(String name,int age){
        this.name = name ;
        this.age = age ;
    }

    //带三个参的构造方法
    public Person(String name,int age,String country){
        this.name = name ;
        this.age = age ;
        this.country = country ;
    }

    //show方法,展示这个人具体信息
    public void show(){
        System.out.println("这个人姓名是:"+name+",年龄是:"+age+",所在的国籍是:"+country);
    }
}
//测试类
public class PersonTest {
    public static void main(String[] args) {
        //测试
        //描述 古代四大美女
        Person p1 = new Person("貂蝉",25,"中国") ;
        p1.show();

        Person p2 = new Person("王昭君",21);
        p2.show();
        
        Person p3 = new Person("西施",22);
        p3.show();
        
        Person p4 = new Person("杨玉环",27);		//只有第一个输入"中国",但后面3个同样输出"中国"
        p4.show();
    }
}
  • 访问的方式:

    •  可以使用对象名来访问,但是,对于系统来说(jvm)对静态的东西:变量/方法,都是通过类名直接访问
       *      类名.变量名;
       *      类名.方法名(); 
      
  • 静态的使用场景适用于范围:

    •              简单记忆:静态只能用于访问静态
                   *                  静态方法中只能访问静态变量
                   *                  静态方法只能调用静态方法
                   *                  非静态方法皆可以访问静态的东西也可以访问非静态的东西
      
public class ArrayTool {
    //提供一个私有的构造方法,为了外界不能直接new
    private ArrayTool(){}

    public static void printArray(int[] arr){ //形式参数---引用类型,数组类型,需要传递这个数组的对象
        System.out.print("[");
        for(int x = 0 ; x <arr.length ; x ++){
            //如果x角标取到最大索引值
            if(x==arr.length-1){
                System.out.println(arr[x]+"]");
            }else{
                System.out.print(arr[x]+", ");
            }
        }
    }
}
//测试类
public class ArrayTest {
    public static void main(String[] args) { //静态只能访问静态

        //数组,静态初始化了
        int[] arr = {65,13,24,97,78} ;

        //新的访问:使用工具类名.静态方法名()
        //遍历
        ArrayTool.printArray(arr) ;
    }
}
3.javadoc注释文档(补充)
  • 对ArrayTool.java文件产生一个文档说明书 ----> 类似于API(Application Programming Interface:应用程序接口文档)
    •  使用jdk安装目录里面的bin里面: javadoc.exe 指令,产生文档说书的指令
      
    •  将ArrayTool这个java文件代码复制到本地某个磁盘上,类名和文件名称一致(先不要把package复制上去)
      
    •  打开dos窗口,进入到这个java文件的路径下(保证访问权限足够大:public)
      
    •  用javadoc  -d 目录名称 -author -version ArrayTool.java(java源文件带后缀)  产生文档说明书
      
/**
 *ArrayTool类是针对数组操作的工具类,里面包含了数组的遍历功能,求数组最值问题,
 * 获取数组的元素第一次出现索引值,冒泡排序等提供很多功能;
 * @author In-Deep
 * @version V8.0
 */
public class ArrayTool {
    private ArrayTool(){}
    /**
     * 这个方法是针对数组的遍历功能,将数组按照指定格式输出,输出格式如下:
     * [元素1, 元素2, 元素3, 元素4,....元素n]
     * @param arr 要传递的真实数组(要遍历的数组对象)
     */
    public static void printArray(int[] arr){ 
        System.out.print("[");
        for(int x = 0; x <arr.length; x++){
            //如果x角标取到最大索引值
            if(x==arr.length-1){
                System.out.println(arr[x]+"]");
            }else{
                System.out.print(arr[x]+", ");
            }
        }
    }

    /**
     * 这个方法是获取数组中的最大值;
     * @param arr 要传递数组对象,在这里面查询最大值
     * @return 返回数组中的最大值
     */
    public static int getMax(int[] arr){
        int max = arr[0];
        for(int x =1; x <arr.length; x++){
            if(arr[x]>max){
                max = arr[x];
            }
        }
        return  max;
    }

    /**
     * 这个方法是获取数组中第一次出现索引值
     * @param arr 要查询的数组
     * @param key 要查找在数组中的指定的元素
     * @return 返回的就是数组的元素第一次出现的索引值,否则,返回-1
     */
    public static int getIndex(int[] arr,int key){
        int index = -1;
        for(int i = 0; i <arr.length; i++){
            if(key == arr[i]){
                index = i;
                break;
            }
        }
        return index;
    }
    /**
     * 这个方法是对数组进行冒泡排序
     * @param arr 要将数组进行排序
     */
    public static void bubleSort(int[] arr){
        for(int x = 0; x < arr.length -1; x++){
            for(int y = 0; y < arr.length-1-x; y++){
                if(arr[y] >arr[y+1]){
                    int temp = arr[y];
                    arr[y]  = arr[y+1];
                    arr[y+1] = temp;
                }
            }
        }
    }
}
4.代码块
  • 代码块 ----> 使用{}括起来的内容

  • 分类:

    • 局部代码块,就是在方法定义中使用{}

      •      {},作用:就是限定局部变量的生命周期;
        
    • 构造代码块:—在类的成员位置定义的{}

      •      特点:在执行构造方法之前,如果类中有构造代码块,则优先执行构造代码块
             *          作用:也可以给类的成员的数据进行初始化
        
      •      只要执行构造方法,如果存在构代码块,它必须优先执行,然后才是构造方法...
        
    • 静态代码块:

      • 类就加载一次,静态代码块也就执行一次

      • 格式 ----> 跟静态相关的都和类有关系,随着类的加载而加载

        static{ 
        
        		//里面书写代码 
        
        }
        
    • 优先级:

      • 静态代码块 > 构造代码块> 构造方法,并且每次执行构造方法之前,优先执行所有的构造代码块
    //测试类
    public class CodeDemo {
        public static void main(String[] args) {
             //局部代码块
            {
                int y = 20 ;
                System.out.println(y);
            }
            
            System.out.println("----------------------------------------------") ;
            
            Code code = new Code();
            Code code1 = new Code("华为");
        }
    }
    
    class Code{
        {
            int x = 100;
            System.out.println(x);
        }
        //无参
        public Code(){
            System.out.println("code");
        }
        {
            int y = 1000;
            System.out.println(y);
        }
        //静态代码块
        static {
            int z = 10000;
            System.out.println(z);
        }
        //有参
        public Code(String brand){
            System.out.println("brand:" + brand);
        }
    }
    
5.继承
  • 将多个类的共性内容抽取出来,放在一个独立的类中,让这个独立的类和其他类产生一种关系

    • “继承” ----> 关键字 extends
  • 格式

            class 父类名{
                     共性内容:姓名,年龄.....
                     提供公共的访问方法setXXX()/getXXX()
            }
            class 子类名 extends 父类名{
                  
            }
    
  • 优点

    •          可以提高代码复用性
      
    •          可以提高代码的维护性,后期便于维护,针对子类和父类进行维护(子父关系明确)
      
    •          类与类产生的继承关系,是"多态"的前提条件
      
    •          在Java中有一个开发原则 "低耦合,高内聚"(Java设计模式都需要遵循这一个原则)
               *              耦合性:开发中是永远避免不了,可以降低(耦合:类和类的关系)
               *              内聚性:指的是某个类完成某个功能的一种能力; 尽量不要产生继承关系来完成一个功能,尽量一个类能完成一个类完成;
               *              低耦合:降低耦合性,减少类和类的关系;
      
  • 特点

    • 在Java语言中,类和的类的关系是一种继承关系,这个继承只能支持"单继承",不支持多继承

    •     class{}
          class2{}
          classextends,2{} //多继承:不支持		错
          classextends{}    //正常的语法格式		对
      
    • 类和类关系,虽然不支持多继承,但是层层单继承----> 多层继承

      //定义父类
      class GrandFather{
          public void method(){
              System.out.println("我是爷爷");
          }
      }
      //定义父类
      class Father extends  GrandFather{
          public void show(){
              System.out.println("我是父亲");
          }
      }
      //父类
      //class Mother{}
      //子类
      //class Son extends  Father,Mother{} //子类不能继承多个父类,多继承语法不支持
      class Son extends  Father{
          //自己的特有功能
          public void playGame(){
              System.out.println("会玩游戏");
          }
      }
      public class ExtendsDemo {
          public static void main(String[] args) {
      
              //创建Son类对象
              Son s = new Son() ;
              s.show();  //访问父亲的方法
              s.method();//访问爷爷的方法(method方法间接继承过来)
              s.playGame(); //访问自己的方法
          }
      

注意:

  •  子类继承父类,对于非私有的成员,直接可以继承过来,但是如果是私有成员,它可以通过公共的访问去访问,但不是直接访问的
    
  •  被私有修饰的东西(成员变量/成员方法),只能在当前类访问的
    
  • 在继承关系中,构造方法的访问问题(重点):

    • 子类继承父类,子类的所有构造方法都默认访问父类的无参构造方法

    • 为什么?

      •  子类继承父类,会用到父类的数据,需要让父类先进行初始化;   一个类初始化的---肯定需要执行构造方法的
        
    • 如果一个父类存在有参构造方法,没有无参构造方法,子类的所有构造会出现什么问题?出现了问题,怎么解决?

      • 子类的所有全部构造方法报错,子类继承父类,子类的所有构造方法都默认访问父类的无参构造方法

      • 解决方案1:

        • 手动给出无参构造方法

          	public 类名(){
                  
              }
          
      • 解决方案2:

        •  假设,人家现在就不需要让你给出父类的无参构造方法,就需要让子类的构造方法,显示的访问父类的有参构造方法 
           *      要使用关键字 <strong>super</strong>:代表父类空间标识(代表的父类对象的地址值引用)
                  *      super() :访问父类的无参构造方法
                  *      super(xxx) :访问父类的有参构造方法
                  *      这些super一定是在子类构造方法中的第一句话
          
      • 解决方案3:

        •  保证子类的所有的构造方法某一个构造方法,让父类初始化完毕即可;
          
        •  先通过子类的无参构造方法里面---this(xxx):访问本类(子类)有参构造方法
          
        •  再子类的有参构造方法的第一话:让父类初始化 super(xxx):间接访问父类的有参构造方法
          
        •  子类继承父类,一定要先执行父类的构造方法,初始化完毕之后;然后才能执行子类的构造方法---分层初始化
          

注意: 子类在隐藏了一个super(),所以先要访问父类构造方法,在执行子类,如果有super(xxx),则super()不自动创建

  • 子类继承父类,成员变量的访问问题:
    • 情况1: 子类和父类的中成员变量名称不一致,访问时,只要分别访问即可
    • 情况2: 子类和父类的成员变量名称一致,访问时:
      • 先在子类的局部位置找,有没有这个变量,如果有就使用
      • 要是没有,在子类成员位置中继续找,有没有这个变量,如果有就使用
      • 要是子类的成员位置也没有,那么会在父类的成员位置继续找,看有没有这个变量,有的话就使用
      • 如果父类的成员位置同样还没有的话,则会报错(前提:这个父类没有它的父类了),说明整个子父类中都没有变量
      • 遵循"就近原则"

如果是向上转型的时候,父类名 对象名 = new 子类名; ---- > 成员变量输出为父类的值

//父类
class Person{
    int age = 20;
}
//子类
 class Man extends Person{
    int age = 40;
}
public class Test{
    public static void main(String[] args){
        Person person = new Man();
        System.out.println(person.age); //20
    }
}

在这里插入图片描述

想要输出子类成员变量值需要用到向下转型(具体后面会分析)

  • 子类继承父类,关于成员方法的访问:

    • 情况1:子类和父类的成员方法名称不一致,调用时,只要分别调用就可以

    • 情况2:子类和父类的成员方法一模一样时(权限修饰符,返回值类型,参数列表都一样)

      • 子类将父类的方法覆盖了---->方法重写 :Override---->子类在父类的基础上,将父类的覆盖了,使用自己的功能;
      public class Person {
          //确定属性
          private String name;
          private int age;
          private String professional;
          //无参
          public Person() {
          }
          //有参
          public Person(String name, int age, String professional) {
              this.name = name;
              this.age = age;
              this.professional = professional;
          }
      
         ...
         ...
      
          //定义方法
          public void eat(){
              System.out.println("都喜欢吃");
          }
          public void show(){
              System.out.println("姓名:" + name + "\n" + "年龄:" + age + "\n" + "职业:" + professional);
          }
      }
      //子类
      public class SourthPerson extends Person{
          public SourthPerson() {
          }
      
        ...
        ...
      
          @Override //重写
          public void eat() {
              System.out.println("南方人喜欢吃大白米饭");
          }
      }
      //测试类
      public class PersonTest {
          public static void main(String[] args) {
              //无参--南方
              SourthPerson sourthPerson = new SourthPerson();
      
              sourthPerson.setName("张三");
              sourthPerson.setAge(33);
              sourthPerson.setProfessional("商人");
      
              sourthPerson.show();
              sourthPerson.eat();
              sourthPerson.favorite();
      
          }
      }
      

在这里插入图片描述

补充:

类加载的时候,内存是很快的(继承关系)

  • 父类和子类与静态相关的先执行

  • 静态的东西优先于对象存在 (类名 对象名 = new 类名() 😉

  • 静态代码块>构造代码块>构造方法…

  • 继承关系:分层初始化---->先父类初始化----然后才是子类初始化

    class Fu2{
        static{
            System.out.println("Fu2的静态代码块");//1)
        }
        public Fu2(){
            System.out.println("Fu2的无参构造方法");//4)
        }
        {
            System.out.println("Fu2的构造代码块");  //3)
        }
    }
    class Zi2 extends  Fu2{
        public Zi2(){
            System.out.println("Zi2的无参构造方法");//6)
        }
        {
            System.out.println("Zi2的构造代码块");   //5)
        }
        static{
            System.out.println("Zi2的静态代码块");    //2)
        }
    }
    
    //看程序,写结果
    public class Test {
        public static void main(String[] args) {
            //创建子类对象
            Zi2 z = new Zi2() ;
        }
    }
    

在这里插入图片描述

6.final关键字
  • final:最终的,不可被更改的,状态修饰符,被final修饰的成员方法,不能被重写,保证父类方法的安全性
class Father{
//    public  void function(){
    public final void function(){
        System.out.println("这个文件不能被修改");
    }
}
//子类继承父类
class Son extends  Father{
   public void function(){
        System.out.println("这是废弃的文件");
                                                 //这里会报错
       	//'function()' cannot override 'function()' in 'com.hwq.Father'; overridden method is final
       //被重写的方法是最终的,但是父类有了final导致不能被覆盖
}
//测试类
public class FinalDemo {
    public static void main(String[] args) {
        //创建子类对象
        Son son = new Son() ;
        son.function();
    }
}

  • 特点: 最终的,无法被修改
    • final可以修饰类,该类不能被继承
    • final修饰成员方法,此时这个方法不能被子类重写,目的是为了保证方法中某些数据的安全性
    • final可以修饰变量,此时这个变量是一个"常量",常驻内存;
      • 自定义常量:在开发中,定义一个int类型的
        • public static final 数据类型 xxx = 值;// 自定义常量: 编译时期常量,不需要加载;jvm检查语法即可

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页
评论

打赏作者

In-Deep

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值