admin管理员组

文章数量:1531434

java的网络编程有用吗

经过一段时间的编码(以我为例,大约20年左右,当您玩得开心时光飞逝),人们开始接受这些习惯。 因为,你知道...

任何可能出错的事情都会发生。

这就是为什么人们会采用“防御性编程”的原因,即偏执狂的习惯有时会变得很有意义,有时会变得晦涩难懂和/或聪明,甚至在想到编写者时也会有些怪异。 这是我个人列出的十大有用但又偏执的Java编程技术。 我们走吧:

1.首先将字符串文字

通过将String文字放在equals()比较的左侧,防止偶然的NullPointerException从来不是一个坏主意,如下所示:

// Bad
if (variable.equals("literal")) { ... }

// Good
if ("literal".equals(variable)) { ... }

这是显而易见的。 将表述从次优版本改为好版本不会丢失任何内容。 如果我们只有真正的期权 ,对吗? 不同的讨论…

2.不要相信早期的JDK API

在Java的早期,编程一定是一个很大的难题。 这些API仍然很不成熟,您可能会碰到如下一段代码:

String[] files = file.list();

// Watch out
if (files != null) {
    for (int i = 0; i < files.length; i++) {
        ...
    }
}

看起来偏执吗? 也许吧, 但是阅读Javadoc :

如果此抽象路径名不表示目录,则此方法返回null。 否则,将返回一个字符串数组,该字符串数组用于目录中的每个文件或目录。

是的,对。 不过,最好确保添加另一张支票:

if (file.isDirectory()) {
    String[] files = file.list();

    // Watch out
    if (files != null) {
        for (int i = 0; i < files.length; i++) {
            ...
        }
    }
}

mm! 编码Java列表时,违反了我们的10条最佳最佳实践中的规则5和6。 因此,请做好准备并添加该null检查!

3.不要相信“ -1”

我知道这很偏执。 String.indexOf()的Javadoc明确指出……

返回此对象表示的字符序列中字符第一次出现的索引;如果未出现字符,则返回-1。

因此, -1是理所当然的,对吧? 我说不。 考虑一下:

// Bad
if (string.indexOf(character) != -1) { ... }

// Good
if (string.indexOf(character) >= 0) { ... }

谁知道。 也许他们需要在某个时间点进行ANOTHER编码,以便说,如果不区分大小写地检查, otherString包含otherString …也许是返回-2的好例子? 谁知道。

毕竟, 关于十亿美元的错误 ,我们已经进行了数十亿次讨论,这是NULL 。 为什么我们不应该开始讨论-1 ,它在某种程度上是原始类型int的替代null

4.避免意外分配

是的 它发生得最好(尽管不是我。请参阅#7)。

(假设这是JavaScript,但是我们也要对语言保持偏执)

// Ooops
if (variable = 5) { ... }

// Better (because causes an error)
if (5 = variable) { ... }

// Intent (remember. Paranoid JavaScript: ===)
if (5 === variable) { ... }

再次。 如果您的表达式中有文字,请将其放在左侧。 当您要添加另一个=符号时,您不会在这里偶然出错。

5.检查空AND长度

只要有集合,数组等,请确保其存在且不为空。

// Bad
if (array.length > 0) { ... }

// Good
if (array != null && array.length > 0) { ... }

您永远不知道这些数组从何而来。 也许来自早期的JDK API?

6.所有方法均为最终方法

您可以告诉我所有关于您的开放/封闭原则的信息,这些都是胡扯。 我不信任您(正确地扩展了我的课程),我也不信任自己(不偶然地扩展了我的课程)。 这就是为什么所有未明确打算用于子类型化(即仅接口)的事物都是严格final 。 另请参阅我们的《 编码Java的10条最佳实践》列表中的第9条。

// Bad
public void boom() { ... }

// Good. Don't touch.
public final void dontTouch() { ... }

是。 这是最终的。 如果那对您不起作用,请对其进行修补或检测,或重写字节码。 或发送功能请求。 我敢肯定,您要覆盖上述内容并不是一个好主意。

7.所有变量和参数均为最终变量

就像我说的。 我不信任自己(不会意外覆盖我的价值观)。 话虽如此,我一点也不相信自己。 因为…

…这就是为什么所有变量和参数也都设为final

// Bad
void input(String importantMessage) {
    String answer = "...";

    answer = importantMessage = "LOL accident";
}

// Good
final void input(final String importantMessage) {
    final String answer = "...";
}

好吧,我承认。 尽管我应该这样做,但我确实很少经常申请。 我希望Java像Scala一样正确 ,人们只需在各处输入val ,甚至都无需考虑可变性-除非他们通过var显式(很少!)使用它。

8.重载时不要相信泛型

是。 这有可能发生。 您相信您写的是一个超级棒的API,它完全摇摆并且完全直观,并且随之而来的是一些用户,它将所有内容原始广播到Object直到织补编译器停止执行,然后突然他们会链接错误的方法,以为这是您的错误(总是如此)。

考虑一下:

// Bad
<T> void bad(T value) {
    bad(Collections.singletonList(value));
}

<T> void bad(List<T> values) {
    ...
}

// Good
final <T> void good(final T value) {
    if (value instanceof List)
        good((List<?>) value);
    else
        good(Collections.singletonList(value));
}

final <T> void good(final List<T> values) {
    ...
}

因为,您知道……您的用户,他们喜欢

// This library sucks
@SuppressWarnings("all")
Object t = (Object) (List) Arrays.asList("abc");
bad(t);

相信我。 我已经看到了一切。 包括像

偏执是很好的。

9.始终打开默认开关

切换...这些滑稽的陈述之一,我不知道该敬畏地吓呆还是哭泣。 无论如何,我们被switch困住了,所以我们最好还是在需要的时候把它弄对。 即

// Bad
switch (value) {
    case 1: foo(); break;
    case 2: bar(); break;
}

// Good
switch (value) {
    case 1: foo(); break;
    case 2: bar(); break;
    default:
        throw new ThreadDeath("That'll teach them");
}

因为将value == 3引入软件的那一刻,它一定会来! 而且不要说enum ,因为它也会发生在enums

10.用花括号切换

实际上, switch是最醉人的说法,任何人在喝醉或打赌时都被允许进入一种语言。 考虑以下示例:

// Bad, doesn't compile
switch (value) {
    case 1: int j = 1; break;
    case 2: int j = 2; break;
}

// Good
switch (value) {
    case 1: {
        final int j = 1;
        break;
    }
    case 2: {
        final int j = 2;
        break;
    }

    // Remember:
    default: 
        throw new ThreadDeath("That'll teach them");
}

switch语句中,所有case语句之间仅定义了一个作用域。 实际上,这些case语句甚至不是真正的语句,它们就像标签,并且switch是goto调用。 实际上,您甚至可以将case语句与令人惊讶的FORTRAN 77 ENTRY语句进行比较, FORTRAN 77 ENTRY语句的神秘之处仅在于其强大功能。

这意味着无论我们是否发出break ,都会为所有不同情况定义变量final int j 。 不是很直观。 这就是为什么通过一个简单的block在每个case语句中创建一个新的嵌套作用域始终是一个好主意的原因。 (但不要忘记块内的break !)

结论

偏执狂编程有时看起来很奇怪,因为代码往往比实际需要的更为冗长。 您可能会想,“哦,这永远不会发生”,但是正如我所说。 经过20年左右的编程,您只是不想修复仅由于该语言太老又有缺陷而导致的那些愚蠢的,不必要的小错误。 因为你知道

现在轮到你了!

您在编程中最偏执的怪癖是什么?

翻译自: https://www.javacodegeeks/2015/08/top-10-useful-yet-paranoid-java-programming-techniques.html

java的网络编程有用吗

本文标签: 十大但又偏执编程技术有用吗