Java 14: instanceof的模式匹配(预览)

之前的instanceof使用

在Java 14对instanceof进行了一些改动.这些改动目前是预览的(后期可能会有变化).

在Java 14之前,我们通常是这样使用instanceof的:


static void show(Object obj){
  User user=null;
  if(obj instanceof User){
    user=(User)obj;
    System.out.println(user.name());
  }
}

会发现在instanceof判断obj是User的实例之后,还需要进行一次强制转换并且还需要提前定义一个变量(user)接收强制转换后的结果,才能使用.显得多余且繁琐.这次的改进就是为了优化instanceof的使用而来.

java标志
image-3141

Java 14中对instanceof的改进(预览)

基本改进

先来一段代码:

static void show1(Object obj){
        if(obj instanceof User user){
            System.out.println(user.name());
        }
}

 

可以和上面对比一下改进,发现至少有两点改进:

  • 1. 不用提前定义局部变量user;
  • 2. 局部变量名可直接写在类型后面,也就是user,在判断为true时,可直接使用user.

模式变量的作用域

模式变量存在作用域限制: 它只能在if中使用,而不能在else if/else中使用.否则会提示编译错误.

如下:

static void show1(Object obj){
    if(obj instanceof User user){
        System.out.println(user.name());
    }else if(obj instanceof String){
        // System.out.println(user.name()); error
    }else{
        // System.out.println(user.name()); error
    }
}

 

当然你可以这样用:



    private static User user=new User("aa",12);
static void show1(Object obj){

    if(obj instanceof User user){
        // 调用instanceof模式匹配变量.
        System.out.println(user.name());
    }else if(obj instanceof String){
        // 调用的静态变量user.
        System.out.println(user.name()); 
    }else{
        // 调用的静态变量user.
        System.out.println(user.name());
    }
}

因此,记住只在if中使用instanceof模式变量.

instanceof模式变量简化if表达式

可以使用instanceof模式变量来简化if表达式:

先看原始的:


public class Person {
    String name;
    int age;

    @Override
    public boolean equals(Object o) {
        if (o instanceof Person) {
            Person other = (Person) o;
            if (name.equals(other.name) && age == other.age) {
                return true;
            }
        }
        return false;
    }
}

简化第一步,引入模式变量:


    public class Person {
        String name;
        int age;

        @Override
        public boolean equals(Object o) {
            /// 将局部变量other提入条件表达式.
            if (o instanceof Person other) {
                /// 移除此行. Person other = (Person) o;
                if (name.equals(other.name) && age == other.age) {
                    return true;
                }
            }
            return false;
        }
    }

第二步,将第二个if与第一个if合并:

public class Person {
        String name;
        int age;

        @Override
        public boolean equals(Object o) {
            /// 将局部变量other提入条件表达式.
            if (o instanceof Person other && name.equals(other.name) && age == other.age) {
                /// 移除此行. Person other = (Person) o;
                /// 与上层if合并. if (name.equals(other.name) && age == other.age) {
                    return true;
                /// 与上层if合并 }
            }
            return false;
        }
    }

第三步,终极优化,直接返回if中的条件判断:

public class Person {
        String name;
        int age;

        @Override
        public boolean equals(Object o) {
            return o instanceof Person other && name.equals(other.name) && age == other.age;
            /// 将局部变量other提入条件表达式.
            /// if (o instanceof Person other && name.equals(other.name) && age == other.age) {
                /// 移除此行. Person other = (Person) o;
                /// 与上层if合并. if (name.equals(other.name) && age == other.age) {
                /// return true;
                /// 与上层if合并 }
            /// }
            /// return false;
        }
}

仅需一行,就可以直接返回equals的结果.

完整代码

完整代码如下:

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;

record User(String name, int age) implements Serializable {
}

public class Main {



    public class Person {
        String name;
        int age;

        @Override
        public boolean equals(Object o) {
            return o instanceof Person other && name.equals(other.name) && age == other.age;
            /// 将局部变量other提入条件表达式.
            /// if (o instanceof Person other && name.equals(other.name) && age == other.age) {
                /// 移除此行. Person other = (Person) o;
                /// 与上层if合并. if (name.equals(other.name) && age == other.age) {
                /// return true;
                /// 与上层if合并 }
            /// }
            /// return false;
        }
    }



    static void show(Object obj){
        User user=null;
        if(obj instanceof User){
            user=(User)obj;
            System.out.println(user.name());
        }
    }

    private static User user=new User("aa",12);
    static void show1(Object obj){
        if(obj instanceof User user){
            System.out.println(user.name());
        }else if(obj instanceof String){
            System.out.println(user.name());
        }else{
            System.out.println(user.name());
        }
    }

    public static void main(String[] args) {
        var user = new User("测试用户", 20);
        show1(user);
        show1("str");
        show1(new StringBuffer("StringBuffer"));
    }
}

购买了阿里CDN

关于阿里CDN

一共有三种:

  1. CDN: 将源站内容分发至最接近用户的节点,使用户可就近取得所需内容,提高用户访问的响应速度和成功率。
    解决因分布、带宽、服务器性能带来的访问延迟问题,适用于站点加速、点播、直播等场景。
  2. 全站加速DCDN: 旨在提升动静态资源混合站点的访问体验,支持静态资源边缘缓存,动态内容最优路由回源传输,同时满足整体站点的全网访问速度及稳定性需求。全站加速构建于阿里云CDN平台之上,适用于动静混合型、纯动态型站点或应用的内容分发加速服务。
  3. 安全加速SCDN: 旨在为网站做加速的同时,防护DDoS,CC,Web应用攻击,恶意刷流量,恶意爬虫等危害网站的行为。它构建于阿里云CDN平台之上,在CDN边缘节点中注入了阿里云云盾十年积累的安全能力,形成一张分布式的安全加速网络。适用于所有同时要兼顾内容加速和安全的网站。

购买与配置

此处仅针对全站加速DCDN,另外两个类似.

第一步是先购买资源包,可以从: 阿里CDN首页,点击 资源套餐包 进去购买.

购买如图(可能随着时间变化套餐内容和价格有变化):

image-3136

就买个便宜的试试.

第二步就是开通,全站加速CDN了.地址在: 全站加速DCDN . 开通之后就可以看到控制台了,这时候就需要去配置了.

控制台是下面这个样子:

image-3137

添加域名:

要加速的域名就是你想给用户访问的加速过的域名,源站和加速域名不能一致,也就是: 你必须有一个域名地址能访问到你的网站,然后把另外一个地址用来加速.比如blog.bckf.cn用来作为源站,www.bckf.cn用来加速,用户访问www.bckf.cn就是访问的加速过的域名了.

image-3138

  • OSS: 阿里云的存储服务,添加之后审核会很快.
  • IP: 可以用ip作为源站,但前提是ip必须是可以访问到网站的.可以有多个.
  • 域名: 使用自己的域名作为源站.可以有多个.

端口: 一般就是如果源站访问使用的是SSL,则可以选择443端口.如果没有使用SSL,则选择80端口.

加速区域: 哪里用户访问的多就选哪里.

保存之后会短暂审核,大概10分钟左右.(OSS的审核速度可能会快一些).

审核之后,需要给加速域名的DNS配置CNAME记录(不能与A记录共存).配置方法可以参考: 配置CNAME.

开启SSL

配置了CNAME之后,可以使用阿里云的免费SSL证书服务.

配置方法参考: 全站加速配置SSL

Java 14:Switch表达式

Java 14相关

java标志
image-3128

成为标准功能

温馨提示: 目前仅IDEA 2020.1 EAP及以上版本支持Java 14中所有新增功能.因此请使用最新版本(目前链接到2020.1 EAP版本,发布正式版之后,可在稳定版中下载.)!~

Switch表达式是Java 12加入的,在Java 13成为预览版,在Java 14成为标准版.也就是正式功能.

同时,Switch表达式在Java 14中并未增加任何新特性.因此关于Switch的变更历史.可以参考: Java 13: Switch表达式Java 12预览:Switch表达式.

Java 14:文本块(第二预览)

Java 14相关

关于文本块

温馨提示: 目前仅IDEA 2020.1 EAP及以上版本支持Java 14中所有新增功能.因此请使用最新版本(目前链接到2020.1 EAP版本,发布正式版之后,可在稳定版中下载.)!~

关于文本块的介绍,请查看这篇文章.

Java 14 在Java 13文本块的基础上,增加了两个转义序列: \ 和 \s .

新增加的转义序列

  • \ : 用来放在行尾禁止插入换行符;
  • \s : 可以用来插入一个空格

java标志
image-3122

普通文本块

例子:

var code = """
public void print($type o){
System.out.println(Objects.toString(o));
}
""".replace("$type", "abc");

// 输出: "public void print(abc o){\n System.out.println(Objects.toString(o));\n}\n"

 

会看到输出中包含了换行符 \n .

去掉换行符

var code = """
public void print($type o){\
System.out.println(Objects.toString(o));\
}\
""".replace("$type", "abc");
// 输出 "public void print(abc o){ System.out.println(Objects.toString(o));}"

 

会发现换行符已经被去掉了.另外,文本块结尾也没有任何空格了.

增加空格

var code = """
public void print($type o){\
Sy\stem.out.println(Objects.toString(o));\
}\
""".replace("$type", "abc");
// 输出: "public void print(abc o){ Sy tem.out.println(Objects.toString(o));}"

 

输出中,去掉了换行符.但是在System的Sy后面增加了一个空格(使用\s).可以看到输出里面明显增加了一个空格.

WordPress: 编辑器中添加媒体为相对路径

相对路径更好一些

之前在做SSL的时候,会有个问题.文章中的图片或者视频链接全都是绝对路径(包含完整域名).如果要更换域名,或者从普通协议转到SSL的时候,需要替换全部非SSL的地址.

比如普通的是: http://www.bckf.cn ,如果文章中大量存在此类链接,会导致https访问时报错.

除了在数据库中直接替换之外,另外一个办法就是在编辑器里面做处理了(编辑器里面的设置仅对后续的文章有效,之前的文章只能通过数据库处理).

wordpress logo
image-3111

需要修改

修改之前,请先备份相关文件!

1. 博客主目录/wp-admin/includes/ajax-actions.php

1.1 wp_ajax_query_attachments()函数中

$posts = array_filter( $posts );

的下面,增加如下内容:

foreach($posts as &$el){
        $newurl=str_replace(home_url(),"",$el['url']);
        $el['url']=$newurl; //str_replace(home_url(),"",$el["url"]);
        $el['sizes']['full']['url']=$newurl;
        $el['sizes']['medium']['url']=str_replace(home_url(),"",$el['sizes']['medium']['url']);
        $el['sizes']['thumbnail']['url']=str_replace(home_url(),"",$el['sizes']['thumbnail']['url']);
        $el['sizes']['large']['url']=str_replace(home_url(),"",$el['sizes']['large']['url']);
}
unset($el); // 销毁$el的引用.

1.2 wp_ajax_send_attachment_to_editor()函数

 

$html = apply_filters( 'media_send_to_editor', $html, $id, $attachment );

 

的下面增加:

$html=str_replace(home_url(),"",$html);

 

2. 博客主目录/wp-admin/includes/media.php:

media_send_to_editor( $html )

 

函数的第一行,增加:

$html=str_replace(home_url(),"",$html);