之前技术博客都是在CSDN上发表的,好久没用了,登录上去居然有人给我以前的博客点赞评论,尽管很少但发现还是有人看的。看了一下之前写的博客,发现不是一般的烂,不知道对于他们是不是一种浪费时间的行为🤣。

最近查询问题/解决bug,发现CSDN很多博客质量不太高(包括我的),有好的博客但是真的要筛选看过几篇后才能看到好的,而且前面浪费时间浏览的几篇有些基本是抄袭的。所以还是下定决心好好写博客,不必高产,但每一篇应该认真写。自己总结学习,也尽力让有缘看到自己博客的同学有所得,而不是内心想着:这又是一篇垃圾博客🌚。


Lambda表达式

使用

Runnable接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// Runnable接口的匿名内部类
// Use in Java 7 or earlier:
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("inside runnable using anonymous inner class");
    }
}).start();

// Thread构造函数中使用lambda表达式
new Thread(() -> System.out.println("inside runnable using a lambda")).start();

// 将lambda表达式赋给变量
Runnable r = () -> System.out.println("using a lambda as a variable");
new Thread(r).start();

FilenameFilter接口

 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
28
29
30
31
32
33
34
File dir = new File("src/main/java");
String[] names = dir.list();
System.out.println(Arrays.asList(names));

// FilenameFilter的匿名内部类实现
// Using anonymous inner class
names = dir.list(new FilenameFilter() {
    @Override
    public boolean accept(File directory, String name) {
        return name.endsWith(".java");
    }
});
System.out.println(Arrays.asList(names));

// FilenameFilter接口的lambda表达式实现
// Use a lambda expression
names = dir.list((dr, name) -> name.endsWith(".java"));
System.out.println(Arrays.asList(names));

// 具有显式数据类型的lambda表达式
names = dir.list((File dr, String name) -> name.endsWith(".java"));
System.out.println(Arrays.asList(names));

// lambda代码块(block lambda)
// Notice:不能省略return关键字
names = dir.list((File dr, String name) -> {
    return name.endsWith(".java");
});
System.out.println(Arrays.asList(names));

Arrays.asList(names).forEach(System.out::println);

names = dir.list(new MyFilter());
System.out.println(Arrays.asList(names));

MyFilter.java

1
2
3
4
5
6
public class MyFilter implements FilenameFilter {
    @Override
    public boolean accept(File dir, String name) {
        return name.endsWith(".java");
    }
}

lambda 表达式在任何情况下都不能脱离上下文存在,上下文指定了将表达式赋给哪个函数式接口。1

lambda 表达式可以是:

1、方法的参数

2、方法的返回类型

3、引用

无论哪种情况,赋值类型必须为函数式接口。

函数式接口:

Runnable.java:

 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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package java.lang;

/**
 * The {@code Runnable} interface should be implemented by any
 * class whose instances are intended to be executed by a thread. The
 * class must define a method of no arguments called {@code run}.
 * <p>
 * This interface is designed to provide a common protocol for objects that
 * wish to execute code while they are active. For example,
 * {@code Runnable} is implemented by class {@code Thread}.
 * Being active simply means that a thread has been started and has not
 * yet been stopped.
 * <p>
 * In addition, {@code Runnable} provides the means for a class to be
 * active while not subclassing {@code Thread}. A class that implements
 * {@code Runnable} can run without subclassing {@code Thread}
 * by instantiating a {@code Thread} instance and passing itself in
 * as the target.  In most cases, the {@code Runnable} interface should
 * be used if you are only planning to override the {@code run()}
 * method and no other {@code Thread} methods.
 * This is important because classes should not be subclassed
 * unless the programmer intends on modifying or enhancing the fundamental
 * behavior of the class.
 *
 * @author  Arthur van Hoff
 * @see     java.lang.Thread
 * @see     java.util.concurrent.Callable
 * @since   1.0
 */
@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface {@code Runnable} is used
     * to create a thread, starting the thread causes the object's
     * {@code run} method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method {@code run} is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

从源码中可以看到:

In most cases, the {@code Runnable} interface should be used if you are only planning to override the {@code run()} method and no other {@code Thread} methods. This is important because classes should not be subclassed unless the programmer intends on modifying or enhancing the fundamental behavior of the class.

这也说明了应该面向接口编程,多用接口,而不是继承。

Callable.java:

 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
28
29
30
31
package java.util.concurrent;

/**
 * A task that returns a result and may throw an exception.
 * Implementors define a single method with no arguments called
 * {@code call}.
 *
 * <p>The {@code Callable} interface is similar to {@link
 * java.lang.Runnable}, in that both are designed for classes whose
 * instances are potentially executed by another thread.  A
 * {@code Runnable}, however, does not return a result and cannot
 * throw a checked exception.
 *
 * <p>The {@link Executors} class contains utility methods to
 * convert from other common forms to {@code Callable} classes.
 *
 * @see Executor
 * @since 1.5
 * @author Doug Lea
 * @param <V> the result type of method {@code call}
 */
@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

可以看到:

The {@code Callable} interface is similar to {@link java.lang.Runnable}, in that both are designed for classes whose instances are potentially executed by another thread. A {@code Runnable}, however, does not return a result and cannot throw a checked exception.

说明了Runnable和Callable的异同点。

Runnable是在package java.lang中,Callable是在package java.util.concurrent中;

Java中只有java.lang包下的类可以直接使用,不需要导入。

同时,从Runnable.javaCallable.java都可以看到@FunctionalInterface注解。

FunctionalInterface.java:

 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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package java.lang;

import java.lang.annotation.*;

/**
 * An informative annotation type used to indicate that an interface
 * type declaration is intended to be a <i>functional interface</i> as
 * defined by the Java Language Specification.
 *
 * Conceptually, a functional interface has exactly one abstract
 * method.  Since {@linkplain java.lang.reflect.Method#isDefault()
 * default methods} have an implementation, they are not abstract.  If
 * an interface declares an abstract method overriding one of the
 * public methods of {@code java.lang.Object}, that also does
 * <em>not</em> count toward the interface's abstract method count
 * since any implementation of the interface will have an
 * implementation from {@code java.lang.Object} or elsewhere.
 *
 * <p>Note that instances of functional interfaces can be created with
 * lambda expressions, method references, or constructor references.
 *
 * <p>If a type is annotated with this annotation type, compilers are
 * required to generate an error message unless:
 *
 * <ul>
 * <li> The type is an interface type and not an annotation type, enum, or class.
 * <li> The annotated type satisfies the requirements of a functional interface.
 * </ul>
 *
 * <p>However, the compiler will treat any interface meeting the
 * definition of a functional interface as a functional interface
 * regardless of whether or not a {@code FunctionalInterface}
 * annotation is present on the interface declaration.
 *
 * @jls 4.3.2 The Class Object
 * @jls 9.8 Functional Interfaces
 * @jls 9.4.3 Interface Method Body
 * @jls 9.6.4.9 @FunctionalInterface
 * @since 1.8
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}

可以看到:

Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references.

函数式接口的实例可以使用lambda表达式,方法引用或构造函数引用创建。

从源码中也可以看到Java文档注释(doc comment)相关内容。

Java文档注释(doc comment)

1、用于编写代码API的文档。

2、是普通的多行注释,以/**开头,以*/结尾。(通常使用的多行注释是以/*开头,以*/结尾)

3、通过阅读就可以明白:

  • @author显示为Author
  • @see显示为See Also
  • @since显示为Since

标签太多一次记不过来,每次学几个就会轻松很多。

4、可以包含简单的HTML标签:

1
2
3
4
5
6
<i> 强调
<code> 显示类、方法和字段的名称
<p> 将说明分成很多段落
<ul> <li> 显示无序列表
但是不能包含HTML主结构标签,例如<h2> <hr>
(因为编写的内容会被嵌入复杂的大型HTML文档,以免影响大型HTML文档的结构)

发现源码就是最可靠的文档,从源码中还可以学习代码书写、注释书写。


  1. 《Java攻略:Java常见问题的简单解法》 by 肯·寇森(Ken Kousen) ↩︎