zoukankan      html  css  js  c++  java
  • Java入门(一)——类、抽象类和接口

    Java是一门面向对象语言,可以看出“对象”在Java有着举足轻重的位置。那么,“对象”从何而来呢?那必须是丈母娘造出来的,下面我们就先来说说这个丈母娘——类。

    Java类

    • 对象: 对象具有状态和行为。 例如:一只狗的状态有:颜色,名称,品种,它的行为有:摇尾巴,吠叫,吃东西。 对象是类的实例
    • 类: 类是一个模板,它描述一类具有相同状态和行为的对象。比如人类,都具有思考这个行为,而植物没有。

    类可以看成是创建Java对象的模板,下面简单定义一个类:

    public class People{
      String name;  // 成员变量
      int age;
      String weight;
      static final double weeks = 9.5;  // 类变量
      void eat(){
      }
     
      void sleep(){
      }
     
      void play(){
      }
      
      Public People {
      	// 这是一个构造方法
      	int count = 0; // 局部变量
      }
    }
    

    一个类可以包含以下类型变量:

    • 局部变量: 在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁
    • 成员变量:成员变量定义在类中,方法体之外的变量。 这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问
    • 类变量:类变量也声明在类中,方法体之外,但必须声明为static类型
    • 类方法:概念同上面的类变量

    构造方法

    每个类都有构造方法。如果没有显示地为类定义构造方法,Java编译器将会为该类提供一个默认构造方法。

    在创建一个对象的时候,至少要调用一个构造方法。构造方法的名称必须与类同名,一个类可以有多个构造方法

    public class Puppy{
        public Puppy(){
        }
     
        public Puppy(String name){
            // 这个构造器仅有一个参数:name
        }
    }
    

    实例化对象

    对象时根据类创建的。在Java中,使用关键字new来创建一个新的对象。创建对象需要以下三步:

    1. 声明:声明一个对象,包括对象名称和对象类型
    2. 实例化:使用关键字new来创建一个对象
    3. 初始化:使用new创建对象时,会调用构造方法初始化对象

    下面是一个创建对象的例子:

    public class Puppy{
       public Puppy(String name){
          //这个构造器仅有一个参数:name
          System.out.println("小狗的名字是 : " + name ); 
       }
       
       public static void main(String[] args){
          // 下面的语句将创建一个Puppy对象
          Puppy myPuppy = new Puppy( "tommy" );
       }
    }
    

    编译并运行上面的程序,会打印出下面的结果:

    小狗的名字是:tommy
    

    下面的例子展示如何访问实例变量和调用成员方法:

    public class Puppy{
       int puppyAge;
       public Puppy(String name){
          // 这个构造器仅有一个参数:name
          System.out.println("小狗的名字是 : " + name ); 
       }
     
       public void setAge( int age ){
           puppyAge = age;  // 当形参`age`也是puppyAge时,需要用this:this.puppyAge = puppyAge
       }
     
       public int getAge( ){
           System.out.println("小狗的年龄为 : " + puppyAge ); 
           return puppyAge;
       }
     
       public static void main(String[] args){
          /* 创建对象 */
          Puppy myPuppy = new Puppy( "tommy" );
          /* 通过方法来设定age */
          myPuppy.setAge( 2 );
          /* 调用另一个方法获取age */
          myPuppy.getAge( );
          /*你也可以像下面这样访问成员变量 */
          System.out.println("变量值 : " + myPuppy.puppyAge ); 
       }
    }
    

    编译并运行上面的程序,产生如下的结果:

    小狗的名字是 : tommy
    小狗的年龄为 : 2
    变量值 : 2
    

    Java继承

    Java的继承是一种机制,表示为一个对象获取父对象的所有属性和行为

    继承是类与类之间的关系,是一个很简单很直观的概念,与现实世界中的继承(例如儿子继承父亲财产)类似。

    Java中的继承,可以创建基于现有类构建新的类。 当你从现有类继承时,就可以重复使用父类的方法和字段,也可以在继承的新类中添加新的方法和字段。

    为什么在Java中使用继承

    对于方法覆盖(因此可以实现运行时的多态性),提高代码可重用性。在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写(覆盖)。

    Java类继承的语法示例:

    class Super {
    }
     
    class Sub extends Super {
    }
    

    extends关键字表示从现有类派生创建的新类。extends的含义是增加功能。在Java的术语中,被继承的类称为父类或超类,新类称为子类。

    Java继承示例

    java继承

    如上图所示,Programmer是子类,Employee是超类。 两个类之间的关系是Programmer IS-A Employee. 它表示 Programmer 是一种 Employee 的类型。

    参考下面示例代码实现:

    class Employee {
        float salary = 40000;
    }
    
    class Programmer extends Employee {
        int bonus = 10000;
    
        public static void main(String args[]) {
            Programmer p = new Programmer();
            System.out.println("Programmer salary is:" + p.salary);
            System.out.println("Bonus of Programmer is:" + p.bonus);
        }
    }
    

    执行上面代码得到以下结果:

    Programmer salary is:40000.0 
    Bonus of programmer is:10000
    

    在上面的例子中,Programmer对象可以访问自身类以及Employee类的字段,即提高了代码可重用性。

    默认的: 不使用任何修饰符声明的属性和方法,对同一个包内的类是可见的。接口里的变量都隐式声明为public static final,而接口里的方法默认情况下访问权限为public

    Java继承类型

    在类的基础上,在Java中可以有三种类型的继承:单一,多级和分层继承。在Java的编程中,仅能通过接口支持多继承和混合继承。

    java继承类型

    注意:Java中的类不支持多继承

    当一个类扩展多个类,即被称为多继承。例如:

    多重继承

    问题:为什么在Java中不支持多继承?

    为了降低复杂性并简化语言,Java中不支持多重继承。想象一个:ABC是三个类。 C类继承AB类。 如果AB类有相同的方法,并且从子类对象调用它,AB类的调用方法会有歧义。

    因为编译时错误比运行时错误好,如果继承2个类,Java会在编译时报告错误。 所以无论子类中是否有相同的方法,都会有报告编译时错误。

    注意:构造方法不能被继承,掌握这一点很重要。 一个类能得到构造方法,只有两个办法:编写构造方法,或者根本没有构造方法,类有一个默认的构造方法。

    抽象类

    在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类

    在Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。

    由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。

    抽象类

    在Java中使用abstract关键字来定义抽象类。如下示例:

    //example of abstract class that have method body  
    abstract class Bike {
        Bike() {
            System.out.println("bike is created");
        }
    
        abstract void run();
    
        void changeGear() {
            System.out.println("gear changed");
        }
    }
    
    class Honda extends Bike {
        void run() {
            System.out.println("running safely..");
        }
    }
    
    class TestAbstraction2 {
        public static void main(String args[]) {
            Bike obj = new Honda();
            obj.run();
            obj.changeGear();
        }
    }
    

    注意到该Bike类没有什么不同,尽管该类是抽象类,但是它仍然有成员变量,抽象方法,方法体,构造函数甚至main()方法。

    执行上面的代码:

    bike is created
    running safely..
    gear changed
    

    抽象方法

    如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。

    Abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体

    抽象方法没有实现,方法名后面直接跟一个分号,而不是花括号。

    public abstract class Employee
    {
       private String name;
       private String address;
       private int number;
       
       public abstract double computePay();
       
       //其余代码
    }
    

    声明抽象方法会造成以下两个结果:

    • 如果一个类包含抽象方法,那么该类必须是抽象类
    • 任何子类必须重写父类的抽象方法,或者声明自身为抽象类

    继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。

    如果Salary类继承了Employee类,那么它必须实现computePay()方法:

    /* 文件名 : Salary.java */
    public class Salary extends Employee
    {
       private double salary; // Annual salary
      
       public double computePay()
       {
          System.out.println("Computing salary pay for " + getName());
          return salary/52;
       }
     
       //其余代码
    }
    

    注意: 抽象类中不能有抽象构造方法或抽象静态方法

    参考: Java抽象类

    抽象类和类的区别

    抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。

    • 抽象类不能被实例化,如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以被实例化

    • 普通类和抽象类都可以被继承,但是抽象类被继承后子类必须重写继承的方法,除非自类也是抽象类

    • 抽象类中不一定含有抽象方法,但是有抽象方法的类必定时抽象类

    • 抽象类中的抽象方法只是声明,不包含方法体,即不能给出方法的具体实现

    • 构造方法、类方法(用static修饰的方法)不能声明为抽象方法

    总之一句话,抽象类只是一种比较特殊的普通类。我觉得这篇文章解释的不错,大概意思就是:抽象类严格规定了几个你必须做的事情,比如:不能实例化、子类必须实现父类,除非子类也是抽象类。你不这样做就会出错,这种严谨的做法比人为规定的更加有效。

    接口

    定义:接口在Java中是一个抽象类型,是抽象方法的集合。一个类通过继承接口的方式,从而继承接口的抽象方法。

    接口通常以interface来声明,可以看做是一种特殊的抽象类。一个类通过继承接口的方式,从而来继承接口的抽象方法。

    接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。

    接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

    接口的声明

    接口的声明语法格式如下:

    public interface 接口名称 [extends 其他的接口名] {
            // 声明变量
            // 抽象方法
    }
    

    接口有以下几个特征:

    • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是public abstract,其他修饰符都会报错)
    • 接口中可以含有变量,但是接口中的变量会被隐式的指定为public static final变量(并且只能是public,用private修饰会报编译错误)
    • 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法

    注:JDK 1.8 以后,接口里可以有静态方法和方法体

    接口的实现

    当类实现接口的时候,类要实现接口中的所有的方法。否则,类必须声明为抽象类

    类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。

    实现一个接口的语法,可以使用这个公式:

    ...implements 接口名称[, 其他接口名称, 其他接口名称..., ...] ...
    

    下面是一个Java的接口示例:

    interface printable {
        void print();
    }
    
    class A6 implements printable {
        public void print() {
            System.out.println("Hello, Interface");
        }
    
        public static void main(String args[]) {
            A6 obj = new A6();
            obj.print();
        }
    }
    

    执行上面的代码,结果如下:

    Hello,Interface
    

    接口与类的相似点

    • 一个接口可以有很多方法
    • 接口文件保存在.java结尾的文件中,文件名使用接口名
    • 接口的字节码文件保存在.class结尾的文件中
    • 接口相应的字节码文件必须在与包名称相匹配的目录结构中

    接口与类的区别

    • 接口不能用于实例化对象
    • 接口没有构造方法
    • 接口中所有方法必须为抽象方法
    • 接口不能包含成员变量,除了staticfinal变量
    • 接口不是被类继承了,而是要被类实现
    • 接口支持多继承

    接口和抽象类的区别

    • 抽象类中的方法可以不是抽象方法,但接口中的方法必须都是抽象方法
    • 抽象类中的非抽象方法可以有方法体,就是实现方法的具体功能,避免在子类中重复实现这些方法。但接口中的方法不行(JDK 1.8以后可以有方法体,作为默认实现)
    • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的
    • 抽象类可以有具体的方法和属性, 接口只能有抽象方法和不可变常量(final)
    • 一个类只能继承一个抽象类,而一个类却可以实现多个接口
    • 抽象类里面的抽象方法必须全部被子类实现,如果子类不实现,那么子类必须也是抽象类。接口里面的方法也必须全部被子类实现,如果子类不能实现,那么子类必须是抽象类
    • 抽象类主要用来抽象类别,接口主要用来抽象方法功能。当你关注事物的本质的时候,请用抽象类;当你关注一种操作的时候,用接口
    • 抽离类可以实现接口,接口不能实现抽象类

    参考:

    抽象类和接口的区别

    接口和抽象类有什么区别?

  • 相关阅读:
    C++: string的大小写转换
    c++自由的转换string和number
    C# 中的数据库操作~存储过程篇Mysql SqlServer
    Google Protocol Buffer Basics: C++
    C#中的扩展方法(向已有类添加方法,但无需创建新的派生类型)
    多态以及虚析构函数的使用
    【Java基础】String 相关知识点总结
    【设计模式】抽象工厂模式
    【设计模式】工厂方法模式
    【设计模式】简单工厂
  • 原文地址:https://www.cnblogs.com/chenwenhao/p/12045786.html
Copyright © 2011-2022 走看看