java抽象类 接口 包

本文详细介绍了Java中的抽象类和接口,包括它们的定义、用法和区别。抽象类不能实例化,常用于作为基类,有抽象方法但不一定全部抽象。接口则是一个抽象方法的集合,可以实现多继承,所有方法默认为public abstract。此外,还讨论了包的概念,它是区别类命名空间和管理类的重要方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

instanceof运算符

1.含义:判别对象是否是某个引用型的实例

2.E instanceof RefType

Animal a=new Animal();Dog d=new Dog();//a,aDog是Animal类型,d是Dog类型
Animal aDog=new Dog()//有aDog instanceof Animal;aDog instanceof Dog均为true
//有aDog instanceof Cat;a instanceof Dog均为false
//有d instanceof Cat编译错,d不能强制转换为Cat类型
//有null instanceof Cat为false,因为null不是任何引用型的实例

抽象类

抽象类

1.一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

2.抽象类不能实例化对象, 只有抽象类的非抽象子类可以创建对象。

3.类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。

4.抽象类必须被继承,才能被使用。

5.抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

抽象方法

1.定义:无方法体,用abstract修饰的方法。

2.作用:是一种“契约”,超类提供契约(抽象方法),要求该超类的子类必须实现该契约(重写抽象方法,为抽象方法补上方法体),否则,如果没有实现该抽象方法,该子类必须是抽象类(无法创建对象)

3.构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。

public abstract class Employee
{
   private String name;
   private String address;
   private int number;
   
   public abstract double computePay(); 
   //其余代码
}
//如果Salary类继承了Employee类,那么它必须实现computePay()方法:
public class Salary extends Employee
{
   private double salary; // Annual salary
   public double computePay()
   {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
 
   //其余代码
}

注意:

*abstract不能修饰构造方法

*abstract不能与final,static同时使用

接口

一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。 借助接口,可以实现不同对象的耦合。

语法约束

​ 1.变量默认:public(公开) static(唯一性) final(不可更改)。

​ 2.方法默认:public abstract,不可更改。

在这里插入图片描述

interface Test1{
    int x=0;         //正确 前面有默认的public static final
    void f();        //正确 前面有默认的public abstract
    int y;           //错误,没有赋值
    protected int y; //错误,不能用protected修饰
    private void h();//错误,不能用private修饰
    void g(){;}      //错误,不能有方法体
}

接口与类的关系

  • 一个接口可以有多个方法
  • 类实现接口的抽象方法
  • 一个类只能继承一个类,但是能实现多个接口。
  • 一个接口能继承另一个接口,这和类之间的继承比较相似。

接口与类的区别

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

抽象类和接口的区别

  • 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
  • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
  • 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
  • 一个类只能继承一个抽象类,而一个类却可以实现多个接口。

声明语法

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

实例

interface Animal {
   public void eat();
   public void travel();
}

public class MammalInt implements Animal{
   public void eat(){
      System.out.println("Mammal eats");
   } 
   public void travel(){
      System.out.println("Mammal travels");
   }  
   public int noOfLegs(){
      return 0;
   } 
   public static void main(String args[]){
      MammalInt m = new MammalInt();
      m.eat();
      m.travel();
   }
}

重写接口中声明的方法时,需要注意以下规则:

  • 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
  • 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
  • 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。

接口的继承

1.接口的继承使用extends关键字,子接口继承父接口的方法。

2.接口的多继承: extends关键字只需要使用一次,在其后跟着继承接口

public interface Hockey extends Sports, Event

public interface Sports
{
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}
public interface Football extends Sports
{
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}//实现Football接口的类需要实现五个方法,其中两个来自于Sports接口
public interface Hockey extends Sports
{
   public void homeGoalScored();
   public void visitingGoalScored();
   public void endOfPeriod(int period);
   public void overtimePeriod(int ot);
}//Hockey接口自己声明了四个方法,从Sports接口继承了两个方法,实现Hockey接口的类需要实现六个方法。

3.接口多继承存在的问题

  • 菱形继承:如下图所示B、C继承A;D继承B、C,D类中x的类型不能确定

在这里插入图片描述

  • 接口冲突现象

    interface A{int x=10;} 
    interface B{double x=2;}
    interface C extends A,B{;} //C里面有两个x
    class D implements C{;}
    //上述代码虽编译正确,加入下列代码会引发编译错误
    D d=new D();
    System.out.println(d.x)//编译错误
    

    初始化块

    1.初始化块:在类中独立于成员方法之外的代码段。

    ​ ◆无名、无参、无返回值。

    ​ ◆被static修饰为静态初始化块,否则为实例块。

    2.初始化块的执行遵循以下规则:

    ​ ◆静态块先于实例块,实例块先于构造函数;

    ​ ◆多个实例块/静态块的执行顺序同其出现次序;

    ​ ◆静态块在类初次加载时执行,仅执行一次。

    class TestBlock{
        TestBlock (int x){System,out.print("1== ");}
        TestBlock (){System,out.print("2== ");}
        static {System,out.print("Static 3== ");}//静态初始化块
        {System,out.print("4== ");}//实例初始化块
        {System,out.print("5== ");}//实例初始化块
        static {System,out.print("Static 6== ");}//静态初始化块
    }
    class{
        public static void main(String args[]){
            System,out.print("ppppp== ");
            new TestBlock();
            new TestBlock (99);
        }
    }
    //运行结果:ppppp== Static 3== Static 6== "4== 5== 2== 4== 5== 1==
    /*总结:初始化块的作用,就是为了初始化
    	从结果看,静态块先于实例块,且仅仅执行一次 (即在类加载时执行)
    	每次构造对象,都要执行先执行实例块,再执行构造函数*/
    

区别类名的命名空间 ,用于将类分门别类的管理,且避免类名冲突(即重名)。

1.声明包:一个java源文件只能声明一个包,用于指明编译后.class文件存储的位置。package语句只能放在第一句。

2.导入包:导入后,可以直接使用类名A。未导入则必须使用全名,如a.b.x.A a=new a.b.x.A();,若导入,使用 A a=new A()即可。

3.包的作用:把不同的 java 程序分类保存,更方便的被其他 java 程序调用。

4.import java.util.*; – 按需导入,会影响编译速度,不影响执行速度。

5.无名包:若未声明包,则编译后产生的.class文件自动放置于无名包。无名包中的类,没有包名,故无法被导入。只能直接拷贝到目录或包中使用。

类的权限

两种权限:public和缺省

**跨包访问:**只能访问外包的public类。

package a.b.x;
public class A {
    public void fa() {;}
}
class B {
    public void fb() {;}
}
-----------------------------------------
package a.b.y;  import a.b.x.A;
public class C {
     public void fc() {
           A a=new A(); a.fa(); //编译正确
          //a.b.x.A a=new a.b.x.A(); a.fa(); //正确
          //a.b.x.B b=new a.b.x.B(); //编译错
    }
}
class D {
     public void fd() {
           A a=new A(); a.fa(); //编译正确
          //a.b.x.A a=new a.b.x.A(); a.fa(); 正确
          //a.b.x.B b=new a.b.x.B(); //编译错
    }
}
//C、D中只能访问A,不能访问B

类中成员的权限

1.对同一类而言,权限没有意义:成员间可任意访问,不受权限制约。

​ 2.对同一包中的类A和B,A不能访问B中的私有部分,其它均可访问;

3. 跨包访问的要求极为苛刻,要求:只能访问public类的public成员。   
   4. 拓展:允许包外的子孙访问自己的protected成员。  

在这里插入图片描述

package X;
public class  A{
  public      int   x1;
  protected   int   x2;
              int   x3;
   private    int   x4;
}
class B{
  public      int   y1;
  protected   int   y2;
              int   y3;
   private    int   y4;
}
----------------------------------
package Y; 
public class C{
    void h(){
   		D d=new D(); 
   		d.x2=5;//编译错
	}

}
class D extends A  
{  
	void h(){
   		A a=new A();
   		x2=6;  //正确 
   		a.x2=5;//编译错,D继承的x2,依旧隶属X包,有保护权限,故编译错。
	}

}

void f()//将f()放在C、D中,f()中的哪些操作可能成功,哪些必定会失败?
{  A a=new A();
   a.x1=1; a.x2=2; a.x3=3;
   B b=new B();
   b.y1=1; b.y2=2; b.y3=2;
}
//放在C中 只能访问x1;放在D中,只能访问x1,x2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值