大数据 -- java基础语法7 面向对象下

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


一、封装:隐藏类中的属性,提供公共的方法给外界
    1、private 私有,它可以修饰成员变量,构造方法,成员方法
        一个标准类1.0:
            成员变量:被private修饰
            成员方法:getXxx()和setXxx()
            show(): 遍历所有成员变量值
            

    2、this关键字
        一个标准类2.0:
        给变量名起名讲究见名知意,为了可以去调用当前对象中的成员变量,我们引出了this
        this代表的是调用方法的当前对象
        

    3、构造方法
        为了创建对象
        (1)、可以发生重载
        (2)、可以给成员变量进行初始化值
        一个标准类的3.0:
          成员变量:使用private关键字修饰
          构造方法:一个无参构造方法/一个带所有参数的构造方法
          成员方法:getXxx()/setXxx() ..
          show(): 遍历所有的成员变量值
          

    4、static
        可以被所有类的对象共享的成员,使用static修饰
        特点:可以直接通过 类名.静态成员 的方式调用
            随着类的加载而加载的,也称之为类成员,类本身的
二、继承: extends关键字
    多个类中存在相同的属性和行为时,将这些内容抽取到一个单独的类中,那么多个类就无需再定义这些属性和行为,只要继承那个单独类即可。
    1、定义语句格式
        class A{}
        class B extends A{}
        B称之为子类,或者派生类
        A称之为父类,超类或者基类

class Father {
    //这些都是共有的属性
    String name;
    int age;

    public void study() {
        System.out.println("学习");
    }

    public void eat() {
        System.out.println("吃饭");
    }

    //这是父类特有的方法
    public void show1() {
        System.out.println("我是父类");
    }
}

//子类通过extends关键字实现对父类的继承,获取父类的共有属性
public class Son extends Father {

    //子类也可以定义自己特有的方法
    public void show2() {
        System.out.println("我是子类");
    }
}


    2、继承的好处:
        (1)、提高了代码的复用性
        (2)、提高了代码的维护性 -- 只需要修改父类的内容
        (3)、让类与类之间产生了继承关系,为了后面多态做铺垫(要有继承才能有多态)

       继承的坏处:
            类的耦合性增强了。(内聚)


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

                耦合:类与类之间的关系
                内聚:类自己本身可以完成的事情
                

    3、java中类只支持单个继承,不支持一次继承多个类,但是可以多层继承。

class Father{
    private String name;
    private int age;
        
    public void eat(){
        System.out.println("吃饭");
    }
}
    
class Mother{
    private String name;
    private int age;
        
    public void eat(){
        System.out.println("吃饭");
    }
}
    
//错误,类不支持多继承
public class Son extends Father , Mother{
}
//类支持多层继承
class Grandpa{
}

class Father extends Grandpa{
}

public class Son extends Father{
}


    4、使用继承时所需要的注意事项:
        (1)、要想初始化子类,必须先初始化父类。(通过子类构造方法默认的第一句话:super() 完成对父类的初始化)
        (2)、子类只能继承父类的非私有的成员(成员变量和成员方法)。
        (3)、子类不能继承父类的构造方法,但是可以通过super关键字去访问父类的构造方法。
          为什么要访问父类的构造方法呢?
                 因为子类会继承父类的数据, 甚至可能会使用父类的数据, 所以在子类初始化之前, 一定会先完成父类的初始化。
           注意:
                 每个子类的构造方法的第一句话默认是super(),但一般隐藏不写。
        (4)、不要为了部分的功能而去使用继承。
                 当两个类满足语法“什么是什么”的时候,就可以使用继承了。

                 例如:苹果是水果、小猫是动物等。
                
    
    5、继承与成员变量之间的关系:
        (1)、当子类中的成员变量与父类中的成员变量名字一样的时候:
               查找:(就近原则)
                1)先在子类方法的局部范围内进行查找,如果找到就返回。
                2)如果在子类方法局部范围内找不到,去子类成员位置上查找,如果找到就返回。
                3)如果在子类成员位置上找不到,去父类成员位置上查找,如果找到就返回。
                4)如果在父类成员位置上找不到,报错。(不考虑父类的父类)
        (2)、当子类中的成员变量与父类中的成员变量名字不一样的时候,使用什么变量名,就访问谁。
      继承与成员方法之间的关系:
        (1)、当子类的成员方法名与父类成员方法名不一样的时候,该调用谁就调用谁的
        (2)、当子类的成员方法名与父类成员方法名一样的时候,怎么办呢?(就近原则)
                1)先在子类中查找,如果有就调用,如果没有去父类中查找。
                2)如果父类中有方法,就调用父类的。
                3)如果连父类中都没有要调用的方法名,报错,提示找不到方法。(不考虑父类的父类)
                
    
    6、super关键字,子类想要访问父类的成员时,用super关键字。
          super的用法和this很像:
                  this代表本类对应的引用,可以访问本类非私有成员变量、构造方法、成员方法。
                  super代表父类存储空间的标识(父类引用),可以访问父类非私有成员变量、构造方法、成员方法。
      
        (1)、访问成员变量
                this.成员变量  : 访问的是本类中的成员变量
                super.成员变量 : 访问的是父类中的成员变量
        (2)、访问构造方法
                this()/this(...)      ... : 访问本类带参构造方法
                super()/super(...)     ... : 访问父类带参构造方法
        (3)、访问成员方法
                this.成员方法()
                super.成员方法()
            
        super(..)或者this(..)必须出现在构造方法第一条语句上。
                 当super、this都出现在第一排,就会让父类的数据进行多次初始化。
              (重点)每个类只能初始化一次。    

class Father {
    int num = 10;
    
    Father(){
    }
    
    Father(int num){
        this.num = num;
    }

    public void show2() {
        System.out.println("这是父类中的show2方法");
    }
}

class Son extends Father {
    int num = 20;
    
    Son(){
    }
    
    Son(int num) {
        super(num);     //访问的是父类的带参构造方法
        //this();       //调用了本类中的无参构造方法
    }

    public void show() {
        int num = 30;
        System.out.println(num);      // 访问的是方法中的成员变量  num = 30
        System.out.println(this.num); // 访问的是本类中的成员变量  num = 20
        System.out.println(super.num);// 访问的是父类中的成员变量  num = 10
        
        
        super.show2();      //调用父类中的show2方法

        this.show3();       //调用子类(Son类)中的show3方法
    }

    public void show3() {
        System.out.println("这是Son类中的show3方法");
    }
}


    7、方法重写: 重写现象是发生在继承的关系中。
        子类中出现了和父类中一模一样的方法声明,也被称为方法覆盖,方法复写。

        方法重写的使用特点:
            如果方法名不同,就调用对应的方法。
            如果方法名相同,最终使用的是子类自己的。

        方法重写的注意事项:
            (1)、父类中私有的方法(private)不能被重写。
            (2)、子类重写父类的方法时候,访问权限不能更低。
                要么子类重写的方法访问权限比父类的访问权限要高或者一样。
            (3)、父类中静态的方法不能被重写,因为静态的是属于类本身的东西。

class OldPhone {
    //将父类中的静态成员看作一个全局共享的,被所有的子类共享
    public static int a = 10;

    private String name;

    public void call(String name) {
        System.out.println("打电话给" + name);
    }

    public static void play() {    //该方法被static静态修饰,不能被子类重写
        System.out.println("玩俄罗斯方块");
    }
}

class NewPhone extends OldPhone {
    public void fun(){
        a = 200;                    //可以访问到父类的声明的a
        System.out.println(a);      //a = 200
    }

    @Override
    public void call(String name) {    //重写了父类的call方法
        //super.call(name);
        System.out.println("一边打电话给" + name+",一边看抖音。");
    }

    //@Override
    public static void play() {     //相当于定义了一个本类的静态方法,只是方法名与父类一样
        System.out.println("玩王者荣耀");
    }

}

      
    8、final关键字:
        final:最终的意思。它可以修饰类、成员变量、成员方法。
        
        特点:
            (1)、修饰类: 类不能被继承
            (2)、修饰成员变量: 变量变自定义常量,并且只能赋值一次,在构造方法完毕之前赋值即可。
         常量分为:
                1)字面值常量
                2)自定义常量: 被final修饰变量变成自定义常量
                3)final修饰成员方法: 方法不能被重写


        final修饰局部变量:
            (1)、在方法内部,修饰基本数据类型的变量,变量值只能赋值一次,之后不能再发生改变。
            (2)、final修饰引用数据类型的变量,引用的地址值不可以发生改变,但是该对象的堆内存中的值是可以发生改变的。
            
        final修饰变量的初始化时机:
               在对象构造完毕前即可。

final class Fu{   //该类不能被继承
} 
class Fu {
    final int num = 100;    
    //num = 200;       //num值不能再被修改
    
    public final void show() {       //该方法不能被子类重写
        System.out.println("这是父类中的show方法");
    }
}

class Zi extends Fu {
    int n = 20;

//    @Override
//    public void show(){        //不能重写父类的show()方法
//        System.out.println("这是子类中的show方法");
//    }
}

    
//测试类
public class FinalDemo {
    public static void main(String[] args) {
    
        final Zi zi = new Zi();
        zi.n = 1000;    //引用的对象的堆内存中的值是可以发生改变的
        System.out.println(zi.n);
        //zi = new Zi();    //但是引用的地址值不可以发生改变
    }
}

 
三、多态
        某一事物,在不同时刻表现出来的不同状态。
        
        举例:
            水:                                              
            固态、液态、气态                                  
            固态的水是水、液态的水也是水、气态的水也是水      
        
            水果:
            波罗蜜、香蕉、榴莲
            波罗蜜是水果、香蕉是水果、榴莲是水果
            
    1、多态的前提(缺一不可):
        (1)、要有继承关系。
        (2)、要有方法的重写。
        (3)、要有父类的引用指向子类的对象(向上转型)。

父类名 f = new 子类名(...);

    2、多态访问成员的特点:
        (1)、成员变量
                    编译看左,运行看左。
        (2)、构造方法
                     创建子类对象的时候,先访问父类中的构造方法,对父类的数据先进行初始化。
        (3)、成员方法
                     编译看左,运行看右
                     因为成员方法存在重写,所以访问看右边。
        (4)、静态成员方法
                     编译看左,运行看左
                     由于被static修饰的成员都是与类相关的,这里不是重写,所以运行的时候,访问的还是左边的。
    
   何为编译看左,运行看右?

//用多态创建了一个对象
Fu fu = new Zi();     //以赋值符"="为界限,分为左右两边;

//调用show方法,运行结果:编译看左,运行看右
fu.show();      //编译看左:查看赋值符"="左边Fu类有没有show()方法,有就通过编译
                //运行看右:查看赋值符"="右边Zi类有没有show()方法,有就运行输出右边Zi类show()方法中的内容。


    3、多态的好处:
        (1)、多态可以使代码的扩展性很好。(这是由继承所保证的)
        (2)、多态可以使代码的维护性很好。(这是由多态保证的)        

       多态的弊端:不能访问子类特有的方法。
            解决方案:使用向下转型。
            
            
    4、对象之间转型的问题:
        (1)、向上转型

Fu f = new Son();

        (2)、向下转型

Son s = (Son)f;      //类似于类型强转: byte b  = (byte)10;

        向下转型需要注意的一个问题:
            要求转型的类与父类引用存在继承关系,并且一开始创建多态的时候,使用的是该类。      

class Fu {
    int num = 100;

    public void show() {
        System.out.println("这是父类中show()方法");
    }

    public static void fun() {
        System.out.println("这是父类中的静态fun方法");
    }
}

class Zi extends Fu {
    int num = 1000;

    @Override
    public void show() {       //重写了父类的show方法
        System.out.println("这是子类中的show()方法");
    }

    public void show2() {      //多态的向上转型无法访问子类特有的方法 ,但是向下转型可以
        System.out.println("这是子类特有的方法1");
    }

    public static void fun() {
        System.out.println("这是子类中的静态fun方法");
    }

}


//测试类
public class DuoTaiDemo1 {
    public static void main(String[] args) {
        //用多态创建了一个对象(向上转型)
        Fu fu = new Zi();
        System.out.println(fu.num);   //编译看左,运行看左    100

        fu.show(); //编译看左,运行看右    这是子类中的show()方法
        fu.fun();  //编译看左,运行看左    这是父类中的静态fun方法


        //向下转型创建对象
        Zi zi = (Zi)fu;
        zi.show2();  //这是子类特有的方法1
        zi.show();   //这是子类中的show()方法
    }
}    

    

    5、抽象类:abstract关键字,它可以修饰类、方法。
    
        (1)、抽象类和抽象方法都要用一个关键字修饰:abstract
                修饰一个类: 放在class的前面。

abstract class Animal2{
}


                修饰一个方法: 一般是放在权限修饰符后面。抽象方法没有方法体{},连大括号都没有,直接以分号结尾。

public abstract void eat(); 


        (2)、有抽象方法的类一定要是抽象类,抽象类不一定要有抽象方法。抽象类中既可以存在抽象方法,也可以存在有方法体的方法。
        (3)、抽象类不能被实例化。
                通过多态的形式,使用具体的子类去实例化调用方法,专业术语称之为:抽象多态。
        (4)、如果继承抽象类的是一个具体的子类,需要重写该抽象类中所有的抽象方法,或本身也是一个抽象类。
                如果继承抽象的也是一个抽象类,可以不去重写父类中的抽象方法,也可以选择性的去重写。
                
 抽象类的成员特点:
        (1)、成员变量:
                既可以是变量,也可以是常量。
        (2)、构造方法:
                可以存在构造方法,但抽象类不能被实例化,所以这里构造方法是提供初始化父类的作用。
        (3)、成员方法:
                可以是抽象方法,但是具体的子类必须要重写该方法。
                也可以不是抽象方法,提高代码的复用性。

abstract class Animal{    //定义一个抽象类
    int a = 20;            //可以有变量
    final int b = 100;     //也可以有常量

    Animal(){             //可以有构造方法
        System.out.println("这是Animal类中的无参构造方法");
    }

    public abstract void eat();  //可以有抽象方法

    public void show(){          //也可以有普通方法
        System.out.println("父类中不是抽象方法的show方法");
    }
}

//非抽象类继承抽象类需要重写其所有的抽象方法
class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }
}

//或本身就是抽象类继承抽象类不需要重写抽象方法,或选择性的重写其抽象方法
abstract class Cat extends Animal{
} 


abstract关键字不能和哪些关键字共存?
        (1)、 private
        (2)、 static
        (3)、 final

abstract class Animal{

    // private 和 abstract 关键字冲突
    //private abstract void show2();

    // static 和 abstract 关键字冲突
    //static abstract void show3();

    // final 和 abstract 关键字冲突
    //final abstract void show4();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值