day08——经典接口(2)、接口的扩展练习、内部类及扩展练习

【经典接口】

1. 经典接口③:java.lang.Cloneable

用于对象的克隆(复制)

在java.lang.Object根父类中有一个克隆对象的方法:

protected Object clone() throws CloneNotSupportedException

权限修饰符:protected(Object本类、java.lang本包、其他包的子类非静态方法中)

在子类(在克隆对象所在类中)中可以重写这个方法,修改protected为public 

方法()后面有throws CloneNotSupportedException(不支持克隆异常),这个clone()方法很可能报异常

如果希望不报异常——让类实现java.lang.Cloneable接口

2. 经典接口④:java.lang.Iterable接口

实现这个接口允许对象称为“foreach”语句的目标

这个接口有一个抽象方法:Iterator iterator()

实现接口的抽象方法的快捷键是Ctrl+I

foreach是JDK1.5增加的语法,叫做增强for循环

JDK1.5之后,所有数组类型都默认实现这个接口,即支持foreach循环遍历数组

JDK1.5之后,很多集合也都支持

作用:遍历数组和集合容器元素

foreach语法:

        for(元素的类型 元素临时名称:数组或集合容器对象名){

}

        元素临时名称:局部变量名称,自己命名就可以,它就是临时代表一个元素

如,遍历元素就可以改为:

int[] arr = {1,2,3,4,5};
for(int num:arr){
    System.out.println(num);
}

练习1:代码阅读分析结果

interface A{
    int x = 0;
}
class B{
    int x = 1;
}
class C extends B implements A{
    public void pX(){
        System.out.println(x);
    }
    public static void main(String[] args){
        new C().pX();
    }
}

结果:歧义,不通过

改为super.x或者A.x

练习2:代码分析

interface Playable{
    void play();
}
interface Bounceable{
    void play();
}
interface Rollable extends Playable,Bounceable{
    Ball ball = new Ball("Pingpang")
}
class Ball implements Rollable{
    private String name;
    public String getName(){
        return name;
    }
    public Ball(String name){
        this.name = name;
    }
    public void play(){
        ball = new Ball("Football");
        System.out.println(ball.getName());
    }
}

结果:错误

原因:ball是接口中的成员变量,是public static final,不能在play中重新命名

练习3:员工类和数组工具类、排序比较器

(1)声明一个Employee员工类

包含编号、姓名、薪资、年龄、属性私有化

提供get/set,提供无参和有参构造

重写toString,返回员工信息

实现Comparable接口,重写int compareTo(Object emp)方法,按照编号比较大小

(2)编写数组工具类ArrayTools,包含

静态方法public static void sort(Object[] arr):实现给对象数组从小到大排序,要求元素的运行时类型必须实现Comparable接口

静态方法public static void sort(Object[] arr,comparator c):实现给对象数组从小到大排序,需要提供一个Comparator接口的实现类对象,给数组的元素对象排序

静态方法public static void print(Object[] arr):使用foreach循环遍历输出数组元素

(3)在测试类创建Employee[]元素数组,长度为5,创建5个员工对象

按照编号从小到大排序输出

按照编号从大到小排序输出(声明一个类实现Comparator接口,实现按照编号逆序比较大小)

按照薪资从低到高排序输出(声明一个类实现Comparator接口,实现按照薪资比较大小)

按照年龄从大到小排序输出(声明一个类实现Comparator接口,实现按照年龄逆序比较大小)

代码:

Employee类:

public class Employee implements Comparable {
    private int id;
    private String name;
    private double salary;
    private int age;

    public Employee() {
    }

    public Employee(int id, String name, double salary, int age) {
        this.id = id;
        this.name = name;
        this.salary = salary;
        this.age = age;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public int compareTo(Object o) {
        return this.id - ((Employee)o).id;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", salary=" + salary +
                ", age=" + age +
                '}';
    }
}

ArrayTools

import java.util.Comparator;

public class ArrayTools {
    public static void sort(Object[] arr){
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < arr.length-i; j++) {
                Comparable left = (Comparable)arr[j];
                if(left.compareTo(arr[j+1])>0){
                    Object tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = tmp;
                }
            }
        }
    }
    public static void sort(Object[] arr, Comparator c){
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < arr.length-i; j++) {
                if(c.compare(arr[j],arr[j+1])>0){
                    Object tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = tmp;
                }
            }
        }

    }
    public static void print(Object[] arr){
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);

        }
    }
}

ID倒叙

import java.util.Comparator;

public class EmpIdReverseComparator implements Comparator {
    @Override
    public int compare(Object o1, Object o2) {
        Employee e1 = (Employee)o1;
        Employee e2 = (Employee)o2;
        return e2.getId()-e1.getId();
    }
}

薪资顺序

import java.util.Comparator;

public class EmpSalComparator implements Comparator {
    @Override
    public int compare(Object o1, Object o2) {
        Employee e1 = (Employee)o1;
        Employee e2 = (Employee)o2;
        return  Double.compare(e1.getSalary(),e2.getSalary());
    }
}

年龄倒叙

import java.util.Comparator;

public class EmpAgeReverseComparator implements Comparator {
    @Override
    public int compare(Object o1, Object o2) {
        Employee e1 = (Employee)o1;
        Employee e2 = (Employee)o2;
        return e2.getAge() - e1.getAge();
    }
}

Test类

public class Test {
    public static void main(String[] args) {
        Employee[] e = new Employee[5];
        e[0] =new Employee(1,"张三",15000,23);
        e[1] =new Employee(3,"李四",12000,21);
        e[2] =new Employee(4,"王五",14000,23);
        e[3] =new Employee(5,"赵六",11000,24);
        e[4] =new Employee(2,"陈琦",17000,27);
        System.out.println("按id大小排序");
        ArrayTools.sort(e);
        ArrayTools.print(e);
        System.out.println("按id大小逆序");
        ArrayTools.sort(e,new EmpIdReverseComparator());
        ArrayTools.print(e);
        System.out.println("按照薪水排序");
        ArrayTools.sort(e,new EmpSalComparator());
        ArrayTools.print(e);
        System.out.println("按照年龄逆序");
        ArrayTools.sort(e,new EmpAgeReverseComparator());
        ArrayTools.print(e);
    }
}

【内部类知识点】

1. 什么是内部类

定义/声明在另一个类里面的类叫做内部类

2. 为什么要用内部类

总的原则:高内聚,低耦合

好处:

(1)可以突破权限修饰符的限制,内部类和外部类可以互相使用对方所有的(包括私有的)成员

(2)内部类通常情况下和外部类的关系非常紧密,内部类通常都是只为这个外部类服务的,不为其他类服务

(3)外部类的某些私有的成员不希望别的类了解或访问,只想给某个类使用,可以把这个类定义为外部类的内部类

3. 内部类的四种形式

(1)成员内部类(方法外)

静态内部类

非静态内部类

(2)局部内部类(方法体内)

有名字的局部内部类

匿名的内部类

4. 静态内部类

(1)语法格式

【修饰符】class 外部类{

        【修饰符】static class 静态内部类{

        }

}

(2)它是一个类

①它没有自己的字节码文件

有,字节码文字的命名:外部类$静态内部类名

即静态内部类的全名称:包.外部类名.静态内部类名

②可以有哪些修饰符

权限修饰符:public 、缺省

抽象修饰符:abstract

最终修饰符:final

③是否有自己的父类和父接口

可以有自己的父类和父接口,和外部类没有关系

④它可以有哪些成员

类的所有成员都有

(3)它是一个成员

①成员修饰符

权限修饰符:public、缺省、protected、private都可以

静态修饰符:static

最终修饰符:final

②在外部类的使用时,要依赖于外部类

③在外部类的里面使用,直接使用

(4)如何使用静态内部类?

①在外部类的外面

使用静态内部类的静态成员:外部类名.静态内部类名.静态成员

使用静态内部类的非静态成员:静态内部类对象.非静态成员

        创建静态内部类的对象,外部类名.静态内部类名 变量= new 外部类名.静态内部类名()

②在外部类的里面

使用静态内部类的静态成员:静态内部类名.静态成员

使用静态内部类的非静态成员:静态内部类对象.非静态成员

        创建静态内部类的对象,静态内部类名 变量= new 静态内部类名()

(5)在静态内部类中使用外部类成员

静态内部类不可以使用外部类的非静态成员

(6)当静态内部类中定义了和外部类重名的静态属性时怎么办

如果要访问外部类的静态成员,需要加“外部类名.”

5. 非静态内部类

(1)语法格式

【修饰符】class 外部类{

        【修饰符】 class 非静态内部类{

        }

}

(2)它是一个类

①它没有自己的字节码文件

有,字节码文字的命名:外部类$非静态内部类名

即非静态内部类的全名称:包.外部类名.非静态内部类名

②可以有哪些修饰符

权限修饰符:public 、缺省

抽象修饰符:abstract

最终修饰符:final

③是否有自己的父类和父接口

可以有自己的父类和父接口,和外部类没有关系

④它可以有哪些成员

非静态的内部类中,不允许有静态成员

(3)它是一个成员

①成员修饰符

权限修饰符:public、缺省、protected、private都可以

最终修饰符:final

②在外部类的使用时,要依赖于外部类,还要依赖于外部类的对象

③在外部类的里面使用,直接使用

(4)如何使用静态内部类?

①在外部类的外面

使用非静态内部类的非静态成员:非静态内部类对象.非静态成员

        创建静态内部类的对象,外部类对象.new 非静态内部类()

②在外部类的里面

使用静态内部类的静态成员:静态内部类名.静态成员

使用静态内部类的非静态成员:静态内部类对象.非静态成员

        创建静态内部类的对象,静态内部类名 变量= new 静态内部类名()

【注】在外部类的静态成员中,不允许使用非静态内部类

(5)在静态内部类中使用外部类成员

没有限制

(6)当静态内部类中定义了和外部类重名的静态属性时怎么办

如果要访问外部类的非静态成员,需要加“外部类名.this

6. 区别

静态内部类非静态内部类
类角色字节码文件外部类名$内部类名相同
修饰符public 缺省 abstract final相同
父类或父接口可以相同
可以包含的对象所有成员没有静态成员
成员角色修饰符public protected 缺省 private final static没有static
依赖于外部类依赖相同
依赖于外部类的对象不依赖依赖
使用在外部类中使用内部类没有限制在外部类的静态方法中不能使用非静态内部类
在内部类中使用外部类静态内部类中不能使用外部类的非静态成员没有限制
在外部类的外面使用内部类的静态成员外部类名.静态内部类名.静态成员没有
在外部类的外面使用内部类的非静态成员

外部类名.静态内部类 变量名= new 外部类名.静态内部类名();

变量.非静态成员

外部类名 变量1 = new 外部类();

外部类名.非静态内部类 变量名= 变量1.new 非静态内部类名();

变量.非静态成员

重名外部类名.重名的成员外部类名.this.重名成员

练习4:内部类代码阅读题

public class Test{
    public Test(){
        Inner s1 = new Inner();
        s1.a = 10;
        Inner s2 = new Inner();
        s2.a = 20;
        Test.Inner s3 = new Test.Inner();
        System.out.println(s3.a);
    }
    class Inner{
        public int a = 5;
    }
    public static void main(String[] args){
        Test t = new Test();
        Inner r = t.new Inner();
        System.out.println(r.a);
    }
}

 结果:5

原因:实例变量是每一个对象“独立的”

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值