美文网首页
类与对象(2) - Class、Object

类与对象(2) - Class、Object

作者: 浪迹一生 | 来源:发表于2017-07-16 12:58 被阅读0次

    继承

    1、定义

    在Java中定义一个类时,让该类通过 extends 关键字继承一个已经存在的类,同时能够将被继承的父类中设定好的属性和方法直接拿过来使用,这就是类的继承。
    (1)被继承的类叫做父类(基类),新的类叫做子类(派生类)。
    (2)子类可以继承父类的所有属性和方法,同时也可以增加属于自己的属性和方法。
    (3)在继承时,子类不能够继承父类的构造方法,也不能继承父类的私有属性和私有方法。

    2、语法格式

    [ 修饰符 ] class 子类名 extends 父类名 { }

    //父类
    public class Father {
        String name;
        int age;    
        public Father(String name,int age){
            super();
            this.name = name;
            this.age = age;
        }
        public Father(){
            System.out.println("new Father...");
        }
            public void eat(){
            System.out.println(this.name+"正在吃东西");
        }
        public void sleep(){
            System.out.println(this.name+"正在睡觉");
        }   
    }
    //子类
    public class Son extends Father{
    
        public Son(){
            System.out.println("new Son...");
        }
            public void eat(){
            System.out.println(t"正在吃东西");
        }
        public void sleep(){
            System.out.println("正在睡觉");
        }   
    }
    

    3、规则和优点

    (1)Java中只支持单继承,也就是说每个子类只能有一个父类,不能有多继承。
    (2)一个父类可以有多个子类。
    (3)子类继承父类的所有属性和方法,同时也可以增加属于自己的属性和方法。
    (4)不能继承 private 修饰的属性和方法。
    (5) 在Java中任何的class都有一个父类 Object 类。
    ——Object类是所有class的父类。
    ——Java中只允许单继承。
    ——若手动添加指定父类,则系统不会默认Object为该class的父类。
    ——若没有继承任何父类,则系统默认Object为其父类。
    (6) 优点:使编码更高效,可以代码重用。

    4、子类实例化的过程

    (1)子类实例化时要先实例化它的父类,然后在实例化子类。
    (2)要先调用父类的构造方法,父类的构造方法运行完毕后,才能调用子类的构造方法。
    (3)子类的构造器——子类不能够继承父类的构造器;
    ——在子类中创建构造器时,必须调用父类的构造器;
    ——子类可以在自己的构造器中使用 super 关键字来调用父类的构造器;
    —— 如果使用super关键字调用父类的构造器,必须写在子类构造器的第一行;
    —— 如果调用的是父类的无参构造器,可以不用写super();
    —— 如果子类调用了父类的无参构造器,而父类中没有无参构造器,则编译器提示错误。

    super(参数1,参数2,...);
    

    5、super 和 this 关键字

    (1)super()
    —— 作用:调用父类的构造器;
    —— 只能出现在子类的构造器中,且必须是放在第一行;
    —— super()中的参数,决定了要调用父类的哪个构造器;
    —— 如果子类构造器中没有出现 super ,那么编译器会默认加上super(),即调用父类的空构造器,如果父类没有空构造器,编译器提示错误。
    (2)this()
    —— 作用:调用本类的构造器;
    —— 只能写在构造器的第一行;
    (3)在同一个构造器中 super()和 this()不能同时出现。
    (4)super:指向父类的引用;this:指向本类的引用。

    //父类
    public abstract class Shape {
        private double area;
        private double per;
        private String color;
        public void setArea(double area) {
            this.area = area;
        }
        public void setPer(double per) {
            this.per = per;
        }
        public void setColor(String color) {
            this.color = color;
        }   
        public Shape() {
            super();
        }
        public Shape(String color){
            super();
            this.color = color;
        }
        public String getColor(){
            return color;
        }
        public abstract double getArea();
        public abstract double getPer();
        public abstract void showAll(); 
    }
    //子类
    public class Rectangle extends Shape{
        private int width;
        private int height; 
        public int getWidth() {
            return width;
        }
        public void setWidth(int width) {
            this.width = width;
        }
        public int getHeight() {
            return height;
        }
        public void setHeight(int height) {
            this.height = height;
        }
        public Rectangle() {
            super();
        }   
        public Rectangle(int width, int height,String color) {
            super(color);    //调用父类的有参构造方法
            this.width = width;
            this.height = height;
        }
        @Override
        public double getArea() {
            double area = width*height;     
            return area;
        }
        @Override
        public double getPer() {
            double per = (width+height)*2;  
            return per;
        }
        @Override
        public void showAll() {
            System.out.println("Rectangle的长度是:"+width);
            System.out.println("Rectangle的宽度是:"+height);
            System.out.println("Rectangle的面积是:"+getArea());
            System.out.println("Rectangle的周长是:"+getPer());
            System.out.println("Rectangle的颜色是:"+getColor());
        }
    }
    //测试类
    public class Test {
        public static void main(String[] args) {
            Rectangle rectangle = new Rectangle(4,5,"black");
            rectangle.showAll();
        }
    }
    
    
    

    访问权限修饰符

    1、封装

    封装就是把客观事物封装成抽象的类,把对象的属性和行为结合在一个独立的类中,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
    隐藏属性、方法或实现细节的过程称为封装。
    <1>封装可以隐藏实现细节,使得代码模块化。
    <2>让使用者只能通过事先制定好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作。
    <3>便于修改,增强代码的可维护性。
    <4>封装的目的是实现代码重用。

    2、访问权限修饰符

    Java有四个作用域,访问权限修饰符 ----- 适用于类和属性
    (1)public(公有)-----任何位置都可以访问
    (2)protected(受保护的)-----在同一个包中的所有类都可以访问,以及该类的子类(可以是不同包)
    (3)default(默认的)-----在同一个包中
    (4)private(私有的)-----只能在本类中

    用来控制类的成员和类的使用范围。
    ——类成员的访问权限修饰符:public、protected、default、private
    ——类的访问权限修饰符:public、default

    方法的覆盖(重写) —— override

    方法的覆盖、重写:子类对从父类继承过来的方法进行改造,重新编写。
    ——在子类继承父类时发生。

    1、规则

    在子类中的覆盖(重写)方法和父类中被覆盖(重写)的方法应具有:
    <1>相同的方法名
    <2>相同的参数列表(参数数量、参数类型、参数顺序都要相同)
    <3>相同的返回值类型
    <4>子类覆盖(重写)方法的访问权限要不小于(大于等于)父类中被覆盖(重写)方法的访问权限。

    //父类
    public class Father {
        String name;
        public void eat(){
            System.out.println("正在吃东西");
        }
        protected String run(){
            return "跑步";
        }
    }
    
    //子类
    public class Son extends Father{    
        String name;
    //方法重写,返回值类型必须相同
    //  public int eat(){
    //      System.out.println("吃东西");
    //      return 0;
    //  }
        //方法重写,子类的访问权限要不小于(大于等于)父类的访问权限
        public String run(){
            return "跑步";
        }
    }
    

    方法的覆盖(重写)(override) 和方法重载(overload)的区别

    方法的覆盖、重写 方法重载
    重写发生在两个有继承关系的class中 重载发生在一个class中
    重写中方法名和参数列表必须完全相同 重载中方法名相同,但参数列表不同
    方法重写,返回值类型必须相同 方法重载,与返回值类型无关
    子类覆盖(重写)方法的访问权限要不小于(大于等于)父类中被覆盖(重写)方法的访问权限。 方法重载,可以有不同的访问修饰符

    引用数据类型的转换

    1、向上转换(Upcasting)——子类转换成父类,自动转换;
    ——前提是:具有继承或实现关系;
    ——向上转换损失了子类新扩展的属性和方法,只可以使用从父类中继承的属性和方法。
    2、向下转换(Downcasting):强制转换
    ——将父类对象显示的转换成子类类型;

    //在创建出这个对象(引用)时,该对象的类型是子类
    PrintMechine print1 = new HeibaiPrint();
    print1.print();
    
    //非基本数据类型,大转小,也强转
    //在创建出这个对象时,该对象的类型是子类
    //例如:print1 在实例化时是new HeibaiPrint()
    HeibaiPrint heibaiPrint = (HeibaiPrint)print1;
    heibaiPrint.print();
    
    //创建父类,然后直接将父类转换成子类是不可行的
    

    instanceof运算符

    1、 判断某个变量的数据类型(小范围)是否符合某个大范围的数据类型
    ——变量 instanceof 数据类型
    2、判断某个对象(引用)是否属于某个类的一个实例。
    ——对象 instanceof 类
    3、它的返回值数据类型是 boolean 型。

    public class PrintMechine {
        public void print(){    }
    }
    public class CaisePrint extends PrintMechine{
        @Override
        public void print() {
            System.out.println("打印出的纸张是彩色的");       
        }
    }
    public class HeibaiPrint extends PrintMechine{
        @Override
        public void print() {
            System.out.println("打印出的纸张是黑白色的");
        }   
    }
    public class SanDPrint extends PrintMechine{
        @Override
        public void print() {
            System.out.println("打印出的纸张是3D的");       
        }
    }
    public class Test01 {
        public static void main(String[] args) {
            //instanceof:判断某个对象或引用是否属于某个类
            //          判断某个变量的数据类型(小范围)是否符合某个大范围的数据类型
            
            //父类的引用 print1 的类型是父类类型
            PrintMechine print1 = new PrintMechine();
            //父类的引用 print2 的类型是子类类型
            PrintMechine print2 = new HeibaiPrint();
            
            //print2 变量能够转换成 HeibaiPrint 类型吗
            if (print2 instanceof HeibaiPrint) {
                HeibaiPrint heibaiPrint2 = (HeibaiPrint) print2;
                heibaiPrint2.print();
            }
            
            if (print1 instanceof HeibaiPrint) { //false:不运行方法体
                //(HeibaiPrint) print1:将父类类型强制转换成子类类型
                HeibaiPrint heibaiPrint3 = (HeibaiPrint) print1;
                heibaiPrint3.print();
            }       
    //java.lang.ClassCastException :类型转换异常  
        }
    }
            
    

    多态 --- Polymorphism

    多态:多形性,父类型引用指向子类型的实现,动态改变行为。一个class,随着不同的场景,它的表现形态,会随之发生变化。
    多态是具有表现多种形态的能力的特征。
    同一个实现接口,使用不同的实例而使用执行不同的操作。

    (1)多态的实现条件:
    <1>父类的引用,引用派生类(子类)的实例:
    <2>父类的引用,调用重写后的方法
    <3>在运行调用时形成多态
    <4>条件:(1)继承 (2)方法重写 (3)类型转换

    (2)多态的目的是实现接口重用
    (3)多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。
    (4)多态的优点:
    —— 简化代码;
    —— 改善代码的组织性和可读性;
    —— 易于扩散

    public class PrintMechine {
        public void print(){    }
    }
    public class CaisePrint extends PrintMechine{
        @Override
        public void print() {
            System.out.println("打印出的纸张是彩色的");       
        }
    }
    public class HeibaiPrint extends PrintMechine{
        @Override
        public void print() {
            System.out.println("打印出的纸张是黑白色的");
        }   
    }
    public class SanDPrint extends PrintMechine{
        @Override
        public void print() {
            System.out.println("打印出的纸张是3D的");       
        }
    }
    public class Test {
    
        public static void main(String[] args) {
            //多态
            //父类的引用,引用子类的实例
            //父类的引用,调用子类重写后的方法
            //在运行调用的同时形成多态
            //条件:(1)继承 (2)方法重写 (3)类型转换
        
            //在创建出这个对象(引用)时,该对象的类型是子类
            PrintMechine print1 = new HeibaiPrint();
            print1.print();
            PrintMechine print2 = new CaisePrint();
            print2.print();
            PrintMechine print3 = new SanDPrint();
            print3.print();
            
            //非基本数据类型,大转小,也强转
            //在创建出这个对象时,该对象的类型是子类
            //例如:print1 在实例化时是new HeibaiPrint()
            HeibaiPrint heibaiPrint = (HeibaiPrint)print1;
            heibaiPrint.print();
            
            //创建父类,然后直接将父类转换成子类是不可行的        
        }
    }
    
    //创建一个调用方法      父类             引用名
    public static void print(ObjectDemo   demo){
        //父类的引用调用重写后的方法
        //父类的引用.重写后的方法()
        if (demo.getAge() > 20) {
            System.out.println("老张的大儿子叫:" + demo.getName() + " 今年" + demo.getAge() );
        }
        if (demo.getName().equals("zhangyusheng")){
            System.out.println("老张的二儿子叫:" + demo.getName() + " 今年" + demo.getAge());
        }
    }
    //运行调用方法 
    public static void main(String[] args){
    //父类的引用,引用派生类(子类)的实例:父类  引用 = new 子类();
        ObjectDemo demo = new SonDemoA();
    //父类的引用调用重写后的方法:引用.重写后的方法();  例如:demo.getName();        
        System.out.println(demo.getName());
        System.out.println(demo.getAge());
        System.out.println("==================================");
        //在运行调用时形成多态
        print(new SonDemoA());
        System.out.println("==================================");   
        print(new SonDemoB());
        System.out.println("==================================");
        }
    }
    //父类
    class ObjectDemo{
        public int getAge(){
            return 50;
        }
        public String getName(){
            return "zhangsan";
        }
    }
    //子类继承父类,重写父类的方法
    class SonDemoA extends ObjectDemo{
        //override:方法重写
        public int getAge(){
            return 25;
        }
        public String getName(){
            return "zhangxueyou";
        }
    }
    class SonDemoB extends ObjectDemo{
        public int getAge(){
            return 18;
        }
        public String getName(){
            return "zhangyusheng";
        }
    }
    

    抽象类 —— abstract class

    abstract:抽象
    abstract class:抽象类:有抽象方法的类就是抽象类。

    1、语法格式

    [ 访问权限修饰符 ] abstract class 类名 { ... }

    2、抽象方法

    抽象方法:只有方法声明,没有方法实现(方法体)的方法。

    [ 访问权限修饰符 ] abstract 返回值类型 抽象方法名(参数列表);

    //abstract  class :抽象类
    public abstract class Animal {//抽象类:有抽象方法的类就是抽象类。抽象类中也可以有普通方法
    
        String name;
        //构造方法
        public Animal(String name){
            this.name = name;
        }
        
        //非抽象方法
        public void sleep(){
            System.out.println("睡觉");
        }
        
        //抽象方法
        //abstract仅仅是对方法的一个声明,并没有具体实现
        public abstract void eat();
        public abstract void play();
    }
    
    

    3、规则

    (1)抽象类不能够被实例化 ———— instantiate:实例化,示例
    (2)抽象类中有构造方法。
    (3)抽象类中也可以有普通方法。
    (4)抽象类中的抽象方法必须在它的子类中被实现,否则该子类只能声明为 abstract 。
    (5)抽象方法必须被子类覆盖(重写),抽象方法不能够为 private。
    (6)不能够将构造方法、类成员方法声明为抽象方法。
    (7)abstract 抽象方法不能够和 static 同用。

    4、使用抽象类的情况

    (1)当一个类的一个或多个方法是抽象方法时;
    (2)当一个类是抽象类的子类,并且没有实现父类的所有抽象方法时,即只实现了部分;
    (3)当一个类实现接口,并且不能够为所有抽象方法都提供实现时;


    final 关键字

    final 关键字可以修饰的元素
    1、类:final 修饰的类不能够被继承;
    2、变量:final 修饰的变量不能够被重新赋值;
    ——在声明时直接赋值,或者在构造器中赋值。
    ——系统不会对final 属性默认的赋初始值。
    3、方法:final 修饰的方法不能够在子类中被覆盖(重写),即不能够进行修改。并且不能够被子类继承。


    接口 —— interface

    1、接口的声明

    ——是方法的定义和常量值的集合。
    ——关键字:implements:实现 。
    ——接口中只有常量和抽象方法,没有变量和方法的实现。

    [ 访问权限修饰符 ] interface 接口名 { 接口的成员 }

    ——接口成员:常量、抽象方法
    ——接口可以多实现。

    public interface InterfaceDemo {
    
        //在接口中不能够声明变量,也不能够定义普通方法
            
    //  int a;
    //  int b;
    //  public void a(){ }
    //  public void b(){ }
    //  在接口中不能够声明变量,也不能够定义普通方法    
    //  接口中定义的属性必须是 public static final  (常量)
    //  接口中定义的方法必须是 public abstract
    //  接口中属性必须都是常量。
    //  接口中方法必须都是抽象方法。
        
        int a = 0;  //接口中属性默认为public static final 
        public static final int b = 100;
        public abstract void a();
        public abstract void b();
    }   
    

    2、注意

    (1)接口不是一个类,没有构造器,不能够被实例化。
    (2)接口使用 interface 关键字来定义,而不是class。
    (3)接口中定义的属性必须是 public static final —— 常量
    (4)接口中定义的方法必须是 public abstract —— 抽象方法
    (5)在接口中不能够声明变量,也不能够定义普通方法 。
    (6)子类可以实现多个接口,在接口之间用“,”分隔写多个接口名。
    (7)如果不想实现接口,在实现类中加 abstract 修饰符将类抽象化。

    //接口1
    public interface Temp {
        public static final int a = 0;
        public static final int b = 100;    
        public abstract void a();
        public abstract void b();
    }
    //接口2
    public interface Temp2 {
        public static final int x = 10;
        public static final int y = 20;
        public abstract void x();
        public abstract void y();
    }
    //接口的实现类 Impl
    public class TempImpl implements Temp,Temp2{
        @Override
        public void a() {
            System.out.println("A");
        }
        @Override
        public void b() {
            System.out.println("B");
        }
        @Override
        public void x() {
            System.out.println("X");
        }
        @Override
        public void y() {
            System.out.println("Y");
        }
    }
    //接口的测试类
    public class TempTest {
        public static void main(String[] args) {
            TempImpl tempImpl = new TempImpl();
            tempImpl.a();
            tempImpl.b();
            System.out.println(tempImpl.a);
            System.out.println(tempImpl.b);
            tempImpl.x();
            tempImpl.y();
            System.out.println(tempImpl.x);
            System.out.println(tempImpl.y);
        }
    }
    
    

    3、接口的意义

    (1)接口可以实现方法的定义和方法的实现相分离,降低模块间或系统间的耦合性。
    (2)接口可以实现多继承。

    4、接口和类的关系

    ——类实现接口:关键字:implements:实现 。
    (1)若想要实现一个接口,必须要编写实现接口的类 Impl 。
    (2)如果一个类想要实现一个接口,那么这个类就必须实现这个接口中所有的抽象方法。否则这个类只能声明为抽象类。
    (3)多个无关的类可以实现一个接口,一个类可以实现多个无关的接口。
    (4)一个类可以在继承一个父类的同时,实现一个或多个接口。


    接口和抽象类的区别

    接口 抽象类
    接口是一个接口 - interface 抽象类是一个类 - class
    接口可以多实现 抽象类只能是单继承
    接口中必须全部都是抽象方法 抽象类中可以有非抽象方法,包括抽象方法,构造方法,普通方法
    接口中定义的抽象方法必须是 public abstract 抽象类中抽象方法的访问权限修饰符可以是public、protected、default
    接口中定义的属性必须是 public static final 常量 抽象类中可以有普通变量和静态变量(static)
    接口中没有构造方法 抽象类中有构造方法

    内部类

    1、内部类——就是定义在另一个类内部的类。
    2、注意
    (1)内部类可以访问其外部类所有的属性和方法。
    (2)无需创建外部类对象,即可从内部类访问外部类的属性和方法。
    (3)必须创建内部类的对象,否则无法从外部类访问内部类的属性和方法。
    (4)如果内部类有和外部类重名的属性或方法,则内部类的属性或方法会优先使用。
    (5)不能够定义static变量。
    (6)先创建好外部类,通过外部类的对象(引用)才能创建内部类。

    //如果内部类有和外部类重名的属性或方法,则内部类的属性或方法会优先使用。
    public class OuterClass2 {
    
        int outer = 100;
        double x =3.14;
        //内部类
        class InnerClass2{
            int inner = 200;
            double x = 3.1415926;
            public void showOuter(){
                System.out.println(outer);//外部类变量
                System.out.println(x); //内部类变量优先级高
                //访问变量同名的外部类变量
                System.out.println(OuterClass2.this.x);
            }
        }
        public void showInner(){
            InnerClass2 innerClass2 = new InnerClass2();
            innerClass2.showOuter();
        }
        public static void main(String[] args) {
            OuterClass2 outerClass2 = new OuterClass2();
            outerClass2.showInner();
        }
    }
    

    3、内部类的访问权限修饰符
    ——普通类的访问权限修饰符:public、default
    ——内部类的访问权限修饰符:public、protected、default、private

    4、内部类的访问
    —先创建好外部类,通过外部类的对象(引用)才能创建内部类
    OuterClass outerClass = new OuterClass(); //实例化外部类
    InnerClass innerClass = outerClass.new InnerClass(); //实例化内部类

    public class OuterClass {
    
        int a;
        public void add(){
            System.out.println("OuterClass=add");
        }
        //内部类
        class InnerClass{
            int b;
            public void add(){
                System.out.println("InnerClass=add");
            }
        }
        
        public static void main(String[] args) {
            //先创建好外部类,通过外部类的对象(引用)才能创建内部类
            OuterClass outerClass = new OuterClass();
            outerClass.add();
            //通过外部类的对象(引用)创建内部类
            InnerClass innerClass = outerClass.new InnerClass();
            innerClass.add();
        }
    }
    

    5、静态内部类
    ——用 static 标识的内部类为静态内部类
    (1)静态内部类作为外部类的静态成员,不能访问外部类非静态成员。
    (2)非静态内部类只能定义非静态成员,而静态内部类可以定义静态成员和非静态成员。
    (3)使用 OuterStatic.InnerStatic in = new OuterStatic.InnerStatic() 方式实例化静态内部类。

    //静态内部类
    public class OuterStatic {
    
        int outer = 100;
        static int outer2 = 300;
        static class InnerStatic{
            static int a;
            int inner = 200;
            public void showOuter(){
                //System.out.println(outer);
                System.out.println(outer2);
            }
        }
        public void showInner(){
            InnerStatic innerStatic = new InnerStatic();
            System.out.println(innerStatic.inner);
        }
        public static void main(String[] args) {
            //创建外部类
            OuterStatic outerStatic = new OuterStatic();
            //创建静态内部类
            OuterStatic.InnerStatic in = new OuterStatic.InnerStatic();
            in.showOuter();
        }
    }
    

    相关文章

      网友评论

          本文标题:类与对象(2) - Class、Object

          本文链接:https://www.haomeiwen.com/subject/bpyghxtx.html