知识库 知识库
首页
  • Hyperskill - Java

    • Java basic
    • Java OOP
    • 应知
    • 扩展
    • IO & Stream
    • Error & Exception
    • Algorithm & Data structure
    • Design pattern
    • Web
    • Spring boot
  • 练习题

    • 选择题 & 填空题
    • 代码题
  • Frank - Java与生活 (OOP)

    • 参考资料
    • Java基础
    • OOP上半部分
    • OOP下半部分
  • Frank - Java API进阶

    • Base API
    • Unit Test and main function
  • 学习笔记
  • 学习笔记

    • 数据库
  • Frank - MySQL删库跑路

    • 安装、连接、配置
    • 基本操作——数据库
    • 基本操作——表
    • 基本操作——数据
    • 数据类型
    • 列属性完整性
    • 数据库设计思维
    • 单表查询
    • 多表查询
  • 学习笔记

    • 其它
  • Frank - Linux现代方法

    • 必知
    • 命令
    • 技巧
  • 技术文档
  • Git
  • GitHub技巧
  • 前端
  • Khan Academy - 语法
  • Monthly
  • 阅读
  • Others
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 标签
  • 归档
GitHub (opens new window)

Jim FuckPPT

Java小学生
首页
  • Hyperskill - Java

    • Java basic
    • Java OOP
    • 应知
    • 扩展
    • IO & Stream
    • Error & Exception
    • Algorithm & Data structure
    • Design pattern
    • Web
    • Spring boot
  • 练习题

    • 选择题 & 填空题
    • 代码题
  • Frank - Java与生活 (OOP)

    • 参考资料
    • Java基础
    • OOP上半部分
    • OOP下半部分
  • Frank - Java API进阶

    • Base API
    • Unit Test and main function
  • 学习笔记
  • 学习笔记

    • 数据库
  • Frank - MySQL删库跑路

    • 安装、连接、配置
    • 基本操作——数据库
    • 基本操作——表
    • 基本操作——数据
    • 数据类型
    • 列属性完整性
    • 数据库设计思维
    • 单表查询
    • 多表查询
  • 学习笔记

    • 其它
  • Frank - Linux现代方法

    • 必知
    • 命令
    • 技巧
  • 技术文档
  • Git
  • GitHub技巧
  • 前端
  • Khan Academy - 语法
  • Monthly
  • 阅读
  • Others
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 标签
  • 归档
GitHub (opens new window)
  • Hyperskill - Java

    • Java basic

    • Java OOP

      • Theory:Introduction OOP
      • Theory:Defining classes
      • Theory:Instance methods
      • Thoery:Constructor
      • Theory:Package
      • Theory:Access modifiers
      • Theory:Getters and setters
      • Theory:Inheritance
      • Theory:Protected modifier
      • Theory:Referencing subclass objects
      • Theory:The Object class
      • Theory:Objects
      • Theory:Interface
      • Theory:Multiple constructors
      • Theory:The keyword super
      • Theory:Static members
      • Theory:Hiding and overriding
      • Theory:Polymorphism
      • Theory:Abstract class
      • Theory:Abstract class vs interface
      • Theory:Anonymous classes
      • Theory:Anonymous classes properties
        • How to create?
        • Learn callbacks by example
        • Restrictions on anonymous classes
        • Summary
    • 应知

    • 扩展

    • IO & Stream

    • Error & Exception

    • Algorithm & Data structure

    • Design pattern

    • Web

    • Spring boot

  • 练习题

  • Frank - Java与生活

  • Frank - Java API进阶

  • 学习笔记

  • Java
  • Hyperskill - Java
  • Java OOP
Jim
2022-10-29
目录

Theory:Anonymous classes properties

As you remember, there are anonymous classes in the world of Java. They don't have name identifiers and they enable you to declare and instantiate a class at the same time. But you didn't think that the whole theory was covered in the first topic, did you? So, today is a special day — you will finally learn all the nuances about anonymous classes!

# How to create?

The most popular way to create an anonymous class is to implement an interface and you have seen it already. So, now let's try something new — let's create an anonymous class that inherits from another class.

Imagine a human: they have a brain and many-many thoughts in it. Every couple of seconds they produce a new thought. And we want to describe it in Java language. So, how will we do it?

abstract class HumanThought {
    public void print() {
        System.out.println("This is a very important thought.");
    }
}
1
2
3
4
5

This is our superclass HumanThought that has one method for printing the standard thought. And now anonymous classes will help us. By inheriting from HumanThought we may have as many different thoughts as we want — and that's all without new .java files.

All new thoughts would be children of our superclass and will have their own method print:

class Human {

    public void takeMilkshake() {

        // creation of anonymous class by inheriting from class HumanThought
        HumanThought thought = new HumanThought() {
            public void print() {
                System.out.println("What to take? Chocolate or strawberry milkshake..");
            }
        };
        thought.print();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

And if we wanted to create an actual human and invoke method takeMilkshake — what would be the output?

public class Main {

    public static void main(String[] args) {

        Human human = new Human();
        human.takeMilkshake();
    }
}
1
2
3
4
5
6
7
8

Of course, you are thinking the right thought:

What to take? Chocolate or strawberry milkshake..
1

And have you noticed that class HumanThought is abstract? Yes, it is — don't forget that we can create an anonymous class by inheriting from both: concrete and abstract classes.

But to become a master in programming you should get acquainted with another case of creating anonymous classes: when we create an anonymous class and pass it in a constructor as an argument.

So, what is going on in our example below? Firstly, Thread is a standard Java class. And if you don't know each other yet, don't be afraid — fruitful cooperation awaits you. And Runnable is an interface that describes some action — any you want. In our example, Runnable has an action that only prints a phrase.

Thread has several constructors, that is a normal situation, and one of its constructors take as an argument an anonymous class that implements the interface Runnable.

As a result, the anonymous class is passed as an argument of the constructor:

class MyExample {
    public static void main(String[] args) {

        //Anonymous class is created as a constructor argument
        Thread t = new Thread(new Runnable() {
            public void run() {
                System.out.println("Run, Forrest, run!");
            }
        });
    }
}
1
2
3
4
5
6
7
8
9
10
11

# Learn callbacks by example

Also, often, after creating an instance of an anonymous class we pass it to some method as an argument. In this case, the anonymous class is called a callback. A callback is a piece of executable code that is passed to another code that executes it (performs a call back) at a convenient time. And can we call our previous example a callback? Yes, we can — because the constructor is a special method.

Let's consider an example. There is a special kind of calculator that can only divide numbers. The calculator takes a callback as its argument and executes the callback passing the result of the calculation or an error message.

The Callback interface has two abstract methods:

interface Callback {

    /**
     * Takes a result and processes it
     */
    void calculated(int result);

    /**
     * Takes an error message
     */
    void failed(String errorMsg);
}
1
2
3
4
5
6
7
8
9
10
11
12

The class Divider has only one static method (just an example, the demonstrated technique works with any methods):

class Divider {

    /**
     * Divide a by b. It executes the specified callback to process results
     */
    public static void divide(int a, int b, Callback callback) {

        if (b == 0) {
            callback.failed("Division by zero!");
            return;
        }

        callback.calculated(a / b);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Of course, in this case, you can perform the division and return the result without any callbacks. In general, though, callbacks can help you in large applications with multiple parts and layers (especially in multithreaded programs).

Calling a method with a callback:

public class CallbacksExample {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int a = scanner.nextInt();
        int b = scanner.nextInt();

        Divider.divide(a, b, new Callback() { // passing callback as an argument

            @Override
            public void calculated(int result) {
                String textToPrint = String.format("%d / %d is %d", a, b, result);
                print(textToPrint);
            }

            @Override
            public void failed(String errorMsg) {
                print(errorMsg);
            }
        });
    }

    public static void print(String text) {
        System.out.println(text);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

As you can see, we instantiate and pass the callback without any additional variables of the Callback type. It's a very common practice for working with callbacks, especially if they are small.

The callback captures the static method print and the local variables a and b from its context. The variables a and b are effectively final here. (i.e the variables aren't changed you don't need to write the keyword final ).

Let's run the program.

Input 1:

8 2
1

Output 1:

8 / 2 is 4
1

Input 2:

10 0
1

Output 2:

Division by zero!
1

So, anonymous classes along with the context capture mechanism allow you to transfer logic between parts of your program. They are used as callbacks in large applications and when working with external libraries.

# Restrictions on anonymous classes

And, of course, anonymous classes have some restrictions:

  • they cannot have static initializers or interface declarations
  • they cannot have static members, except the constant variables (final static fields)
  • they cannot have constructors

Let's consider the following example with an anonymous class SpeakingEntity. To not have static initializers, static members, or interface declarations — it's not a big deal. But what about not having a constructor? How to initialize our fields?

final String robotName = "Bug";
final int robotAssemblyYear = 2112;

SpeakingEntity robot = new SpeakingEntity() {

    static final int MAGIC_CONSTANT = 10;

    private String name;
    private int assemblyYear;

    { /* instance initialization block for setting fields */
        name = robotName;
        assemblyYear = robotAssemblyYear;
    }

    @Override
    public void sayHello() {
        System.out.println("1010001" + MAGIC_CONSTANT);
    }

    @Override
    public void sayBye() {
        System.out.println("0101110" + MAGIC_CONSTANT);
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

And for examples like this one you should be friends with the good old theory! Remember about instance initializers and what they are for? Yeah, instance initializer allows us to substitute a constructor. It runs each time when an object of the class is created. So, fields name and assemblyYear will be initialized and our robot will have the name "Bug" and a year of birth!

# Summary

Perhaps you are wondering where to go to see how anonymous classes are used in "real life"? In that case, we may have a suggestion.

Anonymous classes are actively used when writing user interfaces with the standard Java library called Swing. The same with developing a web user interface using Google Web Toolkit (GWT). It is very common to have a lot of listeners that are used just once for one button, so using anonymous classes allows us to avoid writing a lot of classes and having useless files in the development of the code. Some widespread libraries for working through the HTTP protocol also use anonymous classes. For example, this HttpAsyncClient (opens new window).

And the last one — what are the advantages of anonymous classes? Anonymous classes enable you to make code more concise and reduce the number of .java files. And what about encapsulation? Yes, you are thinking right — each anonymous class has very local scope, it is defined exactly where it is needed and it can never be used anywhere else. So, it definitely increases encapsulation and provides you with a great reason to fall in love with Java!

编辑 (opens new window)
上次更新: 2022/10/29, 19:52:35
Theory:Anonymous classes
Theory:Functional decomposition

← Theory:Anonymous classes Theory:Functional decomposition→

最近更新
01
《挪威的森林》
04-14
02
青钢影
04-14
03
Processing strings
02-18
更多文章>
Theme by Vdoing | Copyright © 2022-2023 Jim Frank | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式