Java的隐藏功能

295

17
请注意,并不总是一个好主意使用这些隐藏的功能;往往会让阅读你代码的其他人感到惊讶和困惑。 - Kevin Bourrillion
1
你(/某人)应该像C#问题那样将答案整洁地总结在问题正文中。 - ripper234
100个回答

20

你可以在方法中声明一个类:

public Foo foo(String in) {
    class FooFormat extends Format {
        public Object parse(String s, ParsePosition pp) { // parse stuff }
    }
    return (Foo) new FooFormat().parse(in);

}

你也可以使用 new Format() 来代替声明 FooFormat 类。 - Pyrolistical
4
匿名类被高估了。如果你尝试调试或在实际应用中支持一个匿名类,你就会明白我的意思。一旦在发布版本中丢失了行号,它们就非常难以追踪。 - TREE
5
它们被称为本地类,详见:http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#247766。 - Özgür
我更喜欢通过让匿名类回调主对象来控制它们的行为;匿名类只是一个适配器,因此很容易做到正确。 - Donal Fellows
@Donal - 我经常在UI代码中使用这个。但值得一提的是,从重构的角度来看,这种设计是不好的。你可能会提取一个“顶层”类,发现它的逻辑完全由另一个类实现! - oxbow_lakes
@oxbow:我并不完全理解你的观点。我的内部类中唯一的内容就是调用外部类上的一个(通常为非公共的)方法。虽然在理论上这可能会让人感到惊讶,但实际上很容易看出来,因为这只是一个没有异常处理的调用。 - Donal Fellows

19

他们花了很长时间才添加对此的支持,

系统托盘


17

1
请参阅COPE的CRTP:http://www.artima.com/weblogs/viewpost.jsp?thread=133275 - Ray Tayek

17

我非常喜欢Java 1.6重写的线程API,特别是Callables。它们基本上就像带返回值的线程。


与旧版本相比,这个新东西更简单。 - Allain Lalonde
基本上有ExecutorServices,您可以向其中提交Callables。当您将Callable提交到ExecutorService时,您会收到一个Future,它具有阻塞调用以获取Callable的结果(或者您可以询问它是否已经有结果,非阻塞)。 - Adam Jaskiewicz
ExecutorService 是一种运行 Callable(和 Runnables)的方式。它可以是单个后台线程,也可以由线程池支持,甚至可以在当前线程中顺序运行任务。这取决于具体实现。 - Adam Jaskiewicz
还有一个CompletionService,可以将可调用对象提交给它,结果会在完成时排队等待消费。 - Adam Jaskiewicz

16

我喜欢使用静态方法导入。

例如创建以下实用类:

package package.name;

public class util {

     private static void doStuff1(){
        //the end
     }

     private static String doStuff2(){
        return "the end";
     }

}

然后像这样使用它。

import static package.name.util.*;

public class main{

     public static void main(String[] args){
          doStuff1(); // wee no more typing util.doStuff1()
          System.out.print(doStuff2()); // or util.doStuff2()
     }

}

静态导入适用于任何类,甚至适用于Math...

import static java.lang.Math.*;
import static java.lang.System.out;
public class HelloWorld {
    public static void main(String[] args) {
        out.println("Hello World!");
        out.println("Considering a circle with a diameter of 5 cm, it has:");
        out.println("A circumference of " + (PI * 5) + "cm");
        out.println("And an area of " + (PI * pow(5,2)) + "sq. cm");
    }
}

1
请在您的示例中修复doStuffX方法中的'S'字母大小写。这可能会令人困惑。 - Archer

16

List.subList返回原始列表的视图

列表的一个已记录但鲜为人知的特性。这使您可以使用列表的部分,并且在原始列表中反映更改。

List subList(int fromIndex, int toIndex)

"此方法消除了对显式范围操作(例如数组通常存在的操作)的需求。通过传递子列表视图而不是整个列表,可以将预期列表的任何操作用作范围操作。例如,以下惯用语从列表中移除一系列元素:

       list.subList(from, to).clear();

可以使用类似的习语来构建indexOf和lastIndexOf,而Collections类中的所有算法都可以应用于子列表。


3
使用 subList 时要小心,即使您只存储子列表的引用,它也会在内存中保存整个基础列表。这与函数式语言中的“tail”操作非常不同。 - lexicalscope
而且,根据实现方式,某些操作在子列表上可能比在完整列表上慢。 - Paŭlo Ebermann
当人们看到list.subList(from, to).clear()时,他们会惊叹这太酷了!但在其他库中,它只是list.RemoveRange(from, to),更加整洁、直接和可用。 - Pacerier

16

哦,我差点忘记了这个小宝石。在任何正在运行的Java进程上尝试此操作:

jmap -histo:live PID

您将获得给定虚拟机中活动堆对象的直方图。作为快速解决某些类型内存泄漏的无价之宝。我使用的另一种技术是创建并使用大小有限的所有集合类子类。这会导致失控集合的快速失败,易于识别。


16

你可以使用一项功能来显示 Java 基于控制台的应用程序的闪屏。

使用带有选项 -splash 的命令行工具 javajavaw

例如:

java -splash:C:\myfolder\myimage.png -classpath myjarfile.jar com.my.package.MyClass

当你执行类"com.my.package.MyClass"时,C:\myfolder\myimage.png 的内容将显示在屏幕中央。


这真的有点难找...在Java(java.exe)命令的文档中找不到该选项。(但它在SplashScreen的帮助消息或javadoc中) - user85421

15

使用静态导入,您可以做很酷的事情,例如:

List<String> myList = list("foo", "bar");
Set<String> mySet = set("foo", "bar");
Map<String, String> myMap = map(v("foo", "2"), v("bar", "3"));

4
你甚至可以使用泛型来完成这个操作。Google Collections库中有很好用的工具类可供使用。 - Tim Büthe

15

Javadoc(Java文档)- 如果正确编写(不幸的是有些开发者没有这么做),它会为您提供清晰、连贯的代码描述,告诉您代码应该执行什么而不是实际上执行了什么。然后可以将其转换为漂亮的可浏览HTML文档集。如果使用持续集成等工具,它可以定期生成,以便所有开发人员都能看到最新的更新。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接