首页 > 应用开发 > Java > JAVA基础学习- 接口与继承
8.1 接口
在设计LOL的时候,进攻类英雄有两种,一种是进行物理系攻击,一种是进行魔法系攻击
这时候,就可以使用 接口来实现这个效果。
接口就像是一种约定,我们约定某些英雄是物理系英雄,那么他们就一定能够进行物理攻击。
物理攻击接口
创建一个接口 AD ,声明一个方法 physicAttack 物理攻击,但是没有方法体,是一个“ 空”方法
package charactor
;
public
interface
AD
{
//物理伤害
public
void
physicAttack
(
)
;
}
设计一类英雄,能够使用物理攻击
设计一类英雄,能够使用物理攻击,这类英雄在LOL中被叫做AD类:ADHero 继承了Hero 类,所以继承了name,hp,armor等属性
实现某个接口,就相当于承诺了某种约定
所以, 实现了 AD这个接口,就 必须提供AD接口中声明的方法 physicAttack() 实现在语法上使用关键字 implements
package charactor
;
public
class
ADHero
extends
Hero
implements
AD
{
@Override
public
void
physicAttack
(
)
{
System
.out
.
println
(
"进行物理攻击"
)
;
}
}
魔法攻击接口
package charactor
;
public
class
APHero
extends
Hero
implements
AP
{
@Override
public
void
magicAttack
(
)
{
System
.out
.
println
(
"进行魔法攻击"
)
;
}
}
设计一类英雄,既能进行物理攻击,又能进行魔法攻击
一种英雄,能够同时进行物理攻击和魔法攻击 比如伊泽瑞尔,皮城女警凯特琳
package charactor
;
//同时能进行物理和魔法伤害的英雄
public
class
ADAPHero
extends
Hero
implements
AD
,
AP
{
@Override
public
void
magicAttack
(
)
{
System
.out
.
println
(
"进行魔法攻击"
)
;
}
@Override
public
void
physicAttack
(
)
{
System
.out
.
println
(
"进行物理攻击"
)
;
}
}
什么样的情况下该使用接口?
如上的例子,似乎要接口,不要接口,都一样的,那么接口的意义是什么呢
学习一个知识点,是由浅入深得进行的。 这里呢,只是引入了接口的概念,要真正理解接口的好处,需要更多的实践,以及在较为复杂的系统中进行大量运用之后,才能够真正理解,比如在学习了 之后就能进一步加深理解。
刚刚接触一个概念,就希望达到炉火纯青的学习效果,这样的学习目标是不科学的。
8.2 对象转型
明确引用类型与对象类型的概念
首先,明确引用类型与对象类型的概念 在这个例子里,有一个对象 new ADHero(), 同时也有一个引用ad 对象是有类型的, 是ADHero 引用也是有类型的,是ADHero 通常情况下,引用类型和对象类型是一样的 接下来要讨论的类型转换的问题,指的是 引用类型和对象类型不一致的情况下的转换问题
package charactor
;
public
class
Hero
{
public String name
;
protected float hp
;
public
static
void
main
(
String
[
] args
)
{
ADHero ad
=
new
ADHero
(
)
;
}
}
子类转父类(向上转型)
所谓的转型,是指当 引用类型和 对象类型不一致的时候,才需要进行类型转换
父类指向子类对象是一定可以成功的。
package charactor
;
!
[image
.png
]
(https
:
/
/p1
-juejin
.byteimg
.com
/tos
-cn
-i
-k3u1fbpfcp
/
0cd3df775bab463f83dacdbb53e8c5ec
~tplv
-k3u1fbpfcp
-watermark
.image
?
)
public
class
Hero
{
public String name
;
protected float hp
;
public
static
void
main
(
String
[
] args
)
{
Hero h
=
new
Hero
(
)
;
ADHero ad
=
new
ADHero
(
)
;
//类型转换指的是把一个引用所指向的对象的类型,转换为另一个引用的类型
//把ad引用所指向的对象的类型是ADHero
//h引用的类型是Hero
//把ADHero当做Hero使用,一定可以
h
= ad
;
}
}
父类转子类(向下转型)
父类转子类,有的时候行,有的时候不行,所以必须进行强制转换。 强制转换的意思就是 转换有风险,风险自担。

package charactor
;
import charactor1
.Support
;
public
class
Hero
{
public String name
;
protected float hp
;
public
static
void
main
(
String
[
] args
)
{
Hero h
=
new
Hero
(
)
;
ADHero ad
=
new
ADHero
(
)
;
Support s
=
new
Support
(
)
;
h
= ad
;
ad
=
(ADHero
) h
;
//可以成功
h
= s
;
ad
=
(ADHero
)h
;
//指向失败
}
}
没有继承关系的两个类,互相转换
没有继承关系的两个类,互相转换,一定会失败。 虽然ADHero和APHero都继承了Hero,但是彼此没有互相继承关系。

package charactor
;
public
class
Hero
{
public String name
;
protected float hp
;
public
static
void
main
(
String
[
] args
)
{
ADHero ad
=
new
ADHero
(
)
;
APHero ap
=
new
APHero
(
)
;
// 没有继承关系的类型进行互相转换一定会失败,所以会出现编译错误
ad
=
(ADHero
) ap
;
}
}
实现类转换成接口(向上转型)
ad指向的对象是ADHero类型,这个类型实现了AD接口。 实现AD接口的类ADHero一定可以转换为接口;
换句话说, 接口可以指向实现此接口的类。
package charactor
;
public
class
Hero
{
public String name
;
protected float hp
;
public
static
void
main
(
String
[
] args
)
{
ADHero ad
=
new
ADHero
(
)
;
AD adi
= ad
;
}
}

接口转换成实现类(向下转型)
实现类指向接口不一定可以成功, 需要强制转换。

10行: ad引用指向ADHero, 而adi引用是接口类型:AD,实现类转换为接口,是向上转型,所以无需强制转换,并且一定能成功 12行: adi实际上是指向一个ADHero的,所以能够转换成功 14行: adi引用所指向的对象是一个ADHero,要转换为ADAPHero就会失败。
假设能够转换成功,那么就可以使用 magicAttack方法,而adi引用所指向的对象 ADHero是 没有magicAttack方法的。
package charactor
;
public
class
Hero
{
public String name
;
protected float hp
;
public
static
void
main
(
String
[
] args
)
{
ADHero ad
=
new
ADHero
(
)
;
AD adi
= ad
;
ADHero adHero
=
(ADHero
) adi
;
ADAPHero adapHero
=
(ADAPHero
) adi
;
adapHero
.
magicAttack
(
)
;
}
}
instanceof Hero 判断一个引用所指向的对象,是否是Hero类型,或者Hero的子类
8.3 重写
子类可以继承父类的对象方法;在继承后,重复提供该方法,就叫做方法的重写。
又叫覆盖 override
父类Item有一个方法,叫做effect
package property
;
public
class
Item
{
String name
;
int price
;
public
void
buy
(
)
{
System
.out
.
println
(
"购买"
)
;
}
public
void
effect
(
)
{
System
.out
.
println
(
"物品使用后,可以有效果"
)
;
}
}
子类LifePotion继承Item,同时也提供了方法effect
package property
;
public
class
LifePotion
extends
Item
{
public
void
effect
(
)
{
System
.out
.
println
(
"血瓶使用后,可以回-血"
)
;
}
}
调用重写的方法
调用就会执行重写的方法,而不是从父类的方法。 所以LifePotion的effect会打印: "血瓶使用后,可以回-血"
package property
;
public
class
Item
{
String name
;
int price
;
public
void
effect
(
)
{
System
.out
.
println
(
"物品使用后,可以有效果"
)
;
}
public
static
void
main
(
String
[
] args
)
{
Item i
=
new
Item
(
)
;
i
.
effect
(
)
;
LifePotion lp
=
new
LifePotion
(
)
;
lp
.
effect
(
)
;
}
}
如果没有重写这样的机制怎么样?
如果没有重写这样的机制,也就是说LifePotion这个类,一旦继承了Item,所有方法都不能修改了。
但是LifePotion又希望提供一点不同的功能,为了达到这个目的,只能 放弃继承Item,重新编写所有的属性和方法,然后在编写effect的时候,做一点小改动.
这样就增加了开发时间和维护成本
package property
;
public
class
LifePotion
{
String name
;
int price
;
public
void
buy
(
)
{
System
.out
.
println
(
"购买"
)
;
}
//只能放弃继承Item
public
void
effect
(
)
{
System
.out
.
println
(
"血瓶使用后,可以回-血"
)
;
}
8.4 多态
操作符的多态
同一个操作符在不同情境下,具备不同的作用 如果+号两侧都是整型,那么**+代表 数字相加** 如果+号两侧,任意一个是字符串,那么**+代表字符串**
package charactor
;
public
class
Hero
{
public String name
;
protected float hp
;
public
static
void
main
(
String
[
] args
)
{
int i
=
5
;
int j
=
6
;
int k
= i
+j
;
//如果+号两侧都是整型,那么+代表 数字相加
System
.out
.
println
(k
)
;
int a
=
5
;
String b
=
"5"
;
String c
= a
+b
;
//如果+号两侧,任意一个是字符串,那么+代表字符串连接
System
.out
.
println
(c
)
;
}
}
观察类的多态现象
观察类的多态现象:
i1和i2都是Item类型
都调用effect方法
输出不同的结果
多态: 都是同一个类型,调用同一个方法,却能呈现不同的状态
Item.java:
package property
;
public
class
Item
{
String name
;
int price
;
public
void
buy
(
)
{
System
.out
.
println
(
"购买"
)
;
}
public
void
effect
(
)
{
System
.out
.
println
(
"物品使用后,可以有效果 "
)
;
}
//java学习交流:737251827 进入可领取学习资源及对十年开发经验大佬提问,免费解答!
public
static
void
main
(
String
[
] args
)
{
//父类引用指向子类实例
Item i1
=
new
LifePotion
(
)
;
Item i2
=
new
MagicPotion
(
)
;
System
.out
.
print
(
"i1 是Item类型,执行effect打印:"
)
;
i1
.
effect
(
)
;
System
.out
.
print
(
"i2也是Item类型,执行effect打印:"
)
;
i2
.
effect
(
)
;
}
}
LifePotion.java
package property
;
public
class
LifePotion
extends
Item
{
public
void
effect
(
)
{
System
.out
.
println
(
"血瓶使用后,可以回-血"
)
;
}
}
MagicPotion.java
package property
;
public
class
MagicPotion
extends
Item
{
public
void
effect
(
)
{
System
.out
.
println
(
"蓝瓶使用后,可以回魔法"
)
;
}
}
类的多态条件
要实现类的多态,需要如下条件
父类(接口)引用指向子类对象
调用的方法有
那么多态有什么作用呢? 通过比较 与 来进一步了解
package charactor
;
import property
.LifePotion
;
import property
.MagicPotion
;
public
class
Hero
{
public String name
;
protected float hp
;
public
void
useLifePotion
(
LifePotion lp
)
{
lp
.
effect
(
)
;
}
public
void
useMagicPotion
(
MagicPotion mp
)
{
mp
.
effect
(
)
;
}
public
static
void
main
(
String
[
] args
)
{
Hero garen
=
new
Hero
(
)
;
garen
.name
=
"盖伦"
;
LifePotion lp
=
new
LifePotion
(
)
;
MagicPotion mp
=
new
MagicPotion
(
)
;
garen
.
useLifePotion
(lp
)
;
garen
.
useMagicPotion
(mp
)
;
}
}
如果不使用多态,假设英雄要使用血瓶和魔瓶,就需要为Hero设计两个方法. useLifePotion useMagicPotion
除了血瓶和魔瓶还有很多种物品,那么就需要设计很多很多个方法,比如 usePurityPotion 净化药水 useGuard 守卫 useInvisiblePotion 使用隐形药水 等等等等
类的多态-使用多态
如果物品的种类特别多,那么就需要设计很多的方法 比如useArmor,useWeapon等等
这个时候采用多态来解决这个问题 设计一个方法叫做useItem,其参数类型是Item 如果是使用血瓶,调用该方法 如果是使用魔瓶,还是调用该方法 无论英雄要使用什么样的物品, 只需要一个方法即可
package charactor
;
import property
.Item
;
import property
.LifePotion
;
import property
.MagicPotion
;
public
class
Hero
{
public String name
;
protected float hp
;
public
void
useItem
(
Item i
)
{
i
.
effect
(
)
;
}
public
static
void
main
(
String
[
] args
)
{
Hero garen
=
new
Hero
(
)
;
garen
.name
=
"盖伦"
;
LifePotion lp
=
new
LifePotion
(
)
;
MagicPotion mp
=
new
MagicPotion
(
)
;
garen
.
useItem
(lp
)
;
garen
.
useItem
(mp
)
;
}
}
8.5 隐藏
与重写类似,方法的 重写是子类覆盖父类的 对象方法
隐藏,就是子类覆盖父类的 类方法
父类
父类有一个类方法 :battleWin
package charactor
;
public
class
Hero
{
public String name
;
protected float hp
;
//类方法,静态方法
//通过类就可以直接调用
public
static
void
battleWin
(
)
{
System
.out
.
println
(
"hero battle win"
)
;
}
}
子类隐藏父类的类方法
package charactor
;
public
class
ADHero
extends
Hero
implements
AD
{
@Override
public
void
physicAttack
(
)
{
System
.out
.
println
(
"进行物理攻击"
)
;
}
//隐藏父类的battleWin方法
public
static
void
battleWin
(
)
{
System
.out
.
println
(
"ad hero battle win"
)
;
}
public
static
void
main
(
String
[
] args
)
{
Hero
.
battleWin
(
)
;
ADHero
.
battleWin
(
)
;
}
}
8.6 super关键字
准备一个显式提供无参构造方法的父类
在实例化Hero对象的时候,其构造方法会打印“Hero的构造方法 "。
package charactor
;
import property
.Item
;
public
class
Hero
{
String name
;
//姓名
float hp
;
//血量
float armor
;
//护甲
int moveSpeed
;
//移动速度
public
void
useItem
(
Item i
)
{
System
.out
.
println
(
"hero use item"
)
;
i
.
effect
(
)
;
}
public
Hero
(
)
{
System
.out
.
println
(
"Hero的构造方法 "
)
;
}
public
static
void
main
(
String
[
] args
)
{
new
Hero
(
)
;
}
}
实例化子类,父类的构造方法一定会被调用
实例化一个ADHero(), 其构造方法会被调用:其 父类的构造方法也会被调用,并且是父类构造方法 先调用。子类构造方法会默认调用父类的 无参的构造方法。
package charactor
;
public
class
ADHero
extends
Hero
implements
AD
{
@Override
public
void
physicAttack
(
)
{
System
.out
.
println
(
"进行物理攻击"
)
;
}
public
ADHero
(
)
{
System
.out
.
println
(
"AD Hero的构造方法"
)
;
}
public
static
void
main
(
String
[
] args
)
{
new
ADHero
(
)
;
}
}
父类显式提供两个构造方法
分别是无参的构造方法和带一个参数的构造方法
package charactor
;
import property
.Item
;
public
class
Hero
{
String name
;
//姓名
float hp
;
//血量
float armor
;
//护甲
int moveSpeed
;
//移动速度
public
void
useItem
(
Item i
)
{
System
.out
.
println
(
"hero use item"
)
;
i
.
effect
(
)
;
}
public
Hero
(
)
{
System
.out
.
println
(
"Hero的无参的构造方法 "
)
;
}
public
Hero
(
String name
)
{
System
.out
.
println
(
"Hero的有一个参数的构造方法 "
)
;
this
.name
= name
;
}
public
static
void
main
(
String
[
] args
)
{
new
Hero
(
)
;
}
}
子类显式调用父类带参构造方法
package charactor
;
public
class
ADHero
extends
Hero
implements
AD
{
@Override
public
void
physicAttack
(
)
{
System
.out
.
println
(
"进行物理攻击"
)
;
}
public
ADHero
(
String name
)
{
super
(name
)
;
System
.out
.
println
(
"AD Hero的构造方法"
)
;
}
public
static
void
main
(
String
[
] args
)
{
new
ADHero
(
"德莱文"
)
;
}
}
调用父类属性
package charactor
;
public
class
ADHero
extends
Hero
implements
AD
{
int moveSpeed
=
400
;
//移动速度
@Override
public
void
physicAttack
(
)
{
System
.out
.
println
(
"进行物理攻击"
)
;
}
public int
getMoveSpeed
(
)
{
return
this
.moveSpeed
;
}
public int
getMoveSpeed2
(
)
{
return
super
.moveSpeed
;
}
public
static
void
main
(
String
[
] args
)
{
ADHero h
=
new
ADHero
(
)
;
System
.out
.
println
(h
.
getMoveSpeed
(
)
)
;
System
.out
.
println
(h
.
getMoveSpeed2
(
)
)
;
}
}
调用父类方法
ADHero重写了useItem方法,并且在useItem中 通过super调用父类的useItem方法
package charactor
;
import property
.Item
;
import property
.LifePotion
;
public
class
ADHero
extends
Hero
implements
AD
{
int moveSpeed
=
400
;
// 移动速度
@Override
public
void
physicAttack
(
)
{
System
.out
.
println
(
"进行物理攻击"
)
;
}
public int
getMoveSpeed
(
)
{
return
this
.moveSpeed
;
}
public int
getMoveSpeed2
(
)
{
return
super
.moveSpeed
;
}
// 重写useItem,并在其中调用父类的userItem方法
public
void
useItem
(
Item i
)
{
System
.out
.
println
(
"adhero use item"
)
;
super
.
useItem
(i
)
;
}
public
static
void
main
(
String
[
] args
)
{
ADHero h
=
new
ADHero
(
)
;
LifePotion lp
=
new
LifePotion
(
)
;
}
}
Object类是所有类的父类
声明一个类的时候,默认是继承了Object
toString()
Object类提供一个toString方法,所以所有的类都有toString方法。toString()的意思是返回当前对象的 字符串表达。 通过 System.out.println 打印对象就是打印该对象的toString()返回值
package charactor
;
public
class
Hero
{
public String name
;
protected float hp
;
public String
toString
(
)
{
return name
;
}
public
static
void
main
(
String
[
] args
)
{
Hero h
=
new
Hero
(
)
;
h
.name
=
"盖伦"
;
System
.out
.
println
(h
.
toString
(
)
)
;
//直接打印对象就是打印该对象的toString()返回值
System
.out
.
println
(h
)
;
}
}
finalize()
当一个对象没有任何引用指向的时候,它就满足垃圾回收的条件
当它被垃圾回收的时候,它的finalize() 方法就会被调用。
finalize() 不是开发人员主动调用的方法,而是由虚拟机JVM调用的。
equals()
equals() 用于判断两个对象的 内容是否相同
假设,当两个英雄的hp相同的时候,我们就认为这两个英雄相同
System
.out
.
println
(h1
.
equals
(h2
)
)
;
System
.out
.
println
(h1
.
equals
(h3
)
)
;
==
这不是Object的方法,但是用于判断两个对象是否相同 更准确的讲,用于判断两个引用,是否 指向了同一个对象
System
.out
.
println
(h1
==h2
)
;
System
.out
.
println
(h1
==h3
)
;
final修饰类
当Hero被修饰成final的时候,表示Hero不能够被继承;其子类会出现编译错误。
package charactor
;
public final
class
Hero
extends
Object
{
String name
;
//姓名
float hp
;
//血量
}
final修饰方法
Hero的useItem方法被修饰成final,那么该方法在ADHero中,不能够被重写
package charactor
;
import property
.Item
;
public
class
Hero
extends
Object
{
public final
void
useItem
(
Item i
)
{
System
.out
.
println
(
"hero use item"
)
;
i
.
effect
(
)
;
}
public
static
void
main
(
String
[
] args
)
{
new
Hero
(
)
;
}
}
final修饰基本类型变量
final修饰基本类型变量,表示该变量只有一次赋值机会;
16行进行了赋值,17行就不可以再进行赋值了。
package charactor
;
public
class
Hero
extends
Object
{
float hp
;
//血量
public
static
void
main
(
String
[
] args
)
{
final int hp
;
hp
=
5
;
hp
=
6
;
}
}
final修饰引用
final修饰引用:h引用被修饰成final,表示该引用只有 1次指向对象的机会。 所以17行会出现编译错误 但是,依然通过h引用修改对象的属性值hp,因为hp并没有final修饰
package charactor
;
public
class
Hero
extends
Object
{
String name
;
//姓名
float hp
;
//血量
float armor
;
//护甲
int moveSpeed
;
//移动速度
public
static
void
main
(
String
[
] args
)
{
final Hero h
;
h
=
new
Hero
(
)
;
h
=
new
Hero
(
)
;
h
.hp
=
5
;
}
}
常量
常量指的是可以公开,直接访问,不会变化的值 比如 itemTotalNumber 物品栏的数量是6个
public
static final int itemTotalNumber
=
6
;
//物品栏的数量
在类中声明一个方法,这个方法没有实现体,是一个“空”方法
这样的方法就叫抽象方法,使用修饰符“abstract"
当一个类有抽象方法的时候,该类必须被声明为抽象类
抽象类
为Hero增加一个 抽象方法 attack,并且把Hero声明为abstract的。 APHero,ADHero,ADAPHero是Hero的子类,继承了Hero的属性和方法。 但是各自的攻击手段是不一样的,所以继承Hero类后,这些 子类就必须提供不一样的attack方法实现。
Hero.java
package charactor
;
public abstract
class
Hero
{
String name
;
float hp
;
float armor
;
int moveSpeed
;
public
static
void
main
(
String
[
] args
)
{
}
// 抽象方法attack
// Hero的子类会被要求实现attack方法
public abstract
void
attack
(
)
;
}
ADHero.java
package charactor
;
public
class
ADHero
extends
Hero
implements
AD
{
public
void
physicAttack
(
)
{
System
.out
.
println
(
"进行物理攻击"
)
;
}
@Override
public
void
attack
(
)
{
physicAttack
(
)
;
}
}
抽象类可以没有抽象方法
Hero类可以在不提供抽象方法的前提下,声明为抽象类 一旦一个类被声明为抽象类,就不能够被直接实例化
package charactor
;
public abstract
class
Hero
{
String name
;
float hp
;
float armor
;
int moveSpeed
;
public
static
void
main
(
String
[
] args
)
{
//虽然没有抽象方法,但是一旦被声明为了抽象类,就不能够直接被实例化
Hero h
=
new
Hero
(
)
;
}
}
抽象类和接口的区别
package charactor
;
public
interface
AP
{
public
static final int resistPhysic
=
100
;
//resistMagic即便没有显式的声明为 public static final
//但依然默认为public static final
int resistMagic
=
0
;
public
void
magicAttack
(
)
;
}
8.10 内部类
非静态内部类
非静态内部类 BattleScore “战斗成绩”,非静态内部类可以直接在一个类里面定义。
比如:战斗成绩只有在一个英雄对象存在的时候才有意义;所以实例化BattleScore 的时候,必须建立在一个存在的英雄的基础上。 语法: new 外部类().new 内部类() 作为Hero的非静态内部类,是可以直接访问外部类的 private实例属性name的
静态内部类
在一个类里面声明一个静态内部类:比如敌方水晶,当敌方水晶没有血的时候,己方所有英雄都取得胜利,而不只是某一个具体的英雄取得胜利。
与非静态内部类不同, 静态内部类水晶类的实例化 不需要一个外部类的实例为基础,可以直接实例化。语法: new 外部类.静态内部类();
因为没有一个外部类的实例,所以在静态内部类里面 不可以访问外部类的实例属性和方法。除了可以访问外部类的 私有静态成员外,静态内部类和普通类没什么大的区别
package charactor
;
public
class
Hero
{
public String name
;
protected float hp
;
private
static
void
battleWin
(
)
{
System
.out
.
println
(
"battle win"
)
;
}
//java学习交流:737251827 进入可领取学习资源及对十年开发经验大佬提问,免费解答!
//敌方的水晶
static
class
EnemyCrystal
{
int hp
=
5000
;
//如果水晶的血量为0,则宣布胜利
public
void
checkIfVictory
(
)
{
if
(hp
==
0
)
{
Hero
.
battleWin
(
)
;
//静态内部类不能直接访问外部类的对象属性
System
.out
.
println
(name
+
" win this game"
)
;
}
}
}
public
static
void
main
(
String
[
] args
)
{
//实例化静态内部类
Hero
.EnemyCrystal crystal
=
new
Hero
.EnemyCrystal
(
)
;
crystal
.
checkIfVictory
(
)
;
}
}
匿名类
匿名类指的是在 声明一个类的同时实例化它,使代码更加简洁精练。通常情况下,要使用一个接口或者抽象类,都必须创建一个子类。
有的时候,为了快速使用,直接实例化一个抽象类,并“ 当场”实现其抽象方法。 既然实现了抽象方法,那么就是一个新的类,只是这个类,没有命名。 这样的类,叫做匿名类
本地类
本地类可以理解为有名字的匿名类。 内部类与匿名类不一样的是,内部类必须声明在成员的位置,即与属性和方法平等的位置。 本地类和匿名类一样,直接声明在代码块里面,可以是主方法,for循环里等等地方。
package charactor
;
public abstract
class
Hero
{
String name
;
//姓名
float hp
;
//血量
float armor
;
//护甲
int moveSpeed
;
//移动速度
public abstract
void
attack
(
)
;
public
static
void
main
(
String
[
] args
)
{
//与匿名类的区别在于,本地类有了自定义的类名
class
SomeHero
extends
Hero
{
public
void
attack
(
)
{
System
.out
.
println
( name
+
" 新的进攻手段"
)
;
}
}
SomeHero h
=
new
SomeHero
(
)
;
h
.name
=
"地卜师"
;
h
.
attack
(
)
;
}
}
在匿名类中使用外部的局部变量
在匿名类中使用外部的局部变量,外部的局部变量必须修饰为final
package charactor
;
public abstract
class
Hero
{
public abstract
void
attack
(
)
;
public
static
void
main
(
String
[
] args
)
{
//在匿名类中使用外部的局部变量damage 必须修饰为final
int damage
=
5
;
//这里使用本地类AnonymousHero来模拟匿名类的隐藏属性机制
//事实上的匿名类,会在匿名类里声明一个damage属性,并且使用构造方法初始化该属性的值
//在attack中使用的damage,真正使用的是这个内部damage,而非外部damage
//假设外部属性不需要声明为final
//那么在attack中修改damage的值,就会被暗示为修改了外部变量damage的值
//但是他们俩是不同的变量,是不可能修改外部变量damage的
//所以为了避免产生误导,外部的damage必须声明为final,"看上去"就不能修改了
class
AnonymousHero
extends
Hero
{
int damage
;
public
AnonymousHero
(
int damage
)
{
this
.damage
= damage
;
}
public
void
attack
(
)
{
damage
=
10
;
System
.out
.
printf
(
"新的进攻手段,造成%d点伤害"
,
this
.damage
)
;
}
}
Hero h
=
new
AnonymousHero
(damage
)
;
}
8.11 默认方法
什么是默认方法
默认方法是JDK8新特性,指的是接口也可以提供具体方法了,而不像以前,只能提供抽象方法
Mortal 这个接口,增加了一个 默认方法 revive,这个方法有实现体,并且被声明为了 default
package charactor
;
public
interface
Mortal
{
public
void
die
(
)
;
default
public
void
revive
(
)
{
System
.out
.
println
(
"本英雄复活了"
)
;
}
}
为什么会有默认方法
假设没有默认方法这种机制,那么如果要为Mortal增加一个新的方法revive,那么所有实现了Mortal接口的类,都需要做改动。
但是引入了默认方法后,原来的类,不需要做任何改动,并且还能 得到这个默认方法
通过这种手段,就能够很好的扩展新的类,并且做到不影响原来的类
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70010294/viewspace-2847046/ ,如需转载,请注明出处,否则将追究法律责任。