接口
接口类似于一种约定,假设约定一些英雄是物理系英雄,那么其一定可以进行物理攻击。
物理攻击接口 物理攻击英雄
//定义物理攻击接口
packagecharactor;public interfaceAD{public voidphysicAttack();
}//定义物理攻击英雄继承该接口
packagecharactor;public class ADHero extends Hero implementsAD{
@Overridepublic voidphysicAttack(){
System.out.println("进行物理攻击");
}
}
魔法攻击接口 魔法攻击英雄
//定义魔法攻击接口
packagecharactor;public interfaceAP{public voidmagicAttack();
}//定义魔法攻击英雄继承该接口
packagecharactor;public class APHero extends Hero implementsAP{public voidmagicAttack(){
@Override
System.out.println("进行魔法攻击");
};
}
物理魔法混合型英雄
packagecharactor;public class ADAPHero extends Hero implementsAP,AD{
@Overridepublic voidmagicAttack() {
System.out.println("进行魔法攻击");
}
@Overridepublic voidphysicAttack() {
System.out.println("进行物理攻击");
}
}
对象转型(对象类型和引用类型不一致的问题)
向上转型(子类转父类)
向上转型一定可以成功,口诀:“把右边当左边来用,看能不能说得通” ,如:把苹果手机当成手机,肯定说的通 Phone p = new Iphone();
向下转型(父类转子类)
有时候行,有时候不行,所以需要强制类型转换
可以转换:需要父类引用变量指向的对象为要转换目标子类对应类型的对象
Hero h=newHero();
ADHero ad= newADHero();
h=ad;
ad= (ADHero) h;
不可以转换 :父类引用变量类型指向的对象和要转换目标子类对应的类型不一致
Hero h =newHero();
ADHero ad= newADHero();
Support s=newSupport();
h=s;
ad= (ADHero)h;
没有继承关系的两个类相互转换一定会失败
接口类可以看作其实现类的父类,因此其转换关系完全满足上述规则。
instanceof 判定一个引用所指向的对象, 如:h instanceof Hero h1 insatnceof ADHero
重写 override(子类继承父类后,重复提供该方法,就叫方法的重写)
多态
操作符多态: +可以作为算数加运算,又可以连接字符串
类多态: 父类引用指向子类对象
条件:1. 父类(接口)指向子类对象 2.调用的方法有重写
packagecharactor;importproperty.Item;importproperty.LifePotion;importproperty.MagicPotion;public classHero {publicString name;protected floathp;public voiduseItem(Item i){
i.effect();
}public static voidmain(String[] args) {
Hero garen= newHero();
garen.name= "盖伦";
LifePotion lp=newLifePotion();
MagicPotion mp=newMagicPotion();
garen.useItem(lp);
garen.useItem(mp);
}
}
隐藏
隐藏是子类覆盖父类的类方法,而重写是子类覆盖父类的对象方法
super 关键字
super作用:调用父类构造方法;调用父类属性;调用父类方法。
Object类 (所有类的父类)
Object提供的相关方法如下所示:
toString() :返回当前对象的字符串表达,通过System.out.println 打印对象就是打印该对象的toString()返回值
finalize():当一个对象没有任何一个引用指向时,会被调用(垃圾回收)
equals() :判断两个对象内容是否相同
== :不是Object提供的方法,其主要判断两个引用是否指向同一个对象
hashCode(): 返回一个对象的哈希值
wait() notify() notifyAll() :线程同步相关方法
getClass(): 返回一个对象的类对象反射相关
final
修饰类:当final修饰类时,表示该类不能被继承
修饰方法:不能被重写
修饰基本类型变量: 表示该变量只有一次赋值机会
修饰引用:表示该引用只有一次指向对象的机会
常量:可以公开,直接访问,不会变化的值 such as : public static final int itemTotalNumber =6;
抽象类
当一个类中存在抽象方法(abstract修饰,该方法没有实现体),那么该类必须被声明为抽象类(同样用abstract修饰)。
一旦一个类被声明为抽象类,那么就不能被实例化
抽象类和接口的区别:
1. 子类只能继承一个抽象类,不能继承多个;子类可以实现多个接口
2. 抽象类可以定义 public,protected,package,private 静态和非静态 final和非final 属性 接口中的属性是能是 public 静态的 final
抽象类和接口都可以有实体方法。 接口中的实体方法,叫做默认方法
默认方法为jdk1.8提供的新特性:
packagecharactor;public interfaceMortal {public voiddie();default public voidrevive() {
System.out.println("本英雄复活了");
}
}
通过默认方法这种手段,就能够很好的扩展新的类,并且做到不影响原来的类
内部类:
非内部静态类: new 外部类().new 内部类() 可以直接访问外部类的private实例属性
内部静态类:new 外部类.静态内部类() 在静态内部类里面不可以访问外部类的实例属性和方法,除了可以访问外部类的私有静态成员外,静态内部类和普通类没什么大的区别
匿名类: 声明一个类的同时实例化它,使代码更加简洁精练。 通常情况下,要使用一个接口或者抽象类,都必须创建一个子类。 有时候,为了快速使用,直接实例化一个抽象类,并“当场”实现其抽象方法。既然实现了抽象方法,那么就是一个新的类,只是这个类,没有命名,这就是匿名类。
public abstract classHero {
String name;//姓名
float hp; //血量
float armor; //护甲
int moveSpeed; //移动速度
public abstract voidattack();public static voidmain(String[] args) {
ADHero adh=newADHero();//通过打印adh,可以看到adh这个对象属于ADHero类
adh.attack();
System.out.println(adh);
Hero h= newHero(){//当场实现attack方法
public voidattack() {
System.out.println("新的进攻手段");
}
};
h.attack();//通过打印h,可以看到h这个对象属于Hero$1这么一个系统自动分配的类名
System.out.println(h);
}
}
本地类:
本地类可以理解为有名字的匿名类,内部类与匿名类不一样的是,内部类必须声明在成员的位置,即与属性和方法平等的位置地类和匿名类一样,直接声明在代码块里面,可以是主方法,for循环里等等地方。
public abstract classHero {
String name;//姓名
float hp; //血量
float armor; //护甲
int moveSpeed; //移动速度
public abstract voidattack();public static voidmain(String[] args) {//与匿名类的区别在于,本地类有了自定义的类名
class SomeHero extendsHero{public voidattack() {
System.out.println( name+ " 新的进攻手段");
}
}
SomeHero h=newSomeHero();
h.name="地卜师";
h.attack();
}
}
在匿名类中使用外部的局部变量时,必须将外部变量声明为final, 原因如下:
匿名类调用外部的局部变量时,相当于将外部局部变量作为一个构造器参数传给了匿名类 Java中只有值传递,也就是说,匿名类得到的是外部局部变量的副本 这个副本的生效范围只在匿名类中,无论怎么更改都不会对外部局部变量造成影响 为了避免开发者混淆,Java干脆不让修改用到的外部局部变量了 这样处理也导致了不方便,外部类后续也无法修改这个局部变量了