栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java SE之基础篇(十四)——匿名内部类与API

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java SE之基础篇(十四)——匿名内部类与API

前言

  上篇文章我们给大家介绍了Java三大特性中的多态与接口,另外还介绍了java开发中常用到的抽象。最后通过一个综合案例加以说明,最后通过XMind将整篇文章的知识点通过思维导图的方式归纳给大家。本文给大家介绍的是Java中比较特殊的类——匿名内部类。首先给大家介绍的是java中的参数传递。

一、参数传递 1、类名作为形参和返回值

   我们一般在参数传递的时候,更多是通过类名作为方法进行传递的形参。其中方法的形参是类名,其实需要的是该类的对象。实际传递的是该对象的【地址值】。另外一种就是通过类名作为方法的返回值。方法的返回值是类名,其实返回的是该类的对象,而方法的返回值是类名,其实返回的是该类的对象。具体我们以一个案例加以说明,具体实现如下:
   首先我们实现Cat类,具体实现如下:

class Cat {
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

   其次实现的是CatOperator类,具体实现如下:

class CatOperator {
    public void useCat(Cat c) { //Cat c = new Cat();
        c.eat();
    }
    public Cat getCat() {
        Cat c = new Cat();
        return c;
    }
}

   最后就是通过一个测试类将其进行简单的测试,具体实现如下:

public class CatDemo {
    public static void main(String[] args) {
        //创建操作类对象,并调用方法
        CatOperator co = new CatOperator();
        Cat c = new Cat();
        co.useCat(c);

        Cat c2 = co.getCat(); //new Cat()
        c2.eat();
    }
}

   该案例具体执行的结果如下所示:

2、抽象类作为形参和返回值

  接下来,我们给大家介绍的就是抽象类作为形参和返回值。当方法的形参是抽象类名的时候,其实需要的是该抽象类的子类对象。当方法的返回值是抽象类名的时候,其实返回的是该抽象类的子类对象。我们同样地通过一个案例加以说明,具体实现如下:
  为了后期我们写作的方便,这里就将所有的类直接写在代码框内,大家在运行的时候,如果是Eclipse那么可以直接粘贴(虽然博主极不愿意大家这么干,但是相信一定有这样的读者)就可以,但是如果是IDEA,那么你就必须一个类一个类的粘贴,否则无法运行,会出现编译错误的情况,所以希望大家练习的时候,一定要多加注意。

abstract class Animal {
    public abstract void eat();
}
class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
class AnimalOperator {
    public void useAnimal(Animal a) { //Animal a = new Cat();
        a.eat();
    }
    public Animal getAnimal() {
        Animal a = new Cat();
        return a;
    }
}
class AnimalDemo {
    public static void main(String[] args) {
        //创建操作类对象,并调用方法
        AnimalOperator ao = new AnimalOperator();
        Animal a = new Cat();
        ao.useAnimal(a);

        Animal a2 = ao.getAnimal(); //new Cat()
        a2.eat();
    }
}

  该案例具体执行的结果如下:

3、接口名作为形参和返回值

  最后给大家介绍的就是接口名作为形参和返回值的相关问题。当方法的形参是接口名的时候,其实需要的是该接口的实现类对象;而当方法的返回值是接口名的时候,其实返回的是该接口的实现类对象。具体代码的实现如下:

interface Jumpping {
    void jump();
}
class JumppingOperator {
    public void useJumpping(Jumpping j) { //Jumpping j = new Cat();
        j.jump();
    }
    public Jumpping getJumpping() {
        Jumpping j = new Cat();
        return j;
    }
}
class Cat implements Jumpping {
    @Override
    public void jump() {
        System.out.println("猫可以跳高了");
    }
}
JumppingDemo {
    public static void main(String[] args) {
        //创建操作类对象,并调用方法
        JumppingOperator jo = new JumppingOperator();
        Jumpping j = new Cat();
        jo.useJumpping(j);

        Jumpping j2 = jo.getJumpping(); //new Cat()
        j2.jump();
    }
}

  该案例具体执行的结果如下:

二、内部类 1、内部类的基本使用

  在日常的开发中,我们经常会用到内部类,内部类即为在一个类中定义一个类。举例:在一个类A的内部定义一个类B,类B就被称为内部类。内部类的相关定义如下:


class Outer {
    public class Inner {
        
    }
}

  内部类的访问特点为内部类可以直接访问外部类的成员,包括私有,另外外部类要访问内部类的成员,必须创建对象。我们通过一个简单的案例来初步了解内部类的相关应用,具体实现如下:

public class Outer {
    private int num = 10;
    public class Inner {
        public void show() {
            System.out.println(num);
        }
    }
    public void method() {
        Inner i = new Inner();
        i.show();
    }
}

  这里的测试类留给读者自己实现哈,我们该代码只给出了内部类的格式。接下来给大家介绍的就是成员内部类的具体内容。

2、成员内部类

  在类中方法,其实成员内部类的定义位置跟成员变量是一个位置;其格式为:外部类名.内部类名 对象名 = 外部类对象.内部类对象;具体代码为:Outer.Inner oi = new Outer().new Inner();成员内部类我们一般推荐使用将一个类,设计为内部类的目的,大多数都是不想让外界去访问,所以内部类的定义应该私有化,私有化之后,再提供一个可以让外界调用的方法,方法内部创建内部类对象并调用。我们通过一个具体小案例来给大家演示内部类应该如何使用的,具体实现如下:

class Outer {
    private int num = 10;
    private class Inner {
        public void show() {
            System.out.println(num);
        }
    }
    public void method() {
        Inner i = new Inner();
        i.show();
    }
}
public class InnerDemo {
    public static void main(String[] args) {
		//Outer.Inner oi = new Outer().new Inner();
		//oi.show();
        Outer o = new Outer();
        o.method();
    }
}

  该案例具体执行的结果如下:

3、局部内部类

  局部内部类定义位置是在方法中定义的类;并且用局部内部类定义方式外界是无法直接使用,需要在方法内部创建对象并使用,另外该类可以直接访问外部类的成员,也可以访问方法内的局部变量。具体用代码演示如下:

class Outer {
    private int num = 10;
    public void method() {
        int num2 = 20;
        class Inner {
            public void show() {
                System.out.println(num);
                System.out.println(num2);
            }
        }
        Inner i = new Inner();
        i.show();
    }
}
public class OuterDemo {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}

  具体执行的结果如下:

4、匿名内部类

  我们在用匿名内部类的前提是存在一个类或者接口,这里的类可以是具体类也可以是抽象类。匿名内部类的格式如下:

new 类名 ( ) {  重写方法 }    new  接口名 ( ) { 重写方法 }
new Inter(){
    @Override
    public void method(){}
} 

  其实匿名内部类的本质就是一个继承了该类或者实现了该接口的子类匿名对象。当然,匿名内部类还有一些细节:比如匿名内部类可以通过多态的形式接受:

Inter i = new Inter(){
  @Override
    public void method(){
        
    }
}

  当然匿名内部类也可以直接调用方法,具体过程如下:

interface Inter{
    void method();
}

class Test{
    public static void main(String[] args){
        new Inter(){
            @Override
            public void method(){
                System.out.println("我是匿名内部类");
            }
        }.method();	// 直接调用方法
    }
}

  接下来就是给大家介绍匿名内部类在开发中的使用。我们一般在匿名内部类在开发中的使用的时候,当发现某个方法需要,接口或抽象类的子类对象,我们就可以传递一个匿名内部类过去,来简化传统的代码。具体我们通过一个案例加以说明,具体代码实现如下:

interface Jumpping {
    void jump();
}
class Cat implements Jumpping {
    @Override
    public void jump() {
        System.out.println("猫可以跳高了");
    }
}
class Dog implements Jumpping {
    @Override
    public void jump() {
        System.out.println("狗可以跳高了");
    }
}
class JumppingOperator {
    public void method(Jumpping j) { //new Cat();   new Dog();
        j.jump();
    }
}
class JumppingDemo {
    public static void main(String[] args) {
        //需求:创建接口操作类的对象,调用method方法
        JumppingOperator jo = new JumppingOperator();
        Jumpping j = new Cat();
        jo.method(j);

        Jumpping j2 = new Dog();
        jo.method(j2);
        System.out.println("--------");

        // 匿名内部类的简化
        jo.method(new Jumpping() {
            @Override
            public void jump() {
                System.out.println("猫可以跳高了");
            }
        });
		// 匿名内部类的简化
        jo.method(new Jumpping() {
            @Override
            public void jump() {
                System.out.println("狗可以跳高了");
            }
        });
    }
}

  该代码执行的结果如下:

  至此,我们内部类的全部知识给大家介绍完毕,接下来再给大家介绍一部分我们在Java中经常使用到的API方法。

三、常用API

  我们在Java开发中有的时候会不得不用一些计算方法,这个时候我们就会想到Math()方法。Math 包含执行基本数字运算的方法。Math类中无构造方法,但内部的方法都是静态的,则可以通过 类名.进行调用。以下就是我们常用的Math类的一些方法:

  我们可以通过一个小的案例加以说明其用法以及应用场景:

public class SystemDemo {
    public static void main(String[] args) {
        // 获取开始的时间节点
        long start = System.currentTimeMillis();
        for (int i = 1; i <= 10000; i++) {
            System.out.println(i);
        }
        // 获取代码运行结束后的时间节点
        long end = System.currentTimeMillis();
        System.out.println("共耗时:" + (end - start) + "毫秒");
    }
}

  该案例具体执行的结果如下:

  这里需要说明的是:这个运行结果与我们电脑配置有关,如果我们的电脑不一样,运行出来的时间数也会有所差异的。接下来就是System中的一些常用方法,具体如下:

  Object 是类层次结构的根,每个类都可以将 Object 作为超类。所有类都直接或者间接的继承自该类,换句话说,该类所具备的方法,所有类都会有一份;这里需要说明的是:如果我们想看对应方法的相应源码在IDEA中只需要快捷键Ctrl+B即可。在开发中,我们往往会重写toString方法,在IDEA中快捷是Alt + Insert 选择toString,当然,我们也可以通过在类的空白区域,右键 -> Generate -> 选择toString也是可以的。重写toString的方式是为了以良好的格式,更方便的展示对象中的属性值。我们通过一个案例来加以说明,具体实现如下:
  首先我们实现的是Student类,具体实现如下:

class Student extends Object {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}

  最后我们实现其测试类,具体实现如下:

public class ObjectDemo {
    public static void main(String[] args) {
        Student s = new Student();
        s.setName("刘涛");
        s.setAge(30);
        System.out.println(s); 
        System.out.println(s.toString()); 
    }
}

  该案例执行的结果如下:

  另外,就是我们在日常开发的时候都会进行用equlas()对对象进行比较,其作用是为了用于对象之间的比较,返回true和false的结果。例如我们常常会s1.equals(s2); s1和s2是两个对象。当然如果我们不希望比较对象的地址值,想要结合对象属性进行比较的时候,那么我们就需要重写equals。重写equals也有两种方式,IDEA中的快捷键为alt + insert 选择equals() and hashCode(),IntelliJ Default,一路next,finish即可;也可以在类的空白区域,右键 -> Generate -> 选择equals() and hashCode(),具体案例实现如下:

class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public boolean equals(Object o) {
        //this -- s1
        //o -- s2
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o; //student -- s2

        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }
}
public class ObjectDemo {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.setName("林青霞");
        s1.setAge(30);

        Student s2 = new Student();
        s2.setName("林青霞");
        s2.setAge(30);

        //需求:比较两个对象的内容是否相同
        System.out.println(s1.equals(s2));
    }
}

  具体执行的结果如下:

  我们之前一定学过冒泡排序,那么你是否真正的掌握冒泡排序的原理呢,冒泡排序:一种排序的方式,对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放在后面,依次对所有的数据进行操作,直至所有数据按要求完成排序。如果有n个数据进行排序,总共需要比较n-1次;每一次比较完毕,下一次的比较就会少一个数据参与。具体用代码实现冒泡排序如下:

public class ArrayDemo {
    public static void main(String[] args) {
        //定义一个数组
        int[] arr = {24, 69, 80, 57, 13};
        System.out.println("排序前:" + arrayToString(arr));

        // 这里减1,是控制每轮比较的次数
        for (int x = 0; x < arr.length - 1; x++) {
            // -1是为了避免索引越界,-x是为了调高比较效率
            for (int i = 0; i < arr.length - 1 - x; i++) {
                if (arr[i] > arr[i + 1]) {
                    int temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;
                }
            }
        }
        System.out.println("排序后:" + arrayToString(arr));

    }

    //把数组中的元素按照指定的规则组成一个字符串:[元素1, 元素2, ...]
    public static String arrayToString(int[] arr) {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0; i < arr.length; i++) {
            if (i == arr.length - 1) {
                sb.append(arr[i]);
            } else {
                sb.append(arr[i]).append(", ");
            }
        }
        sb.append("]");
        String s = sb.toString();
        return s;
    }
}

  我们输入这个无序数组{24, 69, 80, 57, 13},通过冒泡排序排序之后的结果如下:

  给大家介绍冒泡排序的原理以及实现的原因是为了我们在开发中经常会用到一个工具类Arrays,它的原理就是通过冒泡排序的原理实现排序的,其常用的方法如下:

  该方法在使用的时候需要我们注意的是:其构造方法用 private 修饰;而成员用 public static 修饰。

四、知识汇总

  文章最后,我们将本文介绍的所有知识点通过xmind做一个总结;具体知识点总结如下:

总结

  上篇文章我们给大家介绍了Java三大特性中的多态与接口,另外还介绍了java开发中常用到的抽象。最后通过一个综合案例加以说明,最后通过XMind将整篇文章的知识点通过思维导图的方式归纳给大家。本文给大家介绍的是Java中比较特殊的类——匿名内部类。主要介绍了参数的传递以及各种内部类,包括内部类的基本使用、成员内部类、局部内部类以及我们经常使用的匿名内部类,并且通过大量案例加以说明。另外还介绍了常用的API,并且重新给大家解释了数据结构中冒泡排序的实现原理以及代码的具体实现。最后通过Xmind总结了本文介绍到的相关知识点,帮助大家更好的梳理与理解。现在的java发展的如火如荼,在开发这块占据着举足轻重的地位。因此,作为计算机行业的一名开发人员,学习java是很有必要的。让我们一起在java的海洋里遨游吧!!!生命不息,奋斗不止,我们每天努力,好好学习,不断提高自己的能力,相信自己一定会学有所获。正如经典所说:“人不负青山,青山定不负人。”让我们一起向未来!加油!!!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/854516.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号