抽象类(abstract)

一个类只定义了一个为所有子类共享的一般形式,至于细节则交给每一个子类去实现,这种类没有任何具体的实例,只具有一些抽象的概念,那么这样的类称为抽象类。

在面向对象领域,抽象类主要用来进行类型隐藏。比如,如果我们进行一个图形编辑软件的开发,就会发现问题领域存在着圆、三角形这样一些具体概念,它们是不同的,但是它们都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。正是因为抽象概念在问题领域没有对应的具体概念,所以用以表征抽象概念的抽象类是不能够实例化的。

abstract class class_name
{
abstract type method_name(parameter);
}

abstract 表示该类或该方法是抽象的;class_name 表示抽象类的名称;method_name 表示抽象方法名称,如果在一个方法之前使用 abstract 来修饰,则说明该方法是抽象方法,不能有方法体;parameter 表示方法参数列表。

abstract 关键字只能用于普通方法,不能用于 static 方法或者构造方法中。在抽象类中必须包含至少一个抽象方法,并且所有抽象方法不能有具体的实现,而应在它们的子类中实现所有的抽象方法(要有方法体),包含一个或多个抽象方法的类必须通过在其 class 声明前添加 abstract 关键字将其声明为抽象类。因为一个抽象类不定义完整的实现,所以抽象类也就没有自己的对象。因此,任何使用 new 创建抽象类对象的尝试都会导致编译时错误。

public abstract class Shape
{
public int width; //几何图形的长
public int height; //几何图形的宽
public Shape(int width,int height)
{
this.width=width;
this.height=height;
}
public abstract double area(); //定义抽象方法,计算面积
}
public class Square extends Shape
{
public Square(int width,int height)
{
super(width,height);
}
@Override
public double area()//重写父类中的抽象方法,实现计算正方形面积的功能
{
return width*height;
}
}
public static void main(String[] args)
{
Square square=new Square(5,4);
System.out.println("面积为:"+square.area());//输出:面积为:20
}

接口

接口类似于类,但接口的成员没有执行体,它只是方法、属性、事件和索引符的组合而已。接口不能被实例化,接口没有构造方法,没有字段。在应用程序中,接口就是一种规范,它封装了可以被多个类继承的公共部分。

接口继承和实现继承的规则不同,一个类只有一个直接父类,但可以实现多个接口。Java 接口本身没有任何实现,只描述 public 行为,因此 Java 接口比 Java 抽象类更抽象化。Java 接口的方法只能是抽象的和公开的,Java 接口不能有构造方法,Java 接口可以有 public、Static 和 final 属性。

接口把方法的特征和方法的实现分隔开来,这种分隔体现在接口常常代表一个角色,它包装与该角色相关的操作和属性,而实现这个接口的类便是扮演这个角色的演员。一个角色由不同的演员来演,而不同的演员之间除了扮演一个共同的角色之外,并不要求其他的共同之处。

接口对于其声明、变量和方法都做了许多限制,这些限制作为接口的特征归纳如下:

具有 public 访问控制符的接口,允许任何类使用;没有指定 public 的接口,其访问将局限于所属的包。

方法的声明不需要其他修饰符,在接口中声明的方法,将隐式地声明为公有的(public)和抽象的(abstract)。

在 Java 接口中声明的变量其实都是常量,接口中的变量声明,将隐式地声明为 public、static 和 final,即常量,所以接口中定义的变量必须初始化。接口没有构造方法,不能被实例化。

定义

public interface interfaceName{
}
//例如
public interface Personlnterface{
String name; //不合法,变量name必须初始化
int age=20; //合法,等同于 public static final int age=20;
void getInfo(); //方法声明,等同于 public abstract void getInfo();
}

实现

在实现类中,所有的方法都使用了 public 访问修饰符声明。无论何时实现一个由接口定义的方法,它都必须实现为 public,因为接口中的所有成员都显式声明为 public

public class Person implements Personlnterface
{
public void getInfo(){
return "Hello World";
}
}

使用

public static void main(String[] args){
Personlnterface person = new Person();
person.getInfo();//返回 HelloWorld
}

抽象类与接口的区别

在面向对象的设计思想中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有描绘一个具体的对象,那么这样的类就是抽象类,抽象类是对那些看上去不同,但是本质上相同的具体概念的抽象,正是因为抽象的概念在问题领域没有对应的具体概念,所以抽象类是不能够实例化的

语法不同

接口内只能是功能的定义,而抽象类中则可以包括功能的定义和功能的实现。在接口中,所有的属性肯定是 public、static 和 final,所有的方法都是 abstract,所以可以默认不写上述标识符;在抽象类中,既可以包含抽象的定义,也可以包含具体的实现方法

public interface Animal
{
public void eat();
public String fly();
}
public abstract class Animal
{
public abstract void eat();
public String fly(){
return "我会飞";
};
}

接口的实现类中使用 implements 关键字;而在抽象类的实现类中,则使用 extends 关键字。一个接口的实现类可以实现多个接口,而一个抽象类的实现类则只能实现一个抽象类。

//接口
public class concreteAnimal implements Animal
{
public void eat(){}
public void fly(){}
}
//抽象类
public class concreteAnimal extends Animal
{
public void eat(){}
public void fly(){}
}

设计思想不同

从前面抽象类的具体实现类的实现方式可以看出,其实在 Java 中,抽象类和具体实现类之间是一种继承关系,也就是说如果釆用抽象类的方式,则父类和子类在概念上应该是相同的。接口却不一样,如果采用接口的方式,则父类和子类在概念上不要求相同。接口只是抽取相互之间没有关系的类的共同特征,而不用关注类之间的关系,它可以使没有层次关系的类具有相同的行为。因此,可以这样说:抽象类是对一组具有相同属性和方法的逻辑上有关系的事物的一种抽象,而接口则是对一组具有相同属性和方法的逻辑上不相关的事物的一种抽象。

强列的is a 使用抽象类,has a 使用接口。如:鸟是一种动物。鸟有一个功能会飞。猫也是一种动物,但是猫不会飞。

//接口
public interface Fly
{
public void flyUp();
}
//抽象类
public abstract class Animal
{
public abstract void eat();
}
//猫是一种动物
public class Cat extends Animal{
}
//鸟是一种动物,同时会飞
public class Bird extends Animal implements Run {
}

抽象类是对一组具有相同属性和方法的逻辑上有关系的事物的一种抽象,而接口则是对一组具有相同属性和方法的逻辑上不相关的事物的一种抽象,因此抽象类表示的是“is a”关系,接口表示的是“has a”关系。

内部类

在一个类内部的类,我们称之为内部类。内部类可以很好地实现隐藏,一般的非内部类是不允许有 private 与 protected 权限的,但内部类可以。内部类拥有外围类的所有元素的访问权限。

内部类可以分为:实例内部类、静态内部类和成员内部类,每种内部类都有它特定的一些特点,本节先详细介绍一些和内部类相关的知识。

内部类的特点如下:

内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的 .class 文件,但是前面冠以外部类的类名和 $ 符号。

内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否为 private 的。

内部类声明成静态的,就不能随便访问外部类的成员变量,仍然是只能访问外部类的静态成员变量。

public class Test
{
public class InnerClass
{
public int getSum(int x,int y)
{
return x+y;
}
}
public static void main(String[] args)
{
Test.InnerClass testInner =new Test().new InnerClass();
int i = testInner.getSum(2/3);
System.out.println(i); //输出5
}
}

实例内部类

实例内部类是指没有用 static 修饰的内部类

public class Outer
{
class Inner
{
//实例内部类
}
}

在外部类的静态方法和外部类以外的其他类中,必须通过外部类的实例创建内部类的实例,如果有多层嵌套,则内部类可以访问所有外部类的成员

public class Outer
{
class Inner{}
Inner i=new Inner(); //类内部不需要创建外部类实例
public void method0()
{
Inner j=new Inner(); //类内部不需要创建外部类实例
}
public static void method1()
{
Inner r=new Outer().new inner(); //静态方法需要创建外部类实例
}
class Inner1
{
Inner k=new Inner(); //不需要创建外部类实例
}
}
class OtherClass
{
Outer.Inner i=new Outer().new Inner(); //其他类使用时需要创建外部类实例
}

静态内部类

静态内部类是指使用 static 修饰的内部类

public class Outer
{
static class Inner
{
//静态内部类
}
}

在创建静态内部类的实例时,不需要创建外部类的实例

public class Outer
{
static class Inner{}
}
class OtherClass
{
Outer.Inner oi=new Outer.Inner();
}

局部内部类

局部内部类是指在一个方法中定义的内部类

public class Test
{
public void method()
{
class Inner
{
//局部内部类
}
}
}

局部内部类与局部变量一样,不能使用访问控制修饰符(public、private 和 protected)和 static 修饰符修饰,局部内部类只在当前方法中有效,局部内部类中可以访问外部类的所有成员

public class Test
{
Inner i=new Inner(); //编译出错
Test.Inner ti=new Test.Inner(); //编译出错
Test.Inner ti2=new Test().new Inner(); //编译出错
public void method()
{
class Inner{}
Inner i=new Inner();
}
}

匿名类

匿名类是指没有类名的内部类,必须在创建时使用 new 语句来声明类

new<类或接口>()
{
//类的主体
};

这种形式的 new 语句声明一个新的匿名类,它对一个给定的类进行扩展,或者实现一个给定的接口。使用匿名类可使代码更加简洁、紧凑,模块化程度更高

匿名类有两种实现方式:

继承一个类,重写其方法。

实现一个接口(可以是多个),实现其方法。

public class Out
{
void show()
{
System.out.println("调用 Out 类的 show() 方法");
}
}
public class TestAnonymousInterClass
{
//在这个方法中构造一个匿名内部类
private void show()
{
Out anonyInter=new Out()
{
//获取匿名内部类的实例
void show()
{
System.out.println("调用匿名类中的 show() 方法");
}
};
anonyInter.show();
}
public static void main(String[] args)
{
TestAnonymousInterClass test=new TestAnonymousInterClass();
test.show();
}
}

Java入门教程十(抽象类接口内部类匿名类)的更多相关文章

  1. Java入门教程十二(集合与泛型)

    在 Java 中数组的长度是不可修改的.然而在实际应用的很多情况下,无法确定数据数量.这些数据不适合使用数组来保存,这时候就需要使用集合. Java 的集合就像一个容器,用来存储 Java 类的对象. ...

  2. 无废话ExtJs 入门教程十九[API的使用]

    无废话ExtJs 入门教程十九[API的使用] extjs技术交流,欢迎加群(201926085) 首先解释什么是 API 来自百度百科的官方解释:API(Application Programmin ...

  3. “全栈2019”Java第七十八章:内部类可以继承其他类吗?

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  4. RabbitMQ入门教程(十六):RabbitMQ与Spring集成

    原文:RabbitMQ入门教程(十六):RabbitMQ与Spring集成 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https: ...

  5. 无废话ExtJs 入门教程十六[页面布局:Layout]

    无废话ExtJs 入门教程十六[页面布局:Layout] extjs技术交流,欢迎加群(201926085) 首先解释什么是布局: 来自百度词典的官方解释:◎ 布局 bùjú: [distributi ...

  6. 无废话ExtJs 入门教程十五[员工信息表Demo:AddUser]

    无废话ExtJs 入门教程十五[员工信息表Demo:AddUser] extjs技术交流,欢迎加群(201926085) 前面我们共介绍过10种表单组件,这些组件是我们在开发过程中最经常用到的,所以一 ...

  7. 无废话ExtJs 入门教程十四[文本编辑器:Editor]

    无废话ExtJs 入门教程十四[文本编辑器:Editor] extjs技术交流,欢迎加群(201926085) ExtJs自带的编辑器没有图片上传的功能,大部分时候能够满足我们的需要. 但有时候这个功 ...

  8. 无废话ExtJs 入门教程十二[下拉列表联动:Combobox_Two]

    无废话ExtJs 入门教程十二[下拉列表联动:Combobox_Two] extjs技术交流,欢迎加群(201926085) 不管是几级下拉列表的联动实现本质上都是根据某个下拉列表的变化,去动态加载其 ...

  9. 无废话ExtJs 入门教程十[单选组:RadioGroup、复选组:CheckBoxGroup]

    无废话ExtJs 入门教程十[单选组:RadioGroup.复选组:CheckBoxGroup] extjs技术交流,欢迎加群(201926085) 继上一节内容,我们在表单里加了个一个单选组,一个复 ...

随机推荐

  1. Kubernetes 问题定位技巧:分析 ExitCode

    使用 kubectl describe pod 查看异常的 pod 的状态,在容器列表里看 State 字段,其中 ExitCode 即程序退出时的状态码,正常退出时为0.如果不为0,表示异常退出,我 ...

  2. 搭建Docker私有仓库&用户密码认证&web可视化界面

    1.拉取镜像 docker pull hyper/docker-registry-web docker pull registry 2.安装 yum install docker-compose 3. ...

  3. 吴裕雄--天生自然python学习笔记:python 用pyInstaller模块打包文件

    要想在没有安装 Python 集成环境的电脑上运行开发的 Python 程序,必须把 Python 文件打包成 .exe 格式的可执行 文件. Python 的打包工作 PyInstaller 提供了 ...

  4. intel windows caffe加速

    网址: https://github.com/BeFreeRoad/intel_caffe_windows 将intel caffe从linux平台移植到windows平台. 性能: 在虚拟机上测试可 ...

  5. laravel如何输出最后一条执行的SQL

    \DB::connection()->enableQueryLog(); // 开启查询日志 \DB::table('xxx'); // 要查看的sql $queries = \DB::getQ ...

  6. python中字典以key排序,以value排序。以及通过value找key的方式

    1.sorted函数首先介绍sorted函数,sorted(iterable,key,reverse),sorted一共有iterable,key,reverse这三个参数. 其中iterable表示 ...

  7. 关于RFC

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/byxdaz/article/details/557902关于RFC(Request For Comm ...

  8. Rip路由实验

    以上是实验要求和实验拓扑图 (实验拓扑自己重新连线) 1.在R1-R4,4台路由器上各设置一个回环口 2.略 3.在四个路由器上配置rip(rip的基本命令) #rip 1 #version 2 #u ...

  9. [LC] 62. Unique Paths

    A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...

  10. 2015-09-14-初级string

    标准库string类型 string对象初始化 string s1; string s2(s1); string s3("value"); string s4(n,'c'); st ...