295

在阅读了 C# 的隐藏特性后,我想知道,Java 的一些隐藏特性是什么?

4

100 回答 100

432

几个月前,当我第一次发现双括号初始化时,我感到很惊讶,以前从未听说过。

ThreadLocals通常不像存储每个线程状态的方法那样广为人知。

由于 JDK 1.5 Java 已经实现了非常好的和强大的并发工具,而不仅仅是锁,它们存在于java.util.concurrent 中,一个特别有趣的例子是java.util.concurrent.atomic子包,它包含实现比较的线程安全原语-and-swap操作,并且可以映射到这些操作的实际本机硬件支持版本。

于 2008-08-19T20:09:17.063 回答
279

类型参数变化中的联合联合:

public class Baz<T extends Foo & Bar> {}

例如,如果您想获取一个既是 Comparable 又是 Collection 的参数:

public static <A, B extends Collection<A> & Comparable<B>>
boolean foo(B b1, B b2, A a) {
   return (b1.compareTo(b2) == 0) || b1.contains(a) || b2.contains(a);
}

如果两个给定集合相等或其中任何一个包含给定元素,则此人为方法返回 true,否则返回 false。需要注意的一点是,您可以在参数 b1 和 b2 上调用 Comparable 和 Collection 的方法。

于 2008-09-03T21:51:46.267 回答
219

前几天我对实例初始化程序感到惊讶。我正在删除一些代码折叠方法并最终创建了多个实例初始化程序:

public class App {
    public App(String name) { System.out.println(name + "'s constructor called"); }

    static { System.out.println("static initializer called"); }

    { System.out.println("instance initializer called"); }

    static { System.out.println("static initializer2 called"); }

    { System.out.println("instance initializer2 called"); }

    public static void main( String[] args ) {
        new App("one");
        new App("two");
  }
}

执行该main方法将显示:

static initializer called
static initializer2 called
instance initializer called
instance initializer2 called
one's constructor called
instance initializer called
instance initializer2 called
two's constructor called

我想如果您有多个构造函数并且需要通用代码,这些将很有用

它们还提供了用于初始化类的语法糖:

List<Integer> numbers = new ArrayList<Integer>(){{ add(1); add(2); }};

Map<String,String> codes = new HashMap<String,String>(){{ 
  put("1","one"); 
  put("2","two");
}};
于 2008-09-06T14:27:50.503 回答
201

JDK 1.6_07+ 包含一个名为 VisualVM (bin/jvisualvm.exe) 的应用程序,它是许多工具之上的一个不错的 GUI。它似乎比 JConsole 更全面。

于 2008-09-11T01:15:19.320 回答
173

自 Java 6 以来的类路径通配符。

java -classpath ./lib/* so.Main

代替

java -classpath ./lib/log4j.jar:./lib/commons-codec.jar:./lib/commons-httpclient.jar:./lib/commons-collections.jar:./lib/myApp.jar so.Main

请参阅http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html

于 2009-12-07T11:59:37.180 回答
156

对于我采访的大多数 Java 开发人员职位标记块是非常令人惊讶的。这是一个例子:

// code goes here

getmeout:{
    for (int i = 0; i < N; ++i) {
        for (int j = i; j < N; ++j) {
            for (int k = j; k < N; ++k) {
                //do something here
                break getmeout;
            }
        }
    }
}

谁说goto在java中只是一个关键字?:)

于 2008-09-02T12:57:04.033 回答
144

自 JDK 1.5 以来已经存在的协变返回类型怎么样?它的宣传很少,因为它是一个不性感的补充,但据我了解,对于泛型工作来说绝对必要。

本质上,编译器现在允许子类将被覆盖方法的返回类型缩小为原始方法返回类型的子类。所以这是允许的:

class Souper {
    Collection<String> values() {
        ...
    }
}

class ThreadSafeSortedSub extends Souper {
    @Override
    ConcurrentSkipListSet<String> values() {
        ...
    }
}

您可以调用子类的values方法并获得s的排序线程安全Set而无需向下转换为.StringConcurrentSkipListSet

于 2008-08-29T19:29:40.940 回答
142

在 finally 块中转移控制会抛出任何异常。下面的代码不会抛出 RuntimeException——它会丢失。

public static void doSomething() {
    try {
      //Normally you would have code that doesn't explicitly appear 
      //to throw exceptions so it would be harder to see the problem.
      throw new RuntimeException();
    } finally {
      return;
    }
  }

来自http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html

于 2008-09-15T16:49:51.520 回答
140

还没有看到有人提到 instanceof 以不需要检查 null 的方式实现。

代替:

if( null != aObject && aObject instanceof String )
{
    ...
}

只需使用:

if( aObject instanceof String )
{
    ...
}
于 2009-01-19T15:01:05.790 回答
134

在枚举中允许方法和构造函数让我感到惊讶。例如:

enum Cats {
  FELIX(2), SHEEBA(3), RUFUS(7);

  private int mAge;
  Cats(int age) {
    mAge = age;
  }
  public int getAge() {
    return mAge;
   }
}

您甚至可以拥有一个“常量特定类主体”,它允许特定枚举值覆盖方法。

更多文档在这里

于 2008-09-09T21:10:31.103 回答
121

泛型方法的类型参数可以像这样显式指定:

Collections.<String,Integer>emptyMap()
于 2008-09-11T02:09:12.873 回答
112

您可以使用枚举来实现接口。

public interface Room {
   public Room north();
   public Room south();
   public Room east();
   public Room west();
}

public enum Rooms implements Room {
   FIRST {
      public Room north() {
         return SECOND;
      }
   },
   SECOND {
      public Room south() {
         return FIRST;
      }
   }

   public Room north() { return null; }
   public Room south() { return null; }
   public Room east() { return null; }
   public Room west() { return null; }
}

编辑:多年后....

我在这里使用此功能

public enum AffinityStrategies implements AffinityStrategy {

https://github.com/peter-lawrey/Java-Thread-Affinity/blob/master/src/main/java/vanilla/java/affinity/AffinityStrategies.java

通过使用接口,开发人员可以定义自己的策略。使用一种enum方法,我可以定义一个内置集合(五个)。

于 2009-02-18T21:10:20.033 回答
104

从 Java 1.5 开始,Java 现在有了更简洁的语法来编写可变参数的函数。因此,现在您可以执行以下操作,而不仅仅是传递一个数组

public void foo(String... bars) {
   for (String bar: bars)
      System.out.println(bar);
}

bar 会自动转换为指定类型的数组。不是一个巨大的胜利,但仍然是一个胜利。

于 2008-11-03T17:02:46.010 回答
93

我最喜欢的:将所有线程堆栈跟踪转储到标准输出。

windows: CTRL-Break在你的 java cmd/console 窗口中

Unix: kill -3 PID

于 2008-09-17T13:23:06.650 回答
89

有几个人发布了关于实例初始化器的帖子,这是一个很好的用途:

Map map = new HashMap() {{
    put("a key", "a value");
    put("another key", "another value");
}};

如果您只是在做一些快速而简单的事情,这是一种初始化地图的快速方法。

或者用它来创建一个快速的摆动框架原型:

JFrame frame = new JFrame();

JPanel panel = new JPanel(); 

panel.add( new JLabel("Hey there"){{ 
    setBackground(Color.black);
    setForeground( Color.white);
}});

panel.add( new JButton("Ok"){{
    addActionListener( new ActionListener(){
        public void actionPerformed( ActionEvent ae ){
            System.out.println("Button pushed");
        }
     });
 }});


 frame.add( panel );

当然也可以滥用:

    JFrame frame = new JFrame(){{
         add( new JPanel(){{
               add( new JLabel("Hey there"){{ 
                    setBackground(Color.black);
                    setForeground( Color.white);
                }});

                add( new JButton("Ok"){{
                    addActionListener( new ActionListener(){
                        public void actionPerformed( ActionEvent ae ){
                            System.out.println("Button pushed");
                        }
                     });
                 }});
        }});
    }};
于 2008-10-27T00:12:44.807 回答
88

动态代理(在 1.3 中添加)允许您在运行时定义符合接口的新类型。它派上用场的次数令人惊讶。

于 2008-09-03T01:29:39.997 回答
81

最终初始化可以推迟。

它确保即使具有复杂的逻辑流,也始终设置返回值。错过一个案例并意外返回 null 太容易了。它不会使返回 null 成为不可能,只是很明显它是故意的:

public Object getElementAt(int index) {
    final Object element;
    if (index == 0) {
         element = "Result 1";
    } else if (index == 1) {
         element = "Result 2";
    } else {
         element = "Result 3";
    }
    return element;
}
于 2008-10-03T21:59:37.697 回答
62

我认为 java 的另一个“被忽视”的特性是 JVM 本身。它可能是最好的虚拟机了。它支持许多有趣且有用的语言(Jython、JRuby、Scala、Groovy)。所有这些语言都可以轻松无缝地协作。

如果您设计一种新语言(例如在 scala 案例中),您将立即拥有所有可用的现有库,因此您的语言从一开始就“有用”。

所有这些语言都使用了 HotSpot 优化。虚拟机很好地监控和调试。

于 2008-08-19T16:47:35.740 回答
58

你可以定义一个匿名子类并直接调用它的方法,即使它没有实现接口。

new Object() {
  void foo(String s) {
    System.out.println(s);
  }
}.foo("Hello");
于 2009-06-22T01:17:28.063 回答
56

中的asList方法java.util.Arrays可以很好地组合可变参数、泛型方法和自动装箱:

List<Integer> ints = Arrays.asList(1,2,3);
于 2008-09-15T15:55:15.443 回答
53

使用关键字从内部类访问包含类的字段/方法。在下面,相当人为的示例中,我们想使用匿名内部类中容器类的 sortAscending 字段。使用 ContainerClass.this.sortAscending 而不是 this.sortAscending 可以解决问题。

import java.util.Comparator;

public class ContainerClass {
boolean sortAscending;
public Comparator createComparator(final boolean sortAscending){
    Comparator comparator = new Comparator<Integer>() {

        public int compare(Integer o1, Integer o2) {
            if (sortAscending || ContainerClass.this.sortAscending) {
                return o1 - o2;
            } else {
                return o2 - o1;
            }
        }

    };
    return comparator;
}
}
于 2008-09-19T13:02:49.590 回答
52

不是一个真正的功能,而是我最近在一些网页中发现的一个有趣的技巧:

class Example
{
  public static void main(String[] args)
  {
    System.out.println("Hello World!");
    http://Phi.Lho.free.fr

    System.exit(0);
  }
}

是一个有效的 Java 程序(尽管它会生成一个警告)。如果您不明白为什么,请参阅 Gregory 的回答!;-) 好吧,这里的语法高亮也给出了提示!

于 2008-09-17T11:39:29.003 回答
46

这不完全是“隐藏的特性”,也不是很有用,但在某些情况下可能非常有趣:
类 sun.misc.Unsafe - 将允许您在 Java 中实现直接内存管理(您甚至可以编写自修改 Java 代码如果你尝试了很多):

public class UnsafeUtil {

    public static Unsafe unsafe;
    private static long fieldOffset;
    private static UnsafeUtil instance = new UnsafeUtil();

    private Object obj;

    static {
        try {
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);

            unsafe = (Unsafe)f.get(null);
            fieldOffset = unsafe.objectFieldOffset(UnsafeUtil.class.getDeclaredField("obj"));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    };
}
于 2008-09-19T13:35:12.117 回答
42

在 Swing 中工作时,我喜欢隐藏的Ctrl- Shift-F1功能。

它转储当前窗口的组件树。
(假设您没有将该击键绑定到其他东西。)

于 2009-12-02T16:28:17.177 回答
40

每个类文件都以十六进制值0xCAFEBABE开头,以将其标识为有效的 JVM 字节码。

解释

于 2010-02-19T05:29:42.290 回答
38

My vote goes to java.util.concurrent with its concurrent collections and flexible executors allowing among others thread pools, scheduled tasks and coordinated tasks. The DelayQueue is my personal favorite, where elements are made available after a specified delay.

java.util.Timer and TimerTask may safely be put to rest.

Also, not exactly hidden but in a different package from the other classes related to date and time. java.util.concurrent.TimeUnit is useful when converting between nanoseconds, microseconds, milliseconds and seconds.

It reads a lot better than the usual someValue * 1000 or someValue / 1000.

于 2008-12-04T19:51:57.213 回答
37

语言级别的断言关键字。

于 2008-08-19T01:51:22.350 回答
37

不是 Java 语言的一部分,但是 Sun 的 JDK 附带的 javap 反汇编程序并不广为人知或使用。

于 2008-09-10T17:20:11.960 回答
36

在 1.5 中添加了 for-each 循环结构。我 <3 它。

// For each Object, instantiated as foo, in myCollection
for(Object foo: myCollection) {
  System.out.println(foo.toString());
}

并且可以在嵌套实例中使用:

for (Suit suit : suits)
  for (Rank rank : ranks)
    sortedDeck.add(new Card(suit, rank));

for-each 结构也适用于数组,它隐藏索引变量而不是迭代器。以下方法返回 int 数组中值的总和:

// Returns the sum of the elements of a
int sum(int[] a) {
  int result = 0;
  for (int i : a)
    result += i;
  return result;
}

指向 Sun 文档的链接

于 2008-09-16T18:35:19.263 回答
34

我个人java.lang.Void很晚才发现——结合泛型提高代码可读性,例如Callable<Void>

于 2009-02-17T13:25:09.333 回答
30

也许最令人惊讶的隐藏特性是 sun.misc.Unsafe 类。

http://www.docjar.com/html/api/ClassLib/Common/sun/misc/Unsafe.java.html

你可以;

  • 在不调用构造函数的情况下创建对象。
  • 抛出任何异常,甚至 Exception,而不用担心方法上的 throws 子句。(我知道还有其他方法可以做到这一点)
  • 在不使用反射的情况下获取/设置对象中随机访问的字段。
  • 分配/释放/复制/调整大小可以很长(64 位)的内存块。
  • 获取对象中的字段或类中的静态字段的位置。
  • 独立锁定和解锁对象锁。(如无块同步)
  • 从提供的字节码定义一个类。而不是类加载器确定字节码应该是什么。(你也可以通过反射来做到这一点)

顺便说一句:这个类的不正确使用会杀死 JVM。我不知道哪些 JVM 支持此类,因此它不可移植。

于 2009-06-11T20:10:28.227 回答
29

这是我的清单。

我最喜欢(也是最可怕)的隐藏功能是您可以从未声明抛出任何东西的方法中抛出已检查异常。

import java.rmi.RemoteException;

class Thrower {
    public static void spit(final Throwable exception) {
        class EvilThrower<T extends Throwable> {
            @SuppressWarnings("unchecked")
            private void sneakyThrow(Throwable exception) throws T {
                throw (T) exception;
            }
        }
        new EvilThrower<RuntimeException>().sneakyThrow(exception);
    }
}

public class ThrowerSample {
    public static void main( String[] args ) {
        Thrower.spit(new RemoteException("go unchecked!"));
    }
}

你也可能想知道你可以抛出'null'......

public static void main(String[] args) {
     throw null;
}

猜猜这会打印什么:

Long value = new Long(0);
System.out.println(value.equals(0));

而且,猜猜这会返回什么:

public int returnSomething() {
    try {
        throw new RuntimeException("foo!");
    } finally {
        return 0;
    }
}

以上不应该让优秀的开发人员感到惊讶。


在 Java 中,您可以通过以下有效方式声明数组:

String[] strings = new String[] { "foo", "bar" };
// the above is equivalent to the following:
String[] strings = { "foo", "bar" };

所以下面的 Java 代码是完全有效的:

public class Foo {
    public void doSomething(String[] arg) {}

    public void example() {
        String[] strings = { "foo", "bar" };
        doSomething(strings);
    }
}

相反,以下代码不应该是有效的,有什么正当理由吗?

public class Foo {

    public void doSomething(String[] arg) {}

    public void example() {
        doSomething({ "foo", "bar" });
    }
}

我认为,上述语法将是 Java 5 中引入的可变参数的有效替代品。而且,与以前允许的数组声明更加一致。

于 2010-01-25T09:45:51.120 回答
28

关闭挂钩。这允许注册一个将立即创建但仅在 JVM 结束时启动的线程!所以它是某种“全局 jvm 终结器”,您可以在这个线程中制作有用的东西(例如关闭 java 资源,如嵌入式 hsqldb 服务器)。这适用于 System.exit() 或 CTRL-C / kill -15(当然不适用于 unix 上的 kill -9)。

此外,它很容易设置。

            Runtime.getRuntime().addShutdownHook(new Thread() {
                  public void run() {
                      endApp();
                  }
            });;
于 2009-12-16T23:47:36.480 回答
27

的价值:

new URL("http://www.yahoo.com").equals(new URL("http://209.191.93.52"))

true

(来自 Java Puzzlers)

于 2008-10-27T00:03:39.787 回答
26

如果您进行大量 JavaBean 开发并使用属性更改支持,您通常会编写很多这样的 setter:

public void setFoo(Foo aFoo){
  Foo old = this.foo;
  this.foo = aFoo;
  changeSupport.firePropertyChange("foo", old, aFoo);
}

我最近偶然发现了一个博客,该博客建议对此进行更简洁的实现,从而使代码更容易编写:

public void setFoo(Foo aFoo){
  changeSupport.firePropertyChange("foo", this.foo, this.foo = aFoo);
}

它实际上将事情简化到我能够在 Eclipse 中调整 setter 模板以便自动创建该方法的程度。

于 2008-09-26T03:30:29.173 回答
25

静态导入以“增强”语言,因此您可以以类型安全的方式做一些不错的文字操作:

List<String> ls = List("a", "b", "c");

(也可以用于映射、数组、集合)。

http://gleichmann.wordpress.com/2008/01/13/building-your-own-literals-in-java-lists-and-arrays/

更进一步:

List<Map<String, String>> data = List(Map( o("name", "michael"), o("sex", "male")));
于 2008-08-19T02:06:42.227 回答
23

作为初学者,我非常感谢 Java 6 中的 JConsole 监控软件,它已经为我解决了一些问题,并且我一直在寻找它的新用途。

显然 JConsole 在 Java 5 中已经存在,但我认为它现在得到了改进,至少到目前为止工作更加稳定。

Java 5 中的 JConsole:Java 5 中的 JConsole

Java 6 中的 JConsole:Java 6 中的 JConsole

在您阅读的同时,请仔细查看该系列中的其他工具: Java 6 故障排除工具

于 2008-08-20T11:30:49.960 回答
23

没有那么隐蔽,但很有趣。

你可以有一个没有 main 方法的“Hello, world”(它会抛出 NoSuchMethodError 思想)

最初由 RusselW 在最奇怪的语言功能上发表

public class WithoutMain {
    static {
        System.out.println("Look ma, no main!!");
        System.exit(0);
    }
}

$ java WithoutMain
Look ma, no main!!
于 2010-07-05T18:22:40.823 回答
22

如果您不使用默认初始化程序,Java 处理会在变量定义上做一个巧妙的技巧。

{
   诠释 x;

   如果(随便)
      x=1;

   如果(x == 1)
      ...
}

这将在编译时给您一个错误,即您有一个未正确定义 X 的路径。这帮助了我几次,我已经开始考虑像这样的默认初始化:

诠释 x = 0;
字符串 s=null;

成为一个糟糕的模式,因为它阻止了这种有用的检查。

也就是说,有时很难解决——当它作为默认值有意义时,我不得不返回并在 =null 中进行编辑,但我再也没有在第一次通过时将其放入。

于 2008-10-06T18:14:51.657 回答
21

这并不是一个真正的隐藏功能,但当我看到这个编译得很好时,它确实给了我一个很大的惊喜:

public int aMethod(){
    http://www.google.com
    return 1;
}

它编译的原因是http://www.google.com的“http:”部分被编译器视为标签,而该行的其余部分是注释。

因此,如果您想编写一些奇怪的代码(或混淆代码),只需将大量 http 地址放在那里即可。;-)

于 2010-06-28T04:36:04.613 回答
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);

}
于 2008-09-28T15:45:22.937 回答
19

他们花了足够长的时间来增加对此的支持,

系统托盘

于 2008-09-15T15:50:33.520 回答
17

我真的很喜欢从 Java 1.6 重写的 Threading API。可调用对象很棒。它们基本上是具有返回值的线程。

于 2008-08-19T02:03:53.947 回答
17

自绑定泛型:

class SelfBounded<T extends SelfBounded<T>> {
}

http://www.artima.com/weblogs/viewpost.jsp?thread=136394

于 2008-09-10T20:18:12.310 回答
16

我喜欢方法的静态导入。

例如创建以下 util 类:

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()
     }

}

静态导入适用于任何类,甚至是数学......

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");
    }
}
于 2009-02-17T12:56:31.993 回答
16

哦,我差点忘了这个小宝石。在任何正在运行的 java 进程上试试这个:

jmap -histo:live PID

您将获得给定 VM 中活动堆对象的直方图。作为一种快速计算某些类型的内存泄漏的方法是非常宝贵的。我用来防止它们的另一种技术是创建和使用所有集合类的大小限制子类。这会导致易于识别的失控集合中的快速故障。

于 2009-11-26T19:03:03.900 回答
16

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

一个记录在案但鲜为人知的列表功能。这使您可以使用在原始列表中镜像更改的列表部分。

列表子列表(int fromIndex,int toIndex)

“这种方法消除了显式范围操作(通常存在于数组中的那种)的需要。任何需要列表的操作都可以通过传递子列表视图而不是整个列表来用作范围操作。例如,以下idiom 从列表中删除一系列元素:

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

可以为 indexOf 和 lastIndexOf 构造类似的习语,并且可以将 Collections 类中的所有算法应用于子列表。”

于 2009-02-17T13:22:17.907 回答
16

一项功能,您可以使用它为基于 Java 控制台的应用程序显示启动画面。

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

例如:

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

每当您执行“com.my.package.MyClass”类时,内容C:\myfolder\myimage.png将显示在屏幕中央

于 2009-11-27T08:39:36.890 回答
15

不是一个真正的功能,但它让我发笑,这goto是一个保留字,除了提示 javac 戳你的眼睛之外什么都不做。只是提醒您,您现在处于 OO 领域。

于 2008-08-20T10:07:43.700 回答
15

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

List<String> myList = list("foo", "bar");
Set<String> mySet = set("foo", "bar");
Map<String, String> myMap = map(v("foo", "2"), v("bar", "3"));
于 2009-02-04T17:19:12.727 回答
15

Javadoc - 如果编写得当(不幸的是,某些开发人员并非总是如此),它会为您提供清晰、连贯的代码应该做什么的描述,而不是它实际做什么。然后它可以变成一组漂亮的可浏览的 HTML 文档。如果您使用持续集成等,它可以定期生成,以便所有开发人员都可以看到最新的更新。

于 2008-11-12T16:59:39.180 回答
14

strictfp 关键字。(虽然我从未见过它在实际应用程序中使用过 :)

您可以使用以下表示法获取原始类型的类:int.class、float.class 等。在进行反射时非常有用。

最终数组可用于从匿名内部类“返回”值(警告,下面无用的示例):

final boolean[] result = new boolean[1];
SwingUtilities.invokeAndWait(new Runnable() {
  public void run() { result[0] = true; }
});
于 2009-01-01T05:19:38.203 回答
14

您可以在匿名内部类上定义和调用方法。

好吧,它们并没有那么隐藏,但是很少有人知道它们可以用来在类中定义一个新方法并像这样调用它:

(new Object() {
    public String someMethod(){ 
        return "some value";
    }
}).someMethod();

可能不是很常见,因为它也不是很有用,只有在定义它时才能调用它(或通过反射)

于 2010-06-21T23:04:28.123 回答
13

我知道 Java 6 包含脚本支持,但我最近才发现jrunscript,它可以交互地解释和运行 JavaScript(并且假设其他脚本语言,如 Groovy),有点像 Ruby 中的 Python shell 或 irb

于 2008-09-03T00:33:17.307 回答
13

C 风格 printf() :)

System.out.printf("%d %f %.4f", 3,Math.E,Math.E);

输出:3 2.718282 2.7183

二分查找(及其返回值)

int[] q = new int[] { 1,3,4,5};
int position = Arrays.binarySearch(q, 2);

与 C# 类似,如果在数组中没有找到 '2',它会返回一个负值,但如果你取返回值的 1 的补码,你实际上会得到可以插入 '2' 的位置。

在上面的例子中, position = -2, ~position = 1 这是应该插入 2 的位置......它还可以让您在数组中找到“最接近”的匹配项。

我认为它非常漂亮...... :)

于 2010-06-30T08:06:02.710 回答
12

我知道这是在 1.5 版中添加的,但新的枚举类型是一个很棒的功能。不必使用旧的“int enum 模式”极大地帮助了我的一堆代码。 查看 JLS 8.9,了解土豆上的甜肉汁!

于 2008-09-04T15:55:03.823 回答
12

它并没有完全隐藏,但反射非常有用和强大。使用类类型可配置的简单 Class.forName("...").newInstance() 非常棒。编写这种工厂实现很容易。

于 2008-08-29T19:17:46.897 回答
12

部分功能,部分麻烦:Java 的字符串处理使其“显示”为本机类型(在它们上使用运算符,+,+=)

能写:

String s = "A";
s += " String"; // so s == "A String"

非常方便,但只是语法糖(即编译为):

String s = new String("A");
s = new StringBuffer(s).append(" String").toString();

ergo 一个 Object 实例化和 2 个用于简单连接的方法调用。想象一下以这种方式在循环内构建一个长字符串!?并且 StringBuffer 的所有方法都被声明为同步的。值得庆幸的是,在(我认为)Java 5 中,他们引入了与没有同步的 StringBuffer 相同的 StringBuilder。

一个循环,例如:

String s = "";
for (int i = 0 ; i < 1000 ; ++i)
  s += " " + i; // Really an Object instantiation & 3 method invocations!

可以(应该)在您的代码中重写为:

StringBuilder buf = new StringBuilder(); // Empty buffer
for (int i = 0 ; i < 1000 ; ++i)
  buf.append(' ').append(i); // Cut out the object instantiation & reduce to 2 method invocations
String s = buf.toString();

并且将比原始循环快约 80%!(在我运行的一些基准测试中高达 180%)

于 2009-06-04T09:06:47.937 回答
11

final 例如变量:

对于多线程代码非常有用,它使争论实例状态和正确性变得容易得多。在行业环境中没有看到很多,并且在 Java 类中经常没有想到。


静态{某事;}:

用于初始化静态成员(我也更喜欢使用静态方法来完成它(因为它有一个名称)。没想到。

于 2008-09-06T09:07:16.403 回答
11

我今天刚刚(重新)了解到 $ 是 Java 中方法或变量的合法名称。结合静态导入,它可以使代码更具可读性,具体取决于您对可读性的看法:

http://garbagecollected.org/2008/04/06/dollarmaps/

于 2009-07-28T03:21:04.690 回答
10

“const”是一个关键字,但你不能使用它。

int const = 1;   // "not a statement"
const int i = 1; // "illegal start of expression"

我猜编译器作者认为它可能会在将来使用,他们最好保留它。

于 2008-09-16T20:01:59.867 回答
10

当您StringBuilder不需要StringBuffer包含在StringBuilder. 它将提高您的应用程序的性能。

Java 7 的改进甚至比任何隐藏的 Java 特性都要好:

不要在实例化时使用那些无限的 <> 语法:

Map<String, List<String>> anagrams = new HashMap<String, List<String>>();

// Can now be replaced with this:

Map<String, List<String>> anagrams = new HashMap<>();
  • 开关中的字符串: 链接

在 switch 中使用 String,而不是 old-C int:

String s = "something";
switch(s) {
 case "quux":
    processQuux(s);
    // fall-through

  case "foo":
  case "bar":
    processFooOrBar(s);
    break;

  case "baz":
     processBaz(s);
    // fall-through

  default:
    processDefault(s);
    break;
}

这个旧代码:

static void copy(String src, String dest) throws IOException {
    InputStream in = new FileInputStream(src);
    try {
        OutputStream out = new FileOutputStream(dest);
        try {
            byte[] buf = new byte[8 * 1024];
            int n;
            while ((n = in.read(buf)) >= 0)
                out.write(buf, 0, n);
        } finally {
            out.close();
        }
    } finally {
        in.close();
    }
}

现在可以用这个更简单的代码代替:

static void copy(String src, String dest) throws IOException {
    try (InputStream in = new FileInputStream(src);
            OutputStream out = new FileOutputStream(dest)) {
        byte[] buf = new byte[8192];
        int n;
        while ((n = in.read(buf)) >= 0)
            out.write(buf, 0, n);
    }
}
于 2009-11-04T15:00:01.793 回答
9

真正让我吃惊的是自定义序列化机制。

虽然这些方法是私有的!!,它们在对象序列化期间被JVM “神秘地”调用。

private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

通过这种方式,您可以创建自己的自定义序列化,使其更加“随便”(安全、快速、罕见、简单等)

如果必须通过节点传递大量信息,这是真正应该考虑的事情。可以改变序列化机制以发送一半数据。很多时候瓶颈不在平台上,但在通过网络发送的数量上,可能会为您节省数千个硬件中的 dll。

这是一篇文章。 http://java.sun.com/developer/technicalArticles/Programming/serialization/

于 2008-09-27T01:11:17.303 回答
9

您选择的编码中的属性文件怎么样?过去,当您加载属性时,您提供了一个 InputStream,并且该load()方法将其解码为 ISO-8859-1。您实际上可以将文件存储在其他一些编码中,但是在加载后您必须使用像这样令人作呕的黑客来正确解码数据:

String realProp = new String(prop.getBytes("ISO-8859-1"), "UTF-8");

但是,从 JDK 1.6 开始,有一种load()方法采用 Reader 而不是 InputStream,这意味着您可以从一开始就使用正确的编码(还有store()一种采用 Writer 的方法)。这对我来说似乎是一件大事,但它似乎已经悄悄进入 JDK 并没有大张旗鼓。几周前我才偶然发现它,而快速的谷歌搜索只是偶然提到了它。

于 2008-09-24T19:37:07.230 回答
9

一种优化技巧,使您的代码更易于维护并且不易受并发错误的影响。

public class Slow {
  /** Loop counter; initialized to 0. */
  private long i;

  public static void main( String args[] ) {
    Slow slow = new Slow();

    slow.run();
  }

  private void run() {
    while( i++ < 10000000000L )
      ;
  }
}

$ time java Slow
real 0m15.397s
$ time java Slow
real 0m20.012s
$ time java Slow
real 0m18.645s

平均:18.018 秒

public class Fast {
  /** Loop counter; initialized to 0. */
  private long i;

  public static void main( String args[] ) {
    Fast fast = new Fast();

    fast.run();
  }

  private void run() {
    long i = getI();

    while( i++ < 10000000000L )
      ;

    setI( i );
  }

  private long setI( long i ) {
    this.i = i;
  }

  private long getI() {
    return this.i;
  }
}

$ time java Fast
real 0m12.003s
$ time java Fast
real 0m9.840s
$ time java Fast
real 0m9.686s

平均:10.509s

它需要更多的字节码来引用类范围变量而不是方法范围变量。在关键循环之前添加方法调用几乎不会增加开销(无论如何编译器都可能内联调用)。

这种技术(始终使用访问器)的另一个优点是它消除了Slow类中的潜在错误。如果第二个线程不断地将i的值重置为 0(例如,通过调用slow.setI( 0 )),Slow类将永远无法结束其循环。调用访问器并使用局部变量消除了这种可能性。

在 Linux 2.6.27-14 上使用 J2SE 1.6.0_13 进行了测试。

于 2009-06-22T02:46:05.843 回答
9

标识符可以包含外语字符,例如变音符号:

而不是写:

String title="";

有人可以写:

String Überschrift="";
于 2010-01-09T20:04:01.527 回答
9

我可以添加 Scanner 对象。它最适合解析。

String input = "1 fish 2 fish red fish blue fish";
Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
System.out.println(s.nextInt());
System.out.println(s.nextInt());
System.out.println(s.next());
System.out.println(s.next());
s.close();
于 2010-06-09T09:07:06.700 回答
8

Java 6 的注解处理 API 看起来非常适合代码生成和静态代码验证。

于 2008-09-29T11:09:52.327 回答
8

大多数人不知道他们可以克隆一个数组。

int[] arr = {1, 2, 3};
int[] arr2 = arr.clone();
于 2009-08-20T11:45:23.457 回答
8

当人们意识到可以使用反射调用私有方法和访问/更改私有字段时,有时会感到有些惊讶......

考虑以下类:

public class Foo {
    private int bar;

    public Foo() {
        setBar(17);
    }

    private void setBar(int bar) {
        this.bar=bar;
    }

    public int getBar() {
        return bar;
    }

    public String toString() {
        return "Foo[bar="+bar+"]";
    }
}

执行这个程序...

import java.lang.reflect.*;

public class AccessibleExample {
    public static void main(String[] args)
        throws NoSuchMethodException,IllegalAccessException, InvocationTargetException, NoSuchFieldException {
        Foo foo=new Foo();
        System.out.println(foo);

        Method method=Foo.class.getDeclaredMethod("setBar", int.class);
        method.setAccessible(true);
        method.invoke(foo, 42);

        System.out.println(foo);
        Field field=Foo.class.getDeclaredField("bar");
        field.setAccessible(true);
        field.set(foo, 23);
        System.out.println(foo);
    }
}

...将产生以下输出:

Foo[bar=17]
Foo[bar=42]
Foo[bar=23]
于 2009-06-03T14:32:26.060 回答
7

您可以在局部类的初始化块和方法中访问最终局部变量和参数。考虑一下:

    final String foo = "42";
    new Thread() {
        public void run() {
             dowhatever(foo);
        }
    }.start();

有点像闭包,不是吗?

于 2008-10-23T14:18:16.560 回答
7

JDK 发行版中 bin 目录中的 JVisualVM。监视甚至分析任何 Java 应用程序,即使是您没有使用任何特殊参数启动的应用程序。仅在 Java 6SE JDK 的最新版本中。

于 2008-09-15T16:19:57.023 回答
7

You can build a string sprintf-style using String.format().

String w = "world";
String s = String.format("Hello %s %d", w, 3);

You can of course also use special specifiers to modify the output.

More here: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Formatter.html#syntax

于 2009-02-04T16:52:03.703 回答
7

垃圾收集器及其管理对象收集的方式非常强大,尤其是对于长时间运行和时间敏感的应用程序。它从 java.lang.ref 包中的弱引用、软引用和幻像引用开始。看看那些,尤其是构建缓存(已经有一个 java.util.WeakHashMap)。现在深入研究一下 ReferenceQueue,您将开始拥有更多控制权。最后获取垃圾收集器本身的文档,您将能够控制它的运行频率、不同收集区域的大小以及使用的算法类型(对于 Java 5,请参阅http://java.sun.com/docs /hotspot/gc5.0/gc_tuning_5.html)。

于 2008-09-17T17:37:59.657 回答
7

实际上,我喜欢 Java 的地方在于隐藏的技巧很少。这是一种非常明显的语言。如此之多以至于15年后,我能想到的几乎每一个都已经在这几页上列出了。

也许大多数人都知道 Collections.synchronizedList() 将同步添加到列表中。除非您阅读文档,否则您无法知道的是,您可以通过在列表对象本身上同步来安全地迭代该列表的元素。

CopyOnWriteArrayList 有些人可能不知道,Future 代表了一种抽象多线程结果访问的有趣方式。

您可以附加到 VM(本地或远程),通过各种管理、代理和附加 API 获取有关 GC 活动、内存使用、文件描述符甚至对象大小的信息。

虽然 TimeUnit 可能比 long 更好,但我更喜欢 Wicket 的 Duration 类。

于 2009-11-26T18:43:48.887 回答
6

finally围绕return语句的一些控制流技巧:

int getCount() { 
  try { return 1; }
  finally { System.out.println("Bye!"); }
}

明确分配的规则将通过简单的控制流分析检查是否始终分配最终变量:

final int foo;
if(...)
  foo = 1;
else
  throw new Exception();
foo+1;
于 2008-09-15T16:08:02.683 回答
6

Joshua Bloch 的新版Effective Java是一个很好的资源。

于 2008-09-08T13:24:57.610 回答
6

源代码 URL。例如,这里是一些合法的 java 源代码:

http://google.com

(是的,它是在 Java Puzzlers 中。我笑了……)

于 2009-05-12T03:47:42.513 回答
6

没读过这个

Integer a = 1;
Integer b = 1;
Integer c = new Integer(1);
Integer d = new Integer(1);

Integer e = 128;
Integer f = 128;

assertTrue (a == b);   // again: this is true!
assertFalse(e == f); // again: this is false!
assertFalse(c == d);   // again: this is false!

通过搜索 java 的整数池(从 -128 到 127 进行自动装箱的内部“缓存”)或查看 Integer.valueOf,了解更多信息

于 2010-01-22T22:33:07.637 回答
5
于 2008-09-08T16:38:47.287 回答
5

Java 1.6 Update 10 及更高版本中的下一代 Java 插件具有一些非常简洁的特性:

  • 传递 java_arguments 参数以将参数传递给创建的 JVM。这允许您控制分配给小程序的内存量。
  • 为每个小程序创建单独的类加载器甚至单独的 JVM。
  • 指定要使用的 JVM 版本。
  • 如果您只需要完整 Java 库功能的一个子集,请安装部分 Java 内核。
  • 更好的 Vista 支持。
  • 支持(实验性)将小程序拖出浏览器并在您离开时让它继续运行。

此处记录的许多其他内容:http: //jdk6.dev.java.net/plugin2/

此版本的更多信息:http: //jdk6.dev.java.net/6u10ea.html

于 2009-02-04T15:58:41.953 回答
5

逗号和数组。它是合法的语法: String s[] = {
"123" ,
"234" ,
};

于 2009-08-20T10:06:32.503 回答
5

字符串参数化类工厂。

Class.forName( className ).newInstance();

从部署 jar 文件加载资源(属性文件、xml、xslt、图像等)

this.getClass().getClassLoader().getResourceAsStream( ... ) ;
于 2008-09-26T13:06:23.617 回答
5

同一类的实例可以访问其他实例的私有成员:

class Thing {
  private int x;

  public int addThings(Thing t2) {
    return this.x + t2.x;  // Can access t2's private value!
  }
}
于 2008-11-26T19:04:22.240 回答
5

Java 6(来自 Sun)带有一个嵌入式 JavaScrip 解释器。

http://java.sun.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html#jsengine

于 2010-01-14T11:59:43.637 回答
5

交集类型允许您(有点)做具有继承层次结构的枚举。您不能继承实现,但可以将其委托给辅助类。

enum Foo1 implements Bar {}
enum Foo2 implements Bar {}

class HelperClass {
   static <T extends Enum<T> & Bar> void fooBar(T the enum) {}
}

当您有许多实现某种模式的不同枚举时,这很有用。例如,许多具有父子关系的枚举对。

enum PrimaryColor {Red, Green, Blue;}
enum PastelColor {Pink, HotPink, Rockmelon, SkyBlue, BabyBlue;}

enum TransportMedium {Land, Sea, Air;}
enum Vehicle {Car, Truck, BigBoat, LittleBoat, JetFighter, HotAirBaloon;}

您可以编写通用方法,说“好的,给定一个枚举值,它是一些其他枚举值的父级,子类型的所有可能子枚举中有多少百分比将这个特定的父值作为其父值?”,并拥有一切类型安全且无需强制转换即可完成。(例如:“海”是所有可能的车辆的 33%,“绿色”是所有可能的粉彩的 20%)。

代码如下所示。这很糟糕,但有办法让它变得更好。特别注意“叶子”类本身非常简洁——泛型类的声明非常丑陋,但你只写一次。一旦有了泛型类,就很容易使用它们。

import java.util.EnumSet;

import javax.swing.JComponent;

public class zz extends JComponent {

    public static void main(String[] args) {
        System.out.println(PrimaryColor.Green + " " + ParentUtil.pctOf(PrimaryColor.Green) + "%");
        System.out.println(TransportMedium.Air + " " + ParentUtil.pctOf(TransportMedium.Air) + "%");
    }


}

class ParentUtil {
    private ParentUtil(){}
    static <P extends Enum<P> & Parent<P, C>, C extends Enum<C> & Child<P, C>> //
    float pctOf(P parent) {
        return (float) parent.getChildren().size() / //
                (float) EnumSet.allOf(parent.getChildClass()).size() //
                * 100f;
    }
    public static <P extends Enum<P> & Parent<P, C>, C extends Enum<C> & Child<P, C>> //
    EnumSet<C> loadChildrenOf(P p) {
        EnumSet<C> cc = EnumSet.noneOf(p.getChildClass());
        for(C c: EnumSet.allOf(p.getChildClass())) {
            if(c.getParent() == p) {
                cc.add(c);
            }
        }
        return cc;
    }
}

interface Parent<P extends Enum<P> & Parent<P, C>, C extends Enum<C> & Child<P, C>> {
    Class<C> getChildClass();

    EnumSet<C> getChildren();
}

interface Child<P extends Enum<P> & Parent<P, C>, C extends Enum<C> & Child<P, C>> {
    Class<P> getParentClass();

    P getParent();
}

enum PrimaryColor implements Parent<PrimaryColor, PastelColor> {
    Red, Green, Blue;

    private EnumSet<PastelColor>    children;

    public Class<PastelColor> getChildClass() {
        return PastelColor.class;
    }

    public EnumSet<PastelColor> getChildren() {
        if(children == null) children=ParentUtil.loadChildrenOf(this);
        return children;
    }
}

enum PastelColor implements Child<PrimaryColor, PastelColor> {
    Pink(PrimaryColor.Red), HotPink(PrimaryColor.Red), //
    Rockmelon(PrimaryColor.Green), //
    SkyBlue(PrimaryColor.Blue), BabyBlue(PrimaryColor.Blue);

    final PrimaryColor  parent;

    private PastelColor(PrimaryColor parent) {
        this.parent = parent;
    }

    public Class<PrimaryColor> getParentClass() {
        return PrimaryColor.class;
    }

    public PrimaryColor getParent() {
        return parent;
    }
}

enum TransportMedium implements Parent<TransportMedium, Vehicle> {
    Land, Sea, Air;

    private EnumSet<Vehicle>    children;

    public Class<Vehicle> getChildClass() {
        return Vehicle.class;
    }

    public EnumSet<Vehicle> getChildren() {
        if(children == null) children=ParentUtil.loadChildrenOf(this);
        return children;
    }
}

enum Vehicle implements Child<TransportMedium, Vehicle> {
    Car(TransportMedium.Land), Truck(TransportMedium.Land), //
    BigBoat(TransportMedium.Sea), LittleBoat(TransportMedium.Sea), //
    JetFighter(TransportMedium.Air), HotAirBaloon(TransportMedium.Air);

    private final TransportMedium   parent;

    private Vehicle(TransportMedium parent) {
        this.parent = parent;
    }

    public Class<TransportMedium> getParentClass() {
        return TransportMedium.class;
    }

    public TransportMedium getParent() {
        return parent;
    }
}
于 2009-02-22T07:22:36.420 回答
5

已经提到,最终数组可用于将变量传递出匿名内部类。

另一种可以说是更好且不那么丑陋的方法是使用 java.util.concurrent.atomic 包中的 AtomicReference(或 AtomicBoolean/AtomicInteger/...)类。

这样做的好处之一是这些类还提供了诸如 之类的方法compareAndSet,如果您要创建多个可以修改同一变量的线程,这可能很有用。


另一个有用的相关模式:

final AtomicBoolean dataMsgReceived = new AtomicBoolean(false);
final AtomicReference<Message> message = new AtomicReference<Message>();
withMessageHandler(new MessageHandler() {
    public void handleMessage(Message msg) {
         if (msg.isData()) {
             synchronized (dataMsgReceived) {
                 message.set(msg);
                 dataMsgReceived.set(true);
                 dataMsgReceived.notifyAll();
             }
         }
    }
}, new Interruptible() {
    public void run() throws InterruptedException {
        synchronized (dataMsgReceived) {
            while (!dataMsgReceived.get()) {
                dataMsgReceived.wait();
            }
        }
    }
});

在这个特定的示例中,我们可以简单地等待消息变为非空,但是空通常可能是一个有效值,然后您需要使用单独的标志来完成等待。

waitMessageHandler(…)上面是另一个有用的模式:它在某个地方设置一个处理程序,然后开始执行可能抛出异常的Interruptible ,然后在 finally 块中删除处理程序,如下所示:

private final AtomicReference<MessageHandler> messageHandler = new AtomicReference<MessageHandler>();
public void withMessageHandler(MessageHandler handler, Interruptible logic) throws InterruptedException {
    synchronized (messageHandler) {
        try {
            messageHandler.set(handler);
            logic.run();
        } finally {
            messageHandler.set(null);
        }
    }
}

在这里,我假设messageHandler的(如果它不为 null)handleMessage(…)方法在收到消息时被另一个线程调用。messageHandler不能简单地属于MessageHandler类型:那样您将在变化的变量上进行同步,这显然是一个错误。

当然,它不需要是InterruptedException,它可以是IOException之类的东西,或者任何在特定代码段中有意义的东西。

于 2009-08-14T09:35:40.983 回答
5

阅读 Joshua Bloch 的“Java Puzzlers”,你会感到既受启发又感到恐惧。

于 2009-04-20T03:26:55.897 回答
4

显然,对于一些调试版本,有一个选项可以从 HotSpot 转储本机(JIT)汇编代码:http ://weblogs.java.net/blog/kohsuke/archive/2008/03/deep_dive_into.html

不幸的是,我无法通过该帖子中的链接找到构建,如果有人能找到更精确的 URL,我很乐意使用它。

于 2008-12-03T06:21:29.423 回答
4

函子很酷。它们非常接近函数指针,每个人通常很快就会说这在 Java 中是不可能的。

Java中的函子

于 2008-08-29T19:36:48.253 回答
4

SwingWorker用于轻松管理来自后台线程的用户界面回调。

于 2008-11-20T20:19:01.450 回答
4

您可以在枚举类的方法定义中切换(this)。让我大喊“哇!” 当我发现这确实有效时,大声说出来。

于 2009-11-26T17:57:23.910 回答
4

您可以使用对象添加泛型类型的运行时检查,Class<T>当在某处的配置文件中创建类并且无法为类的泛型类型添加编译时检查时,这会派上用场。如果应用程序恰好配置错误并且您不希望所有类都充斥着检查实例,您不希望该类在运行时爆炸。

public interface SomeInterface {
  void doSomething(Object o);
}
public abstract class RuntimeCheckingTemplate<T> {
  private Class<T> clazz;
  protected RuntimeChecking(Class<T> clazz) {
    this.clazz = clazz;
  }

  public void doSomething(Object o) {
    if (clazz.isInstance(o)) {
      doSomethingWithGeneric(clazz.cast(o));
    } else {
      // log it, do something by default, throw an exception, etc.
    }
  }

  protected abstract void doSomethingWithGeneric(T t);
}

public class ClassThatWorksWithStrings extends RuntimeCheckingTemplate<String> {
  public ClassThatWorksWithStrings() {
     super(String.class);
  }

  protected abstract void doSomethingWithGeneric(T t) {
    // Do something with the generic and know that a runtime exception won't occur 
    // because of a wrong type
  }
}
于 2010-03-03T15:17:48.277 回答
3

因为还没有人说过(我想)我最喜欢的功能是自动拳击!

public class Example
{
    public static void main(String[] Args)
    {
         int a = 5;
         Integer b = a; // Box!
         System.out.println("A : " + a);
         System.out.println("B : " + b);
    }
}
于 2008-09-20T04:14:30.023 回答
3

几年前,当我不得不做 Java (1.4.x) 时,我想要一个 eval() 方法,而 Suns javac 是(曾经?)用 Java 编写的,所以它只是链接 tools.jar 并将其与一些胶水代码一起使用它。

于 2008-10-04T21:05:34.530 回答
2

您可以覆盖一个方法并让超类构造函数调用它(这可能会让 C++ 程序员感到惊讶。)

例子

于 2010-01-25T07:20:06.250 回答
1

我喜欢

  1. javadoc的 taglet 和 doclet 使我们能够自定义 javadoc 输出。
  2. JDK 工具:jstat、jstack 等。
于 2009-01-29T17:44:43.460 回答
0

Java Bean 属性访问器方法不必“get”和“set”开头。

甚至 Josh Bloch 在 Effective Java 中也犯了这个错误。

于 2009-06-22T15:10:26.857 回答
-3

当我第一次注意到三元运算符等于一个简单的 if-then-else 语句时,我感到很惊讶:

minVal = (a < b) ? a : b;
于 2010-04-09T12:15:46.503 回答
-8

令我惊讶的是,一个接口可以扩展多个接口,但类只能扩展一个类。

于 2009-12-03T07:08:29.057 回答