第二阶段 day06 final、 权限 、内部类 、引用类型

第二阶段 day06 final、 权限 、内部类 、引用类型

今日内容

final关键字
权限
内部类
引用类型

教学目标

描述final修饰的类的特点
描述final修饰的方法的特点
能够说出权限修饰符作用范围
说出内部类的概念
能够理解引用类型作为成员变量
能够理解引用类型作为方法参数
能够理解引用类型作为方法返回值类型

第一章 final关键字

1.1 概述

学习了继承后,我们知道,子类可以在父类的基础上改写父类内容,比如,方法重写。那么我们能不能随意的继承
API中提供的类,改写其内容呢?显然这是不合适的。为了避免这种随意改写的情况,Java提供了final 关键字,
用于修饰不可改变内容。
final: 不可改变。可以用于修饰类、方法和变量。
类:被修饰的类,不能被继承。
方法:被修饰的方法,不能被重写。
变量:被修饰的变量,不能被重新赋值。

1.2 使用方式

修饰类

格式如下:

final class 类名 {
}

查询API发现像 public final class String 、public final class Math 、public final class Scanner
等,很多我们学习过的类,都是被final修饰的,目的就是供我们使用,而不让我们所以改变其内容。

修饰方法

格式如下:

修饰符 final 返回值类型 方法名(参数列表) {
	// 方法体
}

重写被 final 修饰的方法,编译时就会报错。

修饰变量

  1. 局部变量——基本类型

基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改。代码如下:

public class FinalDemo1 {
public static void main(String[] args) {
// 声明变量,使用final修饰
final int a;
// 第一次赋值
a = 10;
// 第二次赋值
a = 20; // 报错,不可重新赋值
// 声明变量,直接赋值,使用final修饰
final int b = 10;
// 第二次赋值
b = 20; // 报错,不可重新赋值
}
  1. 局部变量——引用类型

引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再更改。但是不影响对象内部的成员变量值的
修改,代码如下:

public class FinalDemo2 {
public static void main(String[] args) {
// 创建 User 对象
final User u = new User();
// 创建 另一个 User对象
u = new User(); // 报错,指向了新的对象,地址值改变。
// 调用setName方法
u.setName("张三"); // 可以修改
}
}
  1. 成员变量

成员变量涉及到初始化的问题,初始化方式有两种,只能二选一:
显示初始化;

public class User {
final String USERNAME = "张三";
private int age;
}

构造方法初始化。

public class User {
final String USERNAME ;
private int age;
public User(String username, int age) {
this.USERNAME = username;
this.age = age;
}
}

被final修饰的常量名称,一般都有书写规范,所有字母都大写。

第二章 权限修饰符

2.1 概述

在Java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限,

  • public 公共的
  • protected 受保护的
  • default 默认的
  • private 私有的

2.2 不同权限的访问能力

publicprotecteddefaultprivate
同一个类中
同一个包(子类与无关类)
不同包的子类
不同包的无关类

可见,public具有最大权限。private则是最小权限。
编写代码时,如果没有特殊的考虑,建议这样使用权限:

  • 成员变量使用private ,隐藏细节。

  • 构造方法使用public ,方便创建对象。

  • 成员方法使用public ,方便调用方法。

    小贴士:不加权限修饰符,其访问能力与default修饰符相同

第三章 内部类

1.1 概述

什么是内部类
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类B则称为外部类

成员内部类:

  • 成员内部类: 定义在类中方法外的类。

定义格式:

class 外部类{
    class 内部类{
        
    }
}

在描述事物时,若一个事物内部还包含其他事物,就可以使用内部类这种结构。比如,汽车类Car 中包含发动机
类Engine ,这时, Engine 就可以使用内部类来描述,定义在成员位置。
代码举例:

class Car {	// 外部类
    class Engine {
        // 内部类
    }
}

访问特点:

  • 内部类可以直接访问外部类的成员,包括私有成员。
  • 外部类要访问内部类的成员,必须创建内部类的对象

创建内部类对象格式:

外部类名.内部类名 对象名 = new 外部类型().new 内部类型();

访问演示,代码如下:

定义类:

package com.witty.web.demo01neibulei;

/*
    外部类,内部类。
 */
// 外部类
public class Person {
    private boolean live = true;

    // 内部类
    class Heart {
        public void jump() {
            // 直接访问外部类成员
            if (live) {
                System.out.println("心脏还在跳动。");
            } else {
                System.out.println("心脏停止跳动。");
            }
        }
    }



    public boolean isLive() {
        return live;
    }

    public void setLive(boolean live) {
        this.live = live;
    }
}

定义测试类:

package com.witty.web.demo01neibulei;

/*
    访问内部类格式:
        外部类名.内部类名 对象名 = new 外部类型().new 内部类型();
 */
public class InnerDemo {
    public static void main(String[] args) {
        // 创建外部类对象
        Person p = new Person();

        // 创建内部类对象
        Person.Heart heart = p.new Heart();

        // 调用内部类方法
        heart.jump();   // 心脏还在跳动。

        // 调用外部类对象
        p.setLive(false);

        // 调用内部类方法
        heart.jump();   // 心脏停止跳动。
    }
}

内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类名
符 号 。 比 如 , P e r s o n 符号 。 比如,Person PersonHeart.class

1.2 匿名内部类

  • 匿名内部类:是内部类简化的写法。它的不止是一个带有具体实现的父类或者接口 匿名的 子类对象。开发中,最常用到的就是匿名内部类。以接口举例,当你使用接口时,似乎得做以下几步:

    1 定义子类

    2 重写接口中的方法

    3 创建子类对象

    4 调用重写后的方法

我们的目的,最终是为了调用方法,那么能不能简化, 将四步骤化为一步呢?匿名内部类就是这样的快捷方式。

前提:

匿名内部类必须继承一个父类或者实现一个父接口

格式:
new 父类名或者接口名() {
    // 方法重写
    @Override
    public void method() {
        // 执行语句
    }
};

使用方式:

以接口为例,匿名内部类的使用,代码如下:

定义接口:

package com.witty.web.demo02inner;

/*
定义接口
 */
public abstract interface FlyAble {
    // 抽象方法
    public abstract void fly();
}

创建匿名内部类,并调用:

package com.witty.web.demo02inner;

/*
    创建匿名内部类,并调用:
 */
public class InnerDemo {
    public static void main(String[] args) {
        /*
            1 等号右边:是匿名内部类,定义并创建该接口的子类对象
            2 等号左边:是多态接口,接口类型引用指向子类对象
         */
        FlyAble f = new FlyAble() {
            @Override
            public void fly() {
                System.out.println("我学会了飞翔。");
            }
        };

        // 调用fly方法,执行重写后的方法
        f.fly();

    }
}

通常在方法的形式参数是接口或者抽象类时,也可以将匿名内部类作为参数传递。代码如下:

package com.witty.web.demo02inner;

public class InnerDemo02 {
    public static void main(String[] args) {
        /*
            1 等号右边:是匿名内部类,定义并创建该接口的子类对象
            2 等号左边:是多态接口,接口类型引用指向子类对象
         */
        FlyAble f = new FlyAble() {
            @Override
            public void fly() {
                System.out.println("火箭飞入外太空。");
            }
        };

        // 调用showFly 方法
        showFly(f);
    }

    // 定义方法 ,将匿名内部类,作为参数传递到方法参数列表
    public static void showFly(FlyAble f) {
        f.fly();
    }
}

以上两步,也可以简化为一步,代码如下:

package com.witty.web.demo02inner;

public class InnerDemo03 {
    public static void main(String[] args) {
        /*
            1 等号右边:是匿名内部类,定义并创建该接口的子类对象
            2 等号左边:是多态接口,接口类型引用指向子类对象
         */

        showFly(new FlyAble() {
            @Override
            public void fly() {
                System.out.println("火箭飞入外太空。");
            }
        });
    }

    // 定义方法 ,将匿名内部类,作为参数传递到方法参数列表
    public static void showFly(FlyAble f) {
        f.fly();
    }
}

第四章 引用类型用法总结

实际的开发中,引用类型的使用非常重要,也是非常普遍的。我们可以在理解基本类型的使用方式基础上,进一步
去掌握引用类型的使用方式。基本类型可以作为成员变量、作为方法的参数、作为方法的返回值,那么当然引用类
型也是可以的。

4.1 class作为成员变量

在定义一个类Role(游戏角色)时,代码如下:

class Role {
    int id;	// 角色id
    int blood; // 生命值
    String name; // 角色名称
}

使用int 类型表示 角色id和生命值,使用String 类型表示姓名。此时, String 本身就是引用类型,由于使用
的方式类似常量,所以往往忽略了它是引用类型的存在。如果我们继续丰富这个类的定义,给Role 增加武器,穿
戴装备等属性,我们将如何编写呢?

定义武器类:

package com.witty.web.demo03Role;

public class Weapon {
    String name;    // 武器名称
    int hurt;   // 伤害值

    public Weapon() {
    }

    public Weapon(String name, int hurt) {
        this.name = name;
        this.hurt = hurt;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getHurt() {
        return hurt;
    }

    public void setHurt(int hurt) {
        this.hurt = hurt;
    }
}

定义装备类:

package com.witty.web.demo03Role;

public class Armour {
    String name;    // 防御装备名称
    int protect;    // 防御值

    public Armour() {
    }

    public Armour(String name, int protect) {
        this.name = name;
        this.protect = protect;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getProtect() {
        return protect;
    }

    public void setProtect(int protect) {
        this.protect = protect;
    }
}

定义角色类:

package com.witty.web.demo03Role;

public class Role {
    int id;     // 角色id
    int blood;  // 生命值
    String name;    // 角色名称

    // 添加武器
    Weapon wp;

    // 添加防具装备
    Armour ar;

    public Role() {
    }

    public Role(int id, int blood, String name, Weapon wp, Armour ar) {
        this.id = id;
        this.blood = blood;
        this.name = name;
        this.wp = wp;
        this.ar = ar;
    }

    // get set
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getBlood() {
        return blood;
    }

    public void setBlood(int blood) {
        this.blood = blood;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Weapon getWp() {
        return wp;
    }

    public void setWp(Weapon wp) {
        this.wp = wp;
    }

    public Armour getAr() {
        return ar;
    }

    public void setAr(Armour ar) {
        this.ar = ar;
    }

    // 攻击方法
    public void attack() {
        System.out.println("使用: " + wp.getName() + " 造成了 " + wp.getHurt() + " 的伤害。");
    }

    // 添加装备方法
    public void wear() {
        int num = getBlood();
        setBlood(num + ar.getProtect());
        System.out.println("使用: " + ar.getName() + " 添加了 " + ar.getProtect() + " 的血量。");
    }


}

定义测视类:

package com.witty.web.demo03Role;

/*
    测试类
 */
public class Test {
    public static void main(String[] args) {
        // 武器
        Weapon wp = new Weapon("屠龙刀", 999999);

        // 装备
        Armour ar = new Armour("八卦镜", 12313);

        // 设置角色,添加装备
        Role witty = new Role(1001, 1000, "witty", wp, ar);

        // 输出信息以及方法
        System.out.println("id: " + witty.getName() +
                " 血量: " + witty.getBlood() +
                " 姓名:" + witty.getName() +
                " 武器:" + wp.getName() +
                " 装备:" + ar.getName()
                );

        // 添加武器
        witty.attack();

        // 添加装备
        witty.wear();

        // 输出信息以及方法
        System.out.println("id: " + witty.getName() +
                " 血量: " + witty.getBlood() +
                " 姓名:" + witty.getName() +
                " 武器:" + wp.getName() +
                " 装备:" + ar.getName()
        );

    }
}

类作为成员变量时,对它进行赋值的操作,实际上,是赋给它该类的一个对象。

4.2 interface作为成员变量

接口是对方法的封装,对应游戏当中,可以看作是扩展游戏角色的技能。所以,如果想扩展更强大技能,我们在
Role 中,可以增加接口作为成员变量,来设置不同的技能。
定义接口:

package com.witty.web.demo04role;

// 法术攻击接口
public interface FaShuSkill {
    public abstract void faShuAttack();
}

定义角色类:

package com.witty.web.demo04role;

// 角色类
public class Role {
    FaShuSkill fs;

    public void setFaShuSkill(FaShuSkill fs) {
        this.fs = fs;
    }

    // 法术攻击
    public void faShuSkillAttack() {
        System.out.print("发动法术攻击:");
        fs.faShuAttack();
        System.out.println("攻击完成。");
    }
}

定义测试类:

package com.witty.web.demo04role;

/*
    测试类
 */
public class Test {
    public static void main(String[] args) {

        // 创建游戏角色
        Role role = new Role();

        // 设置角色法术技能
        role.setFaShuSkill(new FaShuSkill() {
            @Override
            public void faShuAttack() {
                System.out.println("横扫八荒。");
            }
        });

        // 释放法术
        role.faShuSkillAttack();

        System.out.println("----------------------------");

        // 设置角色法术技能
        role.setFaShuSkill(new FaShuSkill() {
            @Override
            public void faShuAttack() {
                System.out.println("枪出如龙");
            }
        });

        // 释放技能
        role.faShuSkillAttack();

    }
}

我们使用一个接口,作为成员变量,以便随时更换技能,这样的设计更为灵活,增强了程序的扩展性。
接口作为成员变量时,对它进行赋值的操作,实际上,是赋给它该接口的一个子类对象。

4.3 interface作为方法参数和返回值类型

当接口作为方法的参数时,需要传递什么呢?当接口作为方法的返回值类型时,需要返回什么呢?对,其实都是它的子类对象。 ArrayList 类我们并不陌生,查看API我们发现,实际上,它是 java.util.List 接口的实现类。所
以,当我们看见List 接口作为参数或者返回值类型时,当然可以将ArrayList 的对象进行传递或返回。
请观察如下方法:获取某集合中所有的偶数。
定义方法:

// 定义方法
public static List<Integer> getEvenNum(List<Integer> list) {

    // 创建保存偶数的集合
    ArrayList<Integer> evenList = new ArrayList<>();

    // 遍历集合,获取偶数集合,添加到evenList集合中
    for (int i = 0; i < list.size(); i++) {
        if (list.get(i) % 2 == 0) {
            int num = list.get(i);
            evenList.add(num);
        }
    }

    /* 返回偶数集合

        因为getEvenNum方法的返回值类型是List,而ArrayList是List的子类,
        所以evenList可以返回
     */
    return evenList;
}

调用方法:

package com.witty.web.dmeo05even;

import java.util.ArrayList;
import java.util.List;

/*
    获取某集合中所有的偶数
 */
public class Test {
    public static void main(String[] args) {
        // 创建arrayList集合,并添加数字
        ArrayList<Integer> srcList = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            srcList.add(i);
        }

        /*
            获取偶数集合
            因为getEvenNum方法的参数是List,而ArrayList是List的子类,
            所以srcList可以传递
         */
        List list = getEvenNum(srcList);
        System.out.println(list);


    }

    // 定义方法
    public static List<Integer> getEvenNum(List<Integer> list) {

        // 创建保存偶数的集合
        ArrayList<Integer> evenList = new ArrayList<>();

        // 遍历集合,获取偶数集合,添加到evenList集合中
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i) % 2 == 0) {
                int num = list.get(i);
                evenList.add(num);
            }
        }

        /* 返回偶数集合

            因为getEvenNum方法的返回值类型是List,而ArrayList是List的子类,
            所以evenList可以返回
         */
        return evenList;
    }
}

接口作为参数时,传递它的子类对象。
接口作为返回值类型时,返回它的子类对象。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值