【Java之旅】 11. 抽象类与接口

【Java之旅】 11. 抽象类与接口

11.1 final关键字

在Java中,final关键字可以用于修饰类、方法和变量

a. 修饰类

当我们用final关键字去修饰一个类时,那么这个类就会断子绝孙。他将不能被其他的类继承.

public class  Finaltest
{
	public static void main(String[] args) 
	{
		Players kupurk = new Players();
		System.out.println(kupurk.id);
	}
}

final class Players
{
	final int id = 1;
	//this.id = 1;
}

class Attackers extends Players
{
}

报错

Finaltest.java:16: 错误: 无法从最终Players进行继承
class Attackers extends Players
                        ^
1 个错误

b. 修饰方法

“ 使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的Java版本中,不需要使用final方法进行这些优化了。”-----《Java编程思想》

final意为 “最终的”,与final修饰后的类一样,在父类中被final修饰过的方法无法被子类覆盖,所以子类不可,无法也就是说被final修饰后的方法方法不能被子类重写,但重载多个final是可行的。

class Players
{
	private int id;
	public final void getId(int id)
	{
		this.id= id;
	}
}

class Attackers extends Players
{
	public final void getId(int id)
	{
		this.id= id+1;
	}
}
public class  Finaltest
{
	public static void main(String[] args) 
	{
		Players kupurk = new Players();
		kupurk.getId(10);
		System.out.println(kupurk.id);
	}
}

报错

Finaltest.java:22: 错误: Attackers中的getId(int)无法覆盖Players中的getId(int)
        public final void getId(int id)
                          ^
  被覆盖的方法为final

所以子类无法继承得到父类final修饰的方法

c. 修饰变量(final主要用于修饰变量)

final修饰的变量,只能赋值一次,并且不能被修改

final修饰的成员属性有两种赋值方式:

①在变量声明的时候初始化;

class Players
{
	final int id = 1;
	public String toString()
	{
		return "id = "+ id;
	}
}

②在声明变量的时候不赋初值,但是要在这个变量所在的类的所有的构造函数中对这个变量赋初值。

class Players
{
	final int id;
	public Players()
	{
		id = 12121;//在构造方法中对final修饰的属性进行赋值
	}
	public String toString()
	{
		return "id = "+ id;
	}
}

d. final修饰的变量是常量吗?

final 修饰的变量与常量很相似,都只能一次赋值并无法改变。

但final修饰的变量也是有生命期的,如果我们将final修饰在一个局部变量身上,那么这个变量只能作用与一个局部,

所以final修饰的变量是可以提前结束生命的

而const修饰的变量是常量,是全局变量。

但如果用static final修饰 那么这就于常量等价了

11.2 权限修饰符

权限修饰符可以用于修饰 类、成员属性、成员方法

类:只能用public 或者 默认修饰,不能用private和protected修饰

成员属性:被protected修饰的变量在类外可以被访问(但必须是在同一个包中进行访问),

成员方法:

加上默认状态(即缺省)一共有四种

  1. public
  2. protected
  3. private
  4. 缺省

11.3 抽象(Abstract)

a. 抽象类

前几篇博客我们说过,父类的特征是他所有子类特征的交集。

那么当我们在刚开始写类的时候,我们不知道这个类到底该怎么写,

例如动物叫,我们不知道哪些动物i叫,毕竟每个动物的叫法都不一样。

所以这时候我们可以将类定义为抽象类,日后在子类中进行修饰。

抽象类是用abstract关键字修饰过的类

它的用法是 (public) abstract class 类名{}

抽象类不是具体存在的类,或者说这样的类还不够完善,不能直接使用new关键字调用其构造器生成该类的对象。

抽象类虽然不能实例化对象(不能被构造),类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。

public class AbstractTest
{
	public static void main(String[] args) 
	{
		Friend kupurk = new Friend(kupurk,1);
		System.out.println(kupurk);
	}
}

abstract class Friend
{
	String name;
	int id;
	public Friend(String name,int id)
	{
		System.out.println("抽象类构造!");
		this.name = name;
		this.id = id;
	}
	public String toString()
	{
		return "[" + name + ", "+ id + "]";
	}
}

编译不通过:

E:\工具\Markdown\输出\EditPlus_out\Abstract and Connector>javac AbstractTest.java
AbstractTest.java:5: 错误: Friend是抽象的; 无法实例化
                Friend kupurk = new Friend(kupurk,1);
                                ^
1 个错误

所以抽象类我们无法构造,因此抽象类必须被继承,这也是抽象类存在的意义,用子类去解释抽象类。

ps(抽象类中也有构造方法,但他的用处并不是拿来实例化自己的(因为他压根就没法实例化自己),而是用于将这个特征留给子类,子类并不是抽象的,肯定需要构造啊,需要对父类构造方法进行重写)

abstract不能和哪些关键字共存

a:final 冲突(待补充)

b:private 冲突(待补充)

c:static 无意义(待补充)

a. 抽象方法

用abstract修饰的方法称为 抽象方法。

抽象方法只有方法声明,而没有方法体,因此他不能被调用,只能而且必须要让子类去对抽象方法进行重写。

因为要实现多态,静态绑定时,只能绑定到父类,而父类中的方法是抽象方法,没有方法体,

动态绑定时,子类也没有对该抽象方法进行重写。

最终就会导致编译不通过报错

抽象方法只能存在于抽象类中

在Java中一个没有方法体的方法应该定义为抽象方法 而类中如果有抽象方法,则必须定义为抽象类

抽象方法没有方法体,没有花括号 ”{}“ ,空方法拥有花括号,不要把空方法和抽象方法靠混淆了

11.4 接口(Interface)

接口的概念与抽象类很相似,

不过有一点不相似的是:接口是百分之百的抽象,而抽象类可以不是百分之白的抽象

意思就是说接口内的方法必须全部都是抽象方法,抽象类中的方法运行存在有方法体的方法

又因为接口是抽象的,因此接口和抽象类一样无法实例化

抽象类一定要有一个子类去实现它,接口也一样需要一个类去实现接口

实现方法

(public) class <类名> implements <接口名>;

在这个实现类中,一定要完全实现接口内所有的抽象方法,否则编译不通过

在实现类中可以自己添加除了接口之外的方法,这是可行的

用接口的定义还有包的概念,依葫芦画瓢写了一个我和我朋友恰饭的程序

主类

package com.main;

import com.Users.Kupurk;
import com.Users.Mo;
import com.Users.Sock;
import com.Users.move.ICanjuIplm;

public class Test {
    public static void main(String[] args) {
        Kupurk kupurk = new Kupurk();
        Mo mo = new Mo();
        Sock sock = new Sock();
        ICanjuIplm icanju = new ICanjuIplm();
        icanju.setIperson(kupurk);
        icanju.eat();
        icanju.setIperson(mo);
        icanju.eat();
        icanju.setIperson(sock);
        icanju.eat();
    }
}

用户信息

package com.Users;

public interface Iperson {
    void eat();
}

public class Kupurk implements Iperson {
    @Override
    public void eat()
    {
        System.out.println(" kupurk 狂吃");
    }
}


public class Mo implements Iperson {
    @Override
    public void eat()
    {
        System.out.println(" Mo 正在恰饭");
    }
}

public class Sock implements Iperson{
    @Override
    public void eat()
    {
        System.out.println(" 袜子 正在干饭");
    }
}



用户行为

package com.Users.move;
import com.Users.Iperson;

public interface ICanju {
    void eat();
}


public class ICanjuIplm implements ICanju
{
    private Iperson iperson;
    public void setIperson(Iperson iperson)
    {
        this.iperson = iperson;
    }
    @Override
    public void eat() {
        iperson.eat();
    }
}

输出结果
在这里插入图片描述

成功了,第一次用IDEA分包写代码,泪目

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值