Java抽象类、接口和内部类
1.抽象方法、抽象类
1)抽象方法:
- 由abstract修饰
- 只有方法的定义,没有方法的具体实现(连{}都没有)
由abstract修饰的方法为抽象方法,抽象方法只有方法的定义,没有方法体实现,用一个分号结尾。即:方法五要素中,抽象方法缺少了一个要素(方法体),也可以将抽象方法理解为不完整的方法。
2)抽象类:
- 由abstract修饰
- 包含抽象方法的类必须是抽象类,不包含抽象方法的类也可以声明抽象类(意义不大)
- 抽象类不能被实例化
- 抽象类是需要被继承的
- 子类需要重写抽象类的所有抽象方法---常用
- 子类也可以声明为抽象类---不常用
- 抽象类的意义:
- 封装子类所共有的属性和行为---代码复用
- 为所有子类提供一种统一的类型---向上造型
- 可以包含抽象方法,为所有子类提供了统一的入口,子类的实现不同,但入口是一致的
由abstract修饰的类为抽象类,抽象类是不能实例化对象的,而一个类不能实例化是没有意义的,所以需要定义类来继承抽象类,它的子类必须重写所有的抽象方法,除非该类也声明为抽象类。
abstract class Foo{
private double c;
public Foo(double c){ //没什么意义,需要被子类重写
this.c = c;
}
public abstract double area(); //抽象方法,没有方法体,大括号也不存在
}
class Sub extends Foo{
public Sub(double c) { //需要重写构造方法
super(c);
}
public double area(){
return 0.0;
}
}
abstract class Sub2 extends Foo{ //抽象方法继承抽象方法
public Sub2(double c) { //需要重写构造方法,不需要重写抽象方法
super(c);
}
}
3)抽象类不可以被实例化
Foo f = new Foo(); //编译错误,抽象类不能被实例化
即使一个类中没有抽象方法,也可以将其定义为抽象类,同样,该类不可以实例化。
注意:abstract和final关键字不能同时修饰一个类,因为final使得类不可继承,而abstract修饰的类如果不可以继承将没有任何意义。
4)继承抽象类
一个类继承抽象类后,必须实现其抽象方法,不同的子类可以有不同的实现。
abstract class Foo{
private double c;
public Foo(double c){ //没什么意义,需要被子类重写
this.c = c;
}
public abstract String sayHi();
}
class Sub extends Foo{
public Sub(double c) { //需要重写构造方法
super(c);
}
public String sayHi(){
return "Hello";
}
}
4)抽象类的意义
- 为其子类提供一个公共的类型(父类引用指向子类对象,即向上造型)
- 封装子类中的重复内容(成员变量和方法)
- 定义有抽象方法,子类虽然有不同的实现,但该方法的定义是一致的(子类需要实现此抽象方法)
案例1:抽象类演示
public class AbstractDemo {
public static void main(String[] args){
// Shape s = new Shape(); //编译错误,抽象类不能被实例化
Shape[] shape = new Shape[4]; //创建Shape数组对象
shape[0] = new Circle(1); //向上造型
shape[1] = new Circle(2);
shape[2] = new Square(1);
shape[3] = new Square(2);
maxArea(shape); //调用求最大面积方法
} private static void maxArea(Shape[] shape) {
double max = shape[0].area();
int maxIndex = 0; //最大面积下标
for(int i=0;i<shape.length;i++){
double area = shape[i].area();
if(area>max){
max = area;
maxIndex=i;
}
}
System.out.println("最大面积为:"+max+"所在下标为:"+maxIndex);
}
}
abstract class Shape{ //抽象类---不完整的类
protected double c; //周长
public abstract double area(); //抽象方法---不完整
}
class Circle extends Shape{
public Circle(double c){
this.c = c;
}
public double area(){ //重写抽象方法---变不完整为完整
return 0.0796*c*c;
}
}
class Square extends Shape{
public Square(double c){
this.c = c;
}
public double area(){
return 0.0625*c*c;
}
}
2. 接口
- 是一个标准、规范,遵循了这个标准就能干某件事
- 是一种数据类型(引用类型)
- 由interface定义,只能包含常量和抽象方法,方法默认由public abstract修饰
- 接口不能被实例化
- 接口是需要被实现的,通过implements关键字实现,实现类:必须重写接口中的所有抽象方法
- 一个类可以实现多个接口,逗号分隔,若又继承又实现,必须先继承后实现
- 接口可以继承一个或多个接口,逗号分隔(extends)
1)定义接口
接口可以看成是特殊的抽象类。即:只包含抽象方法和常量的抽象类。通过interface关键字来定义接口。
interface Demo{
public static int x = 100;
public int y = 50;
double area(); //默认会加上public abstract修饰
public abstract void test();
}
2)实现接口
与继承不同,一个类可以实现多个接口,实现的接口直接用逗号分隔,该类需要实现这些接口中定义的所有方法。通过implements关键字实现接口。接口可以作为一种类型声明变量,一个接口类型的变量可以引用实现了该接口的类的对象,通过该变量可以调用该接口中定义的方法(具体的实现类提供了方法的实现)。一个接口类型变量,引用了子类的对象,调用时,调用的是子类对象的具体的实现。
public class Test {
public static void main(String[] args){
Demo d = new Aoo(); //一个接口类型变量,引用了子类的对象,调用时,调用的是子类对象的具体的实现
d.test(); //This is Aoo
}
} interface Demo{
public static int x = 100;
public int y = 50;
double area(); //默认会加上public abstract修饰
public abstract void test();
}
class Aoo implements Demo{
public double area(){
return 0.0;
}
public void test(){
System.out.println("This is Aoo");
}
}
3)接口的继承
接口间可以存在继承关系,一个接口可以通过extends关键字继承另外一个接口,子接口继承了父接口中定义的所有方法。
interface Foo{
public void funFoo();
}
interface Goo{
public void funGoo();
}
interface Hoo extends Foo,Goo{ //接口可以继承一个或多个接口,逗号分隔
public void funHoo();
}
interface Ioo{
void funIoo();
} class Joo implements Hoo,Ioo{ //一个类可以继承多个接口
public void funFoo(){} //重写父类的父类的抽象方法
public void funGoo(){} //重写父类的父类的抽象方法
public void funHoo(){} //重写父类的抽象方法
public void funIoo(){} //重写父类的抽象方法
}
4)接口和抽象类的区别
- 一个类只能继承一个抽象类,但可以实现多个接口
- 抽象类中可以包含抽象方法和非抽象方法,而接口中的所有方法均为抽象的
- 子类继承抽象类必须实现抽象类中所有抽象方法,否则子类也必须是抽象类。而子类实现接口则必须实现接口中所有的抽象方法。
案例2:接口的演示
public class InterfaceDemo {
public static void main(String[] args){
// Inter6 o1= new Inter6(); //编译错误,接口不能被实例化
Inter6 o2 = new Moo(); //向上造型
Inter5 o3 = new Moo();
}
}
//演示接口语法
interface Inter1{
public static final int NUM = 5;
public abstract void show();
double PI = 3.14; //默认public static final修饰
void say(); //默认public abstract修饰
// int count; //编译错误,常量必须声明同时初始化
// void test(){} //编译错误,抽象方法没有方法体
} //演示接口实现
interface Inter2{
void show();
void say();
}
class Joo implements Inter2{
public void show(){}
public void say(){}
} //演示接口的多实现、继承
interface Inter3{
void show();
}
interface Inter4{
void say();
}
abstract class Koo{
abstract void test();
}
class Loo extends Koo implements Inter3,Inter4{
public void show(){}
public void say(){}
void test(){}
} //演示接口继承接口
interface Inter5{
void show();
}
interface Inter6 extends Inter5{
void say();
}
class Moo implements Inter6{
public void show(){}
public void say(){}
}
3. 多态
1)意义:
1.1)同一类型的引用指向不同的对象时,有不同的实现:行为的多态:cut()、run()
1.2)同一个对象被造型为不同的类型时,有不同的功能:对象的多态:水
2)向上造型:
2.1)父类型的引用指向子类的对象
2.2)能造型成为的类有:父类、所实现的接口
2.3)能点出来什么,看引用的类型
3)强制类型转换,成功的条件有两种:
3.1)引用所指向的对象,就是该子类型
3.2)引用所指向的对象,实现了该接口
4)若不满足以上两个条件,则发生ClassCastException类型转换异常
建议:在强转之前先通过instanceof判断引用指向的对象是否是该类型
4. 成员内部类:应用几率不大
1)类中套类,里面的成为Inner,外面的成为Outer
2)内部类通常只服务于外部类,对外不具备可见性
3)内部类对象通常是在外部类中创建的
4)内部类中可以直接访问外部类的成员,包括私有的
一般情况下,Inner对象会在Outer对象中创建(构造方法或其他方法),Inner对象中会有一个隐式的引用指向创建它的Outer类对象,外部类名.this.
5. 匿名内部类
1)若想创建一个类(子类)的对象,并且对象只被创建一次,此时该类不必命名,称之为匿名内部类
2)匿名内部类中访问外部的变量,该变量必须是final的
常见面试题:内部类有独立的.class吗? 答案:有
5. 面向对象三大特征
1)封装:
1.1)类:封装的是对象的属性和行为
1.2)方法:封装的是业务逻辑功能的实现
1.3)访问控制修饰符:封装的是访问的权限
2)继承:
2.1)作用:代码复用,通过extends来实现继承
2.2)父类/基类:共有的
子类/派生类:特有的
3.3)单一继承、多接口实现
3)多态:
3.1)意义:行为的多态、对象的多态
3.2)向上造型、强制类型转换(instanceof)
3.3)多态的表现形式:重写、重载
设计规则:
1)将所有子类共有的属性和行为,抽象到父类中
2)所有子类行为都一样,设计为普通方法
所有子类行为不一样,设计为抽象方法
3)将部分子类共有的行为,抽象到接口中
符合既是也是的原则,使用接口
接口是对继承的单根性的扩展——实现多继承
案例3:多态的演示
public class MultiTypeDemo {
public static void main(String[] args){
Aoo o1 = new Boo(); //向上造型(自动类型转换)
Boo o2 = (Boo)o1; //o1指向的对象就是Boo类型(强制类型转换)
Inter o3 = (Inter)o1; //o1指向的对象实现了Inter接口(强制类型转换)
// Coo o4 = (Coo)o1; //java.lang.ClassCastException:类型转换异常
if(o1 instanceof Coo){ //强转建议使用instanceof判断
Coo o5 = (Coo)o1;
}
}
} interface Inter{}
class Aoo{}
class Boo extends Aoo implements Inter{}
class Coo extends Aoo{}
案例4:多态的演示2
public class UnionPayTest {
public static void main(String[] args) {
ABCATM atm = new ABCATM(); //atm机对象
UnionPay card = new ABCImpl(); //银联卡
atm.insertCard(card); //插卡
atm.payTelBill(); //支付电话费
}
}
class ABCATM{ //农行ATM机类
private UnionPay card; //银联卡
public void insertCard(UnionPay card){ //插卡
this.card = card;
}
public void payTelBill(){ //支付电话费按钮
if(card instanceof ABC){ //是农行卡
ABC abcCard = (ABC)card; //强转为农行卡
abcCard.payTelBill("12345679845", 500);
}else{ //不是农行卡
System.out.println("不是农行卡,不能支付电话费");
}
}
} interface UnionPay{ //银联接口
public double getBalance(); //查询余额
public boolean drawMoney(double number); //取款
public boolean checkPwd(String input); //验证密码
}
interface ICBC extends UnionPay{ //工行接口
public void payOnline(double number); //在线支付
}
interface ABC extends UnionPay{ //农行接口
public boolean payTelBill(String phoneNum,double sum); //支付电话费
} class ICBCImpl implements ICBC{ //工行卡
public double getBalance(){return 0.0;}
public boolean drawMoney(double number){return true;}
public boolean checkPwd(String input){return true;}
public void payOnline(double number){}
}
class ABCImpl implements ABC{ //农行卡
public double getBalance(){return 0.0;}
public boolean drawMoney(double number){return true;}
public boolean checkPwd(String input){return true;}
public boolean payTelBill(String phoneNum,double sum){
System.out.println("支付电话费成功");
return true;
}
}
案例5:成员内部类的演示
public class InnerClassDemo {
public static void main(String[] args){
Outer outer = new Outer(100);
outer.printTime();
// Inner g = new Inner(); //编译错误
}
} class Outer{
private int time;
private Inner inner;
Outer(int time){
this.time = time;
inner = new Inner();
inner.timeInc();
}
public void printTime(){
System.out.println(Outer.this.time); //101
System.out.println(++time); //102
}
class Inner{
public void timeInc(){
time++;
}
}
}
在Outer构造方法中创建的Inner对象会有一个隐式的引用指向创建它的Outer对象,调用Inner对象的timeInc方法,即会对Outer的time属性进行操作。
案例6:匿名内部类的演示
public class NstInnerClassDemo {
public static void main(String[] args){
/*
* 1)创建了Inter2的一个子类,但是没有名字
* 2)为该子类创建了一个对象,叫o1
* 3)大括号中的为子类的类体
*/
Inter2 o1 = new Inter2(){ }; /*
* 1)创建了Inter2的一个子类,但是没有名字
* 2)为该子类创建了一个对象,叫o2
* 3)大括号中的为子类的类体
*/
Inter2 o2 = new Inter2(){ }; int num = 5;
/*
* 1)创建了Inter1的一个子类,但是没有名字
* 2)为该子类创建了一个对象,叫o3
* 3)大括号中的为子类的类体
*/
Inter1 o3 = new Inter1(){
public void show(){
System.out.println("show");
System.out.println(num);
}
};
o3.show();
}
} interface Inter1{
void show();
}
interface Inter2{ }
Java抽象类、接口和内部类的更多相关文章
- Java抽象类接口、内部类题库
一. 选择题 1. Person类和Test类的代码如下所示,则代码中的错误语句是( C ).(选择一项) public class Person { public String nam ...
- Java核心技术--接口与内部类
接口implement 继承接口,即履行"义务". 接口中所有的方法自动属于public,在接口声明中,不必提供关键字public 接口中决不能含有实例域,也不能在接口中实现方法 ...
- java 抽象类&接口
1,抽象类中有构造函数吗? 有,用于给子类对象进行初始化. 2,抽象关键字不可以和那些关键字共存? private 不行 static 不行 final 不行 final关键字: 1,fina ...
- java抽象类,接口(接口定义,实现接口,instanceof运算符,对象转换)
抽象类 在面向对象的概念中,所有的对象都是通过类来表述的,但并不是所有的类都能够完整的描绘对象,如果一个类中没有包含足够的信息来描绘一类具体的对象,这样的类就是抽象类.抽象类往往用来表征对问题领域进行 ...
- java 抽象类 接口 区别
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 接口 里面 都是抽象方法. 接口里面的 字段 都是 public static fina ...
- 《thinking in java》 接口与内部类
书本上的例子 改编后的. package test2; class A{ interface B{void f();} public class BImp implements B{public vo ...
- Java程序设计8——抽象类、接口与内部类
1 抽象类 当编写一个类时,常常会为该类定义一些方法,这些方法用以描述该类的行为方式,那么这些方法都有具体的方法体.但在某些情况下,某个父类并不需要实现,因为它只需要当做一个模板,而具体的实现,可以由 ...
- Java抽象类、接口、内部类
抽象类的概念: 1.Java中可以定义没有方法体的方法,还方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类: 2.如,shape类计算周长和面积的方法无法确定,那么就可以将这样 ...
- Java入门教程十(抽象类接口内部类匿名类)
抽象类(abstract) 一个类只定义了一个为所有子类共享的一般形式,至于细节则交给每一个子类去实现,这种类没有任何具体的实例,只具有一些抽象的概念,那么这样的类称为抽象类. 在面向对象领域,抽象类 ...
- Java 抽象类与接口
接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法. 抽象类与接口是 Java 语言中对抽象概念进行定义的两种机制,正是由于他们的存在才赋予 Java 强大的面向对象的能力.他们两者之间对 ...
随机推荐
- [hdu4311]Meeting point-1
题意:在整数坐标轴上找一个距离所有给定点距离最小的点. 解题关键:对x和y分别处理,前缀和预处理所有点到最小点的距离,每点的$sum$等于左边的贡献+右边的贡献,最后取$min$即可. 复杂度:$O( ...
- Obama unveils his&nbsp…
LAS VEGAS - Declaring that America's immigration system is broken, President Obama on Tuesday called ...
- ES5.X相关API和技巧汇总
https://blog.csdn.net/laoyang360/article/details/77412668
- Spring入门第十课
Spring表达式语言:SpEL Spring表达式语言(简称SpEL)是一个支持运行时查询和操作对象图的强大的表达式语言. 语法类似于EL:SpEL使用#{...}作为定界符,所有在大括号中的字符都 ...
- Windows Error Codes
http://www.briandunning.com/error-codes/?source=Windows Windows Error Codes List All Error Codes | S ...
- GridView 中RowDataBound 获取绑定后的各个字段的值
protected void GridView_dept_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType ...
- IOSerialize,xml和json,soap序列化器,二进制序列化器,XML序列化器,文件 检查、新增、复制、移动、删除
1 文件夹/文件 检查.新增.复制.移动.删除,2 文件读写,记录文本日志/读取配置文件3 三种序列化器4 xml和json1.文件夹/文件 检查.新增.复制.移动.删除,2 文件读写,记录文本日志/ ...
- The King’s Ups and Downs
有n个高矮不同的士兵,现在要将他们按高,矮依次排列,问有多少种情况. 化简为 n个人,求出可以形成波浪形状的方法数 #include <iostream> #include <cma ...
- List Control控件中及时捕获checkbox被选中的消息的解决方案
转自:http://blog.csdn.net/vycode/article/details/7345073 我的功能需求是:用户可以在List Control里添加item,当无选项被选中(即Che ...
- katalon studio配置git与git项目创建
katalon 是一款在2015年诞生的可以安装在windows.macOS.linux操作系统上,基于selenium 和 Appium 测试框架,并集成了这些框架的优点的自动化测试工具.关于这个工 ...