您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > JAVA

Java 10 大装 B 写法,看完可以出去吹了!

时间:2020-04-18 09:39:49  来源:  作者:

Java 10 大装 B 写法,看完可以出去吹了!

 

1、集合初始化

集合的创建、赋值一步到位,想不想学?

来,上边跟我一起画个 List,在你下边画一个Map……

List<String> list = new ArrayList<String>() {{
    add("www.");
    add("JAVAstack.");
    add("cn");
}};

Map<String, String> map = new HashMap<String, String>() {{
    put("1", "www.");
    put("2", "javastack.");
    put("3", "cn");
}};

哈哈,高大上的写法,栈长以前写过,写法虽然是很装X,然而并没有什么卵用。

2、算术

static {
    final int size = -(-128) + 127 + 1;

    // Load and use the archived cache if it exists
    VM.initializeFromArchive(ByteCache.class);
    if (archivedCache == null || archivedCache.length != size) {
        Byte[] c = new Byte[size];
        byte value = (byte)-128;
        for(int i = 0; i < size; i++) {
            c[i] = new Byte(value++);
        }
        archivedCache = c;
    }
    cache = archivedCache;
}

注意到上面size的写法没有?

明明可以写成:

final int size = 256;

他非要写成:

final int size = -(-128) + 127 + 1;

这么装 B 的写法来自 JDK 包装类java.lang.Byte里面的静态方法。

为什么要这么写呢?

这样的写法在 JDK 里面有很多,大家看到这些写法都会觉得很奇怪,Java技术栈微信群里、知识星球里面有曾有粉丝问我这是为什么。

真正缘由无从考察,但栈长我觉得写 JDK 的大神其实就想告诉你,Byte 的 256 个数是由 -128 ~ 127 这个范围组成的,起到一个标识数字范围的作用而已。至少 Byte 为什么取这个范围,为什么byte取值-128~127??这篇文章可以解密。

3、移位

/**
 * The default initial capacity - MUST be a power of two.
 */
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

/**
 * The maximum capacity, used if a higher value is implicitly specified
 * by either of the constructors with arguments.
 * MUST be a power of two <= 1<<30.
 */
static final int MAXIMUM_CAPACITY = 1 << 30;

这两个变量来自java.util.HashMap源码,你可能也非常好奇为什么不直接写成数字,要弄一个移位骚操作?

这是在告诉开发者,HashMap 的容量大小必须是 2 的幂次,不然会造成空间浪费。另外,HashMap 容量为什么总是为 2 的次幂?这篇推荐看下。

4、复制变量

transient Collection<V> values;

public Collection<V> values() {
    Collection<V> vs = values;
    if (vs == null) {
        vs = new Values();
        values = vs;
    }
    return vs;
}

以上同样来自java.util.HashMap的源码,为什么不直接用values:

transient Collection<V> values;

public Collection<V> values() {
    if (values == null) {
        values = new Values();
    }
    return values;
}

而要重新定义一个vs来绕一个弯呢?

这样写不是更简单么?

JDK里面大量这样的写法,这是为什么呢?!

那是因为操作局部变量要比读取全局变量要更快,另外,我个人觉得还有一个好处,再申明一下局部变量,可以很明显的看到这个变量的类型,而不要翻到上面或者用鼠标移上去来看变量类型。

另外提一点,上面的复制变量再操作的方式让我想到了CopyOnWriteArrayList,这也是让当前变量不被其他线程改变保证当前线程变量一致性的一种方式。

写 JDK 源码的都是大神啊,透过源码,我们能学到太多东西!

5、泛型

来看一段泛型的灵活运用:

public <R> Observable<R> compose(Transformer<? super T, ? extends R> transformer) {
    return ((Transformer<T, R>) transformer).call(this);
}

这个泛型方法写得牛 X 吧,泛型 T、R、通配符(?)、上边界(extends)和下边界(super)都用上了!

常用的泛型含义:

  • T - Type(类型)
  • R - Result(结果)
  • K - Key(键)
  • V - Value(值)
  • E - Element (元素)
  • N - Number(数字)
  • ? - 不确定类型

上面的泛型我们应该有常见到吧,边界和通配符不懂的可以看下这篇文章吧:困扰我多年的Java泛型 和 ,终于搞清楚了。

泛型要学会用,学好能装B。

6、Lambda

Lambda 表达式这是 Java 8 里面添加的新特性,用来简化匿名内部类以及结合函数式接口编程用的。

如下面创建线程的示例:

// 1
Runnable runnable = () -> System.out.println("javastack.cn");
new Thread(runnable).start();

// 2
new Thread(() -> System.out.println("javastack.cn")).start();

// 3
new Thread(() -> clean()).start();

三个不同的写法,我们再也不用写new Runnable()的一大堆 的匿名内部类了,是不是很清爽了!

如果你还不会用Lambda表达式,那真的 OUT 了,可以关注微信公众号:Java技术栈,在后台回复:新特性,我已经写了一大堆教程了。

下面是一个Lambada真实案例:

@Bean
public CommandLineRunner commandLineRunner(NettyServer nettyServer) {
    return (args) -> {
        Thread thread = new Thread(() -> nettyServer.start());
        thread.setDaemon(true);
        thread.start();
    };
}

上述示例省去了 newCommandLineRunner的匿名内部类的过程。

7、函数式编程

上面有提到函数式编程,这是 Java 8 里面添加的新特性,我之前在公众号里已经写过很多 Java 新特性的教程,这也不是新玩法了,已经被玩烂了。

来看一个真实的案例,来自 Spring Boot 的邮件发送自动配置:

private void ApplyProperties(JavaMailSenderImpl sender) {
    PropertyMapper map = PropertyMapper.get();
    map.from(this.properties::getHost).to(sender::setHost);
    map.from(this.properties::getPort).whenNonNull().to(sender::setPort);
    map.from(this.properties::getUsername).to(sender::setUsername);
    map.from(this.properties::getPassword).to(sender::setPassword);
    map.from(this.properties::getProtocol).to(sender::setProtocol);
    map.from(this.properties::getDefaultEncoding).whenNonNull().as(Charset::name)
            .to(sender::setDefaultEncoding);
    map.from(this.properties::getProperties).whenNot(Map::isEmpty)
            .as(this::asProperties).to(sender::setJavaMailProperties);
}

第一次看到这段代码的时候,我内心是拒绝的,很难理解。

上面的 from 和 to 方法分别用到了Supplier和Consumer函数式接口,还用到了双冒号::结合使用,讳莫如深,还能结合Lambda表达式使用。

函数式编程很厉害,虽然会用,但到现在我也觉得很高深,可读性和可理解性太差了,但是,装 X 必学、必用。

8、流关闭

MyInputStream mis = new MyInputStream();
MyOutputStream mos = new MyOutputStream();
try (mis; mos) {
    mis.read("1.9");
    mos.write("1.9");
} catch (Exception e) {
    e.printStackTrace();
}

没错,你看到的这个关闭流骚操作是 Java 9 的新语法糖,较 Java 7 又简化了try-with-resources用法,装 X 的姿势越来越多了。

关于try-with-resources的详细介绍及演进过程,大家可以阅读这篇文章:JDK9新特性实战:简化流关闭新姿势,或者可以关注微信公众号:Java技术栈,在后台回复 "新特性" 获取这篇文章完整版。

不知道的可能上来就一顿骂了,你流关闭动作在哪,为什么不关闭流,多跟着栈长学点新知识吧,哈哈。

9、类型推断

关注Java技术栈公众号的老读者应该都看过,Java 10 刚出来的时候,我写过两篇新特性文章:

  • Java 10的10个新特性,将彻底改变你写代码的方式!
  • Java 10 实战第 1 篇:局部变量类型推断

来,我再挑两个示例来欣赏下:

示例1:

var javastack = "javastack";

示例2:

private static void testLoop() {
    for (var i = 0; i < 3; i++) {
        for (var m = 10; m < 15; m++) {
            System.out.println(i + m);
        }
    }
}

这样写会不会被打?也太省事了!

类型推断出来后,都说 Java 越来越像 JavaScript 了,其实就是 Java 10 增加的一种语法糖而已,在编译期间会自动推断实际类型,其编译后的字节码和实际类型一致。

10、模式匹配

instanceof模式是匹配这是 Java 14 推出来的新特性:

if (object instanceof Kid kid) {
    // ...
} else if (object instanceof Kiddle kiddle) {
    // ...
}

匹配后直接创建对象和赋值直接拿来用,不需要再添加强制转换的代码,大大提高了可读性和安全性。具体可以看这篇文章:Java 14 之模式匹配,非常赞的一个新特性!



Tags:Java 10   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
1、集合初始化集合的创建、赋值一步到位,想不想学?来,上边跟我一起画个 List,在你下边画一个Map&hellip;&hellip;List<String> list = new ArrayList<String>() {{ add("ww...【详细内容】
2020-04-18  Tags: Java 10  点击:(52)  评论:(0)  加入收藏
▌简易百科推荐
面向对象的特征之一封装 面向对象的特征之二继承 方法重写(override/overWrite) 方法的重载(overload)和重写(override)的区别: 面向对象特征之三:多态 Instanceof关键字...【详细内容】
2021-12-28  顶顶架构师    Tags:面向对象   点击:(2)  评论:(0)  加入收藏
一、Redis使用过程中一些小的注意点1、不要把Redis当成数据库来使用二、Arrays.asList常见失误需求:把数组转成list集合去处理。方法:Arrays.asList 或者 Java8的stream流式处...【详细内容】
2021-12-27  CF07    Tags:Java   点击:(3)  评论:(0)  加入收藏
文章目录 如何理解面向对象编程? JDK 和 JRE 有什么区别? 如何理解Java中封装,继承、多态特性? 如何理解Java中的字节码对象? 你是如何理解Java中的泛型的? 说说泛型应用...【详细内容】
2021-12-24  Java架构师之路    Tags:JAVA   点击:(5)  评论:(0)  加入收藏
大家好!我是老码农,一个喜欢技术、爱分享的同学,从今天开始和大家持续分享JVM调优方面的经验。JVM调优是个大话题,涉及的知识点很庞大 Java内存模型 垃圾回收机制 各种工具使用 ...【详细内容】
2021-12-23  小码匠和老码农    Tags:JVM调优   点击:(11)  评论:(0)  加入收藏
前言JDBC访问Postgresql的jsonb类型字段当然可以使用Postgresql jdbc驱动中提供的PGobject,但是这样在需要兼容多种数据库的系统开发中显得不那么通用,需要特殊处理。本文介绍...【详细内容】
2021-12-23  dingle    Tags:JDBC   点击:(13)  评论:(0)  加入收藏
Java与Lua相互调用案例比较少,因此项目使用需要做详细的性能测试,本内容只做粗略测试。目前已完成初版Lua-Java调用框架开发,后期有时间准备把框架进行抽象,并开源出来,感兴趣的...【详细内容】
2021-12-23  JAVA小白    Tags:Java   点击:(11)  评论:(0)  加入收藏
Java从版本5开始,在 java.util.concurrent.locks包内给我们提供了除了synchronized关键字以外的几个新的锁功能的实现,ReentrantLock就是其中的一个。但是这并不意味着我们可...【详细内容】
2021-12-17  小西学JAVA    Tags:JAVA并发   点击:(11)  评论:(0)  加入收藏
一、概述final是Java关键字中最常见之一,表示“最终的,不可更改”之意,在Java中也正是这个意思。有final修饰的内容,就会变得与众不同,它们会变成终极存在,其内容成为固定的存在。...【详细内容】
2021-12-15  唯一浩哥    Tags:Java基础   点击:(17)  评论:(0)  加入收藏
1、问题描述关于java中的日志管理logback,去年写过关于logback介绍的文章,这次项目中又优化了下,记录下,希望能帮到需要的朋友。2、解决方案这次其实是碰到了一个问题,一般的情况...【详细内容】
2021-12-15  软件老王    Tags:logback   点击:(19)  评论:(0)  加入收藏
本篇文章我们以AtomicInteger为例子,主要讲解下CAS(Compare And Swap)功能是如何在AtomicInteger中使用的,以及提供CAS功能的Unsafe对象。我们先从一个例子开始吧。假设现在我们...【详细内容】
2021-12-14  小西学JAVA    Tags:JAVA   点击:(21)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条