JAVA学习第五天:接口和继承(二)

一、隐藏

重写是子类覆盖父类的对象方法;
隐藏是子类覆盖父类的类方法;

在Hero类中设计静态方法(类方法)battleWin()

public static void battleWin(){
		System.out.println("Hero battle win");
	}

并在子类(ADHero)中隐写:

	public static void battleWin(){
		System.out.println("ADHero battle win");
	}	
	public static void main(String[] args){
		Hero.battleWin();//静态类方法,可以直接通过类调用
		ADHero.battleWin();//静态方法(类方法),通过类调用无需实例化
		//问题:
		Hero h = new Hero();
		h.battleWin();//调用的是父类的方法,还是子类的方法?
	}

输出:

Hero battle win
ADHero battle win
Hero battle win

结果显示,虽然h指向的是对象ADHero,但h的类型为Hero,所以调用的是父类的方法。
并且此时eclipse还会警告提示,要么将改引用的对象、要么改类方法为静态方法。

二、super关键字

讲道理有点懵
1 实例化子类的方法时,父类的构造方法一定会被调用
2 子类使用关键字super显示的调用父类带参的构造方法

作为子类,无论如何都会调用父类的构造方法。默认调用父类的无参的构造方法。但是,当父类没有无参构造方法的时候( 提供了有参构造方法,并且不显示提供无参构造方法),子类就会抛出异常,因为它尝试去调用父类的无参构造方法。这个时候,必须通过super去调用父类声明的、存在的、有参的构造方法。

public ADHero(String name,float hp){
		super(name,hp); //直接调用了父类的构造方法
		
		System.out.println("ADHero 的有参构造方法(super)");
	}
2.调用父类属性

通过super调用父类的moveSpeed属性,以及调用
ADHero提供的属性moveSpeed;

public int getMoveSpeed(){
		return this.moveSpeed;//子类的移动方法,设为400
	}
	public int getMoveSpeed2(){
		return super.moveSpeed;//父类的移动方法为定义,默认为0
	}

运行代码块结果如下:

System.out.println(delaiwen.getMoveSpeed()); //400 ,子类的定义的400
System.out.println(delaiwen.getMoveSpeed2());//0,父类默认的速度
2.调用父类方法

这里懵了,先不管

三、Object类

Object类是所有类的父类,声明一个类时,默认继承了Object;

1. toString

Object类提供一个toString方法,所以所有的类都有toString方法,toString()的意思是返回当前对象的字符串表达通过 System.out.println 打印对象就是打印该对象的toString()返回值。

System.out.println(h,toString());//h@139a55
System.out.println(h);//结果是一样的
2. finalize()

当一个对象没有任何引用指向的时候,它就满足垃圾回收的条件.当它被垃圾回收的时候,它的finalize() 方法就会被调用。finalize() 不是开发人员主动调用的方法,而是由虚拟机JVM调用的。

public void finalize(){
		System.out.println("这个英雄正在被回收");
	}

结果:

...
这个英雄正在被回收
这个英雄正在被回收
这个英雄正在被回收
这个英雄正在被回收
这个英雄正在被回收
这个英雄正在被回收
3. equals()

equals() 用于判断两个对象的内容是否相同,

/*instanceof 是 Java 的一个二元操作符,类似于 ==,>,< 等操作符。
instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
*/
 public boolean equals(Object o){//传参为类 o
        if(o instanceof Hero){//如果o是Hero的子类
            Hero h = (Hero) o;//强制转换,子类转父类
            return this.hp == h.hp;
        }
        return false;
4. ==

用于判断两个引用,是否指向了同一个对象

 System.out.println(h1==h2);
5. hashCode()

hashCode方法返回一个对象的哈希值

6. 线程同步
7. getClass()

四、final

final修饰类,方法,基本类型变量,引用的时候分别有不同的意思。

1. final修饰类

当Hero被修饰成final的时候,表示Hero不能够被继承,其子类会出现编译错误。

public final class Hero{
}
2. final修饰方法

如果一个方法被修饰成final,那么该方法在子类中不能够被重写。

 public final void useItem(Item i){
 ...
    }   
3. final修饰基本变量

final修饰基本类型变量,表示该变量只有一次赋值机会 。

final int hp;
4. final修饰引用

final修饰引用,h引用被修饰成final,表示该引用只有1次指向对象的机会。

final Hero h;
5. 常量

常量指的是可以公开,直接访问,不会变化的值
比如 itemTotalNumber 物品栏的数量是6个

   public static final int itemTotalNumber = 6;//物品栏的数量

五、抽象类

1. 抽象方法

在类中声明一个方法,这个方法没有实现体,是一个“空”方法 。这样的方法就叫抽象方法,使用修饰符“abstract" 。当一个类有抽象方法的时候,该类必须被声明为抽象类。
当为Hero增加一个abstract方法attack,并把Hero声明为abstract。(抽象类可以没有抽象方法)

package charactor;
public abstract class Hero{
	String name;
	float hp;
	float armor;
	int moveSpeed;
	public abstract void attack();	
	public static void  main(String[] arg){
	}
}

在Hero类中增加了abstract抽象方法attack,在子类中必须实现该方法。

public void attack() {
		// TODO Auto-generated method stub
		
	}

当一个类被声明为抽象类时就不能够被实例化。

2. 抽象类和接口的区别

区别1:

  • 子类只能继承一个抽象类,不能继承多个
  • 子类可以实现多个接口

区别2:

  • 抽象类可以定义
    public,protected,package,private
    静态和非静态属性
    final和非final属性
  • 接口中声明的属性
    只能是
    public
    静态
    final的

六、内部类

1. 非静态内部类

非静态内部类可以直接在一个类里面定义,
实例化的时候,必须建立在一个存在的类的基础
语法: new 外部类().new 内部类()

2. 静态内部类

非静态内部类不同,静态内部类的实例化 不需要一个外部类的实例为基础,可以直接实例化
语法:new 外部类.静态内部类();

3. 匿名类

直接实例化一个抽象类,并“当场”实现其抽象方法。既然实现了抽象方法,那么就是一个新的类,只是这个类,没有命名。这样的类,叫做匿名类

4.本地类

本地类可以理解为有名字的匿名类。
内部类与匿名类不一样的是,内部类必须声明在成员的位置,即与属性和方法平等的位置。本地类和匿名类一样,直接声明在代码块里面,可以是主方法,for循环里等等地方。
创建一个Item的匿名类,Item有抽象方法disposable(),

package property;

public abstract class Item {
	public String name;
	int price;
	
	public abstract boolean disposable();
	
	public static void main(String[] args){
		Item ig = new Item(){
			public boolean disposable(){
				return false;
			}
		};
		System.out.println(ig);
		System.out.println(ig.disposable());
	}
}

结果:

property.Item$1@1db9742
false

七、默认方法

默认方法是JDK8新特性,指的是接口也可以提供具体方法了,而不像以前,只能提供抽象方法。
Mortal 这个接口,增加了一个默认方法 revive,这个方法有实现体,并且被声明为了default。

package charactor;
public interface Mortal {
	public void die();
	default public void revive(){
		System.out.println("本英雄复活了");
	}
}

假设没有默认方法这种机制,那么如果要为Mortal增加一个新的方法revive,那么所有实现了Mortal接口的类,都需要做改动。
但是引入了默认方法后,原来的类,不需要做任何改动,并且还能得到这个默认方法
通过这种手段,就能够很好的扩展新的类,并且做到不影响原来的类
如果某个类同时实现了两个接口,且都有同样的默认方法,那么该类的实例化对象调用接口中的该默认方法时,必须重写该方法。不然会混淆到底实现的是哪个接口的方法?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值