Bor*_*zic 432
几个月前,当我第一次发现它时,双支撑初始化让我感到意外,从未听说过它.
ThreadLocals通常不是众所周知的存储每线程状态的方法.
由于JDK 1.5 Java具有非常好的实现和强大的并发工具,而不仅仅是锁,它们存在于java.util.concurrent中,一个特别有趣的例子是java.util.concurrent.atomic子包,它包含实现比较的线程安全原语和交换操作,可以映射到这些操作的实际本机硬件支持版本.
Apo*_*isp 279
类型参数方差中的联合联合:
public class Baz<T extends Foo & Bar> {}
Run Code Online (Sandbox Code Playgroud)
例如,如果您想要一个兼容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);
}
Run Code Online (Sandbox Code Playgroud)
如果两个给定集合相等或者其中任何一个包含给定元素,则该设计方法返回true,否则返回false.需要注意的是,您可以在参数b1和b2上调用Comparable和Collection的方法.
Dav*_*son 220
前几天,我对实例初始化程序感到惊讶.我正在删除一些代码折叠的方法,最后创建了多个实例初始化器:
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");
}
}
Run Code Online (Sandbox Code Playgroud)
执行该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
Run Code Online (Sandbox Code Playgroud)
我想如果你有多个构造函数并需要公共代码,这些将是有用的
它们还为初始化类提供语法糖:
List<Integer> numbers = new ArrayList<Integer>(){{ add(1); add(2); }};
Map<String,String> codes = new HashMap<String,String>(){{
put("1","one");
put("2","two");
}};
Run Code Online (Sandbox Code Playgroud)
cro*_*wne 173
自Java 6以来的Classpath外卡.
java -classpath ./lib/* so.Main
Run Code Online (Sandbox Code Playgroud)
代替
java -classpath ./lib/log4j.jar:./lib/commons-codec.jar:./lib/commons-httpclient.jar:./lib/commons-collections.jar:./lib/myApp.jar so.Main
Run Code Online (Sandbox Code Playgroud)
请参阅http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html
Geo*_*uba 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;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
谁goto
在java中说只是一个关键字?:)
ser*_*g10 144
从JDK 1.5开始,协变返回类型如何?它的宣传非常糟糕,因为它是一个不容易添加的东西,但据我所知,泛型工作绝对是必要的.
本质上,编译器现在允许子类将重写方法的返回类型缩小为原始方法的返回类型的子类.所以这是允许的:
class Souper {
Collection<String> values() {
...
}
}
class ThreadSafeSortedSub extends Souper {
@Override
ConcurrentSkipListSet<String> values() {
...
}
}
Run Code Online (Sandbox Code Playgroud)
您可以调用子类的values
方法并获取s 的已排序线程安全Set
,而无需向下转换为.String
ConcurrentSkipListSet
Jam*_*fer 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;
}
}
Run Code Online (Sandbox Code Playgroud)
来自http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
小智 141
没有看到有人提到实现的实例是以不需要检查null的方式实现的.
代替:
if( null != aObject && aObject instanceof String )
{
...
}
Run Code Online (Sandbox Code Playgroud)
只需使用:
if( aObject instanceof String )
{
...
}
Run Code Online (Sandbox Code Playgroud)
Adr*_*uat 134
在枚举中允许方法和构造函数让我感到惊讶.例如:
enum Cats {
FELIX(2), SHEEBA(3), RUFUS(7);
private int mAge;
Cats(int age) {
mAge = age;
}
public int getAge() {
return mAge;
}
}
Run Code Online (Sandbox Code Playgroud)
您甚至可以拥有一个"常量特定类主体",它允许特定的枚举值覆盖方法.
这里有更多文档.
Kev*_*ong 121
泛型方法的类型参数可以明确指定,如下所示:
Collections.<String,Integer>emptyMap()
Run Code Online (Sandbox Code Playgroud)
Pet*_*rey 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; }
}
Run Code Online (Sandbox Code Playgroud)
编辑:多年后....
我在这里使用这个功能
public enum AffinityStrategies implements AffinityStrategy {
Run Code Online (Sandbox Code Playgroud)
通过使用界面,开发人员可以定义自己的策略.使用一种enum
方法,我可以定义一个内置的集合(五个).
Pau*_*cks 104
从Java 1.5开始,Java现在有更清晰的语法来编写变量arity的函数.因此,现在您可以执行以下操作,而不仅仅是传递数组
public void foo(String... bars) {
for (String bar: bars)
System.out.println(bar);
}
Run Code Online (Sandbox Code Playgroud)
条形图自动转换为指定类型的数组.不是一场巨大的胜利,而是一场胜利.
Chr*_*ola 93
我最喜欢的:将所有线程堆栈跟踪转储到标准输出.
windows:CTRL- Break在你的java cmd/console窗口中
UNIX: kill -3 PID
Jac*_*eow 89
有几个人发布了关于实例初始化器的信息,这里有一个很好的用途:
Map map = new HashMap() {{
put("a key", "a value");
put("another key", "another value");
}};
Run Code Online (Sandbox Code Playgroud)
如果您只是快速而简单地执行某些操作,那么这是一种快速初始化地图的方法.
或者使用它来创建快速摆动框架原型:
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 );
Run Code Online (Sandbox Code Playgroud)
当然可以滥用:
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");
}
});
}});
}});
}};
Run Code Online (Sandbox Code Playgroud)
All*_*nde 82
最终初始化可以推迟.
它确保即使具有复杂的逻辑流返回值也始终设置.错过一个案例并且偶然返回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;
}
Run Code Online (Sandbox Code Playgroud)
Mo.*_*Mo. 62
我认为java的另一个"被忽视的"特性是JVM本身.它可能是最好的VM.它支持许多有趣且有用的语言(Jython,JRuby,Scala,Groovy).所有这些语言都可以轻松无缝地进行合作.
如果你设计一种新语言(比如在scala-case中),你可以立即使用所有现有的库,因此从一开始你的语言就是"有用的".
所有这些语言都使用HotSpot优化.VM非常好监视和调试.
Ron*_*Ron 58
您可以定义匿名子类并直接在其上调用方法,即使它没有实现接口也是如此.
new Object() {
void foo(String s) {
System.out.println(s);
}
}.foo("Hello");
Run Code Online (Sandbox Code Playgroud)
Bru*_*ine 56
该asList的方法java.util.Arrays
允许可变参数,泛型方法和自动装箱的一个很好的组合:
List<Integer> ints = Arrays.asList(1,2,3);
Run Code Online (Sandbox Code Playgroud)
Tah*_*tar 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;
}
}
Run Code Online (Sandbox Code Playgroud)
Phi*_*Lho 52
这不是一个功能,但我最近在一些网页上发现了一个有趣的技巧:
class Example
{
public static void main(String[] args)
{
System.out.println("Hello World!");
http://Phi.Lho.free.fr
System.exit(0);
}
}
Run Code Online (Sandbox Code Playgroud)
是一个有效的Java程序(虽然它会生成一个警告).如果你不明白为什么,请看格雷戈里的回答!;-)嗯,这里的语法高亮也给出了一个提示!
Das*_*Das 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);
}
};
}
Run Code Online (Sandbox Code Playgroud)
小智 38
我的投票是java.util.concurrent及其并发集合和灵活的执行程序,允许其他线程池,计划任务和协调任务.DelayQueue是我个人的最爱,在指定的延迟后元素可用.
java.util.Timer和TimerTask可以安全地休息.
此外,不是完全隐藏,而是与其他与日期和时间相关的类不同的包.java.util.concurrent.TimeUnit在纳秒,微秒,毫秒和秒之间转换时非常有用.
它读取比通常的someValue*1000或someValue/1000好很多.
Mar*_*ade 37
语言级断言关键字.
18R*_*bit 36
在1.5中添加for-each循环结构.我<3.
// For each Object, instantiated as foo, in myCollection
for(Object foo: myCollection) {
System.out.println(foo.toString());
}
Run Code Online (Sandbox Code Playgroud)
并且可以在嵌套实例中使用:
for (Suit suit : suits)
for (Rank rank : ranks)
sortedDeck.add(new Card(suit, rank));
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
Rah*_*thy 34
我个人发现java.lang.Void
很晚 - 与泛型一起提高代码可读性,例如Callable<Void>
Pet*_*rey 30
也许最令人惊讶的隐藏功能是sun.misc.Unsafe类.
http://www.docjar.com/html/api/ClassLib/Common/sun/misc/Unsafe.java.html
您可以;
顺便说一句:错误地使用这个类会杀死JVM.我不知道哪个JVM支持这个类,所以它不可移植.
Lui*_*ano 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!"));
}
}
Run Code Online (Sandbox Code Playgroud)
你也许想知道你可以抛出'null'......
public static void main(String[] args) {
throw null;
}
Run Code Online (Sandbox Code Playgroud)
猜猜这是什么印刷品:
Long value = new Long(0);
System.out.println(value.equals(0));
Run Code Online (Sandbox Code Playgroud)
而且,猜猜这回归:
public int returnSomething() {
try {
throw new RuntimeException("foo!");
} finally {
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
以上不应该让优秀的开发者感到惊讶
在Java中,您可以通过以下有效方式声明数组:
String[] strings = new String[] { "foo", "bar" };
// the above is equivalent to the following:
String[] strings = { "foo", "bar" };
Run Code Online (Sandbox Code Playgroud)
所以遵循Java代码是完全有效的:
public class Foo {
public void doSomething(String[] arg) {}
public void example() {
String[] strings = { "foo", "bar" };
doSomething(strings);
}
}
Run Code Online (Sandbox Code Playgroud)
是否有任何正当理由,相反,以下代码不应有效?
public class Foo {
public void doSomething(String[] arg) {}
public void example() {
doSomething({ "foo", "bar" });
}
}
Run Code Online (Sandbox Code Playgroud)
我认为,上面的语法将是Java 5中引入的varargs的有效替代.并且,与之前允许的数组声明更加一致.
SRG*_*SRG 28
关机钩.这允许注册一个即时创建但仅在JVM结束时启动的线程!所以它是某种"全局jvm终结器",你可以在这个线程中做出有用的东西(例如关闭像嵌入式hsqldb服务器这样的java资源).这适用于System.exit(),或者使用CTRL-C/kill -15(当然不能使用unix上的kill -9).
此外,它很容易设置.
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
endApp();
}
});;
Run Code Online (Sandbox Code Playgroud)
Jac*_*eow 27
的价值:
new URL("http://www.yahoo.com").equals(new URL("http://209.191.93.52"))
Run Code Online (Sandbox Code Playgroud)
是true
.
(来自Java Puzzlers)
Kev*_*Day 26
如果你做了很多JavaBean开发并使用属性更改支持,你通常会编写很多像这样的setter:
public void setFoo(Foo aFoo){
Foo old = this.foo;
this.foo = aFoo;
changeSupport.firePropertyChange("foo", old, aFoo);
}
Run Code Online (Sandbox Code Playgroud)
我最近偶然发现了一个博客,该博客建议更简洁的实现,使代码更容易编写:
public void setFoo(Foo aFoo){
changeSupport.firePropertyChange("foo", this.foo, this.foo = aFoo);
}
Run Code Online (Sandbox Code Playgroud)
它实际上简化了我能够在Eclipse中调整setter模板的程度,以便自动创建方法.
Mic*_*ale 25
静态导入以"增强"语言,因此您可以以类型安全的方式做好文字事物:
List<String> ls = List("a", "b", "c");
Run Code Online (Sandbox Code Playgroud)
(也可以使用地图,数组,集合).
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")));
Run Code Online (Sandbox Code Playgroud)
PPS*_*PPS 23
作为首发,我非常欣赏Java 6中的JConsole监控软件,它已经为我解决了一些问题,并且我一直在寻找它的新用途.
显然JConsole已经存在于Java 5中,但我认为它现在已得到改进,至少现在工作得更稳定了.
Java 5中的JConsole:Java 5中的 JConsole
Java 6中的JConsole:Java 6中的 JConsole
在阅读本文时,请仔细阅读本系列中的其他工具: Java 6故障排除工具
Osc*_*Ryz 23
不是那么隐蔽,而是有趣.
你可以拥有一个没有main方法的"Hello,world"(它会抛出NoSuchMethodError的想法)
最初由RusselW发布在Strangest 语言功能上
public class WithoutMain {
static {
System.out.println("Look ma, no main!!");
System.exit(0);
}
}
$ java WithoutMain
Look ma, no main!!
Run Code Online (Sandbox Code Playgroud)
Bil*_*l K 22
如果不使用默认初始值设定项,Java处理会对变量定义进行巧妙处理.
{ int x; if(whatever) x=1; if(x == 1) ... }
这将在编译时给您一个错误,即您有一个未正确定义X的路径.这对我有所帮助,我已经考虑过这样的默认初始化:
int x=0; String s=null;
是一个糟糕的模式,因为它阻止这个有用的检查.
也就是说,有时它很难绕过 - 我必须返回并在= null时进行编辑,当它作为默认值有意义时,但我再也不会把它放在第一遍了.
Jas*_*ang 21
这不是一个真正隐藏的功能,但当我看到这个编译好的时候它确实给了我一个大惊喜:
public int aMethod(){
http://www.google.com
return 1;
}
Run Code Online (Sandbox Code Playgroud)
它编译的原因是http://www.google.com的"http:"部分被编译器视为标签,其余部分是注释.
所以,如果你想写一些古怪的代码(或混淆的代码),只需在那里放置很多http地址.;-)
oxb*_*kes 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);
}
Run Code Online (Sandbox Code Playgroud)
小智 17
自限泛型:
class SelfBounded<T extends SelfBounded<T>> {
}
Run Code Online (Sandbox Code Playgroud)
http://www.artima.com/weblogs/viewpost.jsp?thread=136394
you*_*uri 16
我喜欢静态导入方法.
例如,创建以下util类:
package package.name;
public class util {
private static void doStuff1(){
//the end
}
private static String doStuff2(){
return "the end";
}
}
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它.
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()
}
}
Run Code Online (Sandbox Code Playgroud)
Static Imports适用于任何类,甚至是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");
}
}
Run Code Online (Sandbox Code Playgroud)
chi*_*tom 16
List.subList返回原始列表上的视图
列表的文档但鲜为人知的特征.这允许您使用原始列表中镜像的更改来处理列表的某些部分.
列出subList(int fromIndex,int toIndex)
"此方法消除了对显式范围操作(对于数组通常存在的排序)的需要.任何期望列表的操作都可以通过传递subList视图而不是整个列表来用作范围操作.例如,以下成语从列表中删除一系列元素:
Run Code Online (Sandbox Code Playgroud)list.subList(from, to).clear();
可以为indexOf和lastIndexOf构造类似的习语,Collections类中的所有算法都可以应用于subList."
Jon*_*cke 16
哦,我差点忘了这个小宝石.在任何运行的java进程上试试这个:
jmap -histo:直播PID
您将获得给定VM中的实时堆对象的直方图.非常宝贵,可以快速识别某些类型的内存泄漏.我用来防止它们的另一种技术是创建和使用所有集合类的大小有限的子类.这会导致易于识别的失控集合中的快速失败.
kca*_*k11 16
用于显示基于Java控制台的应用程序的初始屏幕的功能.
使用命令行工具java
或javaw
选项-splash
例如:
java -splash:C:\myfolder\myimage.png -classpath myjarfile.jar com.my.package.MyClass
Run Code Online (Sandbox Code Playgroud)
C:\myfolder\myimage.png
每当执行"com.my.package.MyClass"类时,内容将显示在屏幕的中央
ser*_*g10 15
这不是一个特色,但它让我轻笑,这goto
是一个保留的词,除了提示javac戳你的眼睛之外什么也不做.只是为了提醒你,你现在在OO-land.
小智 15
Javadoc - 当正确编写时(不幸的是一些开发人员的情况并非如此),它为您提供了一个清晰,连贯的描述代码应该做什么,而不是实际做什么.然后它可以变成一个很好的可浏览的HTML文档集.如果您使用持续集成等,它可以定期生成,以便所有开发人员都可以看到最新的更新.
小智 15
使用静态导入,你可以做很酷的事情:
List<String> myList = list("foo", "bar");
Set<String> mySet = set("foo", "bar");
Map<String, String> myMap = map(v("foo", "2"), v("bar", "3"));
Run Code Online (Sandbox Code Playgroud)
Rom*_*Guy 14
strictfp关键字.(我从来没有看到它用于真正的应用程序:)
您可以使用以下表示法获取基本类型的类:int.class,float.class等.在进行反射时非常有用.
最终数组可用于从匿名内部类"返回"值(警告,下面没用的示例):
final boolean[] result = new boolean[1];
SwingUtilities.invokeAndWait(new Runnable() {
public void run() { result[0] = true; }
});
Run Code Online (Sandbox Code Playgroud)
Osc*_*Ryz 14
您可以在匿名内部类上定义和调用方法.
好吧,他们不是那么隐藏,但是很少有人知道它们可以用来在类中定义一个新方法并像这样调用它:
(new Object() {
public String someMethod(){
return "some value";
}
}).someMethod();
Run Code Online (Sandbox Code Playgroud)
可能不是很常见,因为它也不是很有用,你可以只在你定义它时(或通过反射)调用它的方法
yal*_*tar 13
我知道Java 6包含脚本支持,但我刚刚发现了jrunscript,它可以交互式地解释和运行JavaScript(以及一种假设,其他脚本语言,如Groovy),有点像Ruby shell或Ruby中的irb
st0*_*0le 13
C风格的printf():)
System.out.printf("%d %f %.4f", 3,Math.E,Math.E);
Run Code Online (Sandbox Code Playgroud)
产量:3 2.718282 2.7183
二进制搜索(和它的返回值)
int[] q = new int[] { 1,3,4,5};
int position = Arrays.binarySearch(q, 2);
Run Code Online (Sandbox Code Playgroud)
与C#类似,如果在数组中找不到"2",则返回负值,但是如果您获取返回值的1的补码,则实际上可以获得可以插入"2"的位置.
在上面的例子中,position = -2,~position = 1,这是应该插入2的位置......它还可以让你找到数组中"最接近"的匹配.
我觉得它很漂亮...... :)
Joh*_*her 12
它并没有完全隐藏,但反射非常有用和强大.很高兴使用一个简单的Class.forName("...").newInstance(),其中类类型是可配置的.编写这种工厂实现很容易.
小智 12
部分功能,部分麻烦:Java的字符串处理使其"显示"为本机类型(在它们上使用运算符,+,+ =)
能够写:
String s = "A";
s += " String"; // so s == "A String"
Run Code Online (Sandbox Code Playgroud)
是非常方便的,但只是语法糖(即编译到):
String s = new String("A");
s = new StringBuffer(s).append(" String").toString();
Run Code Online (Sandbox Code Playgroud)
为一个简单的连接提供了一个Object实例和2个方法调用.想象一下,以这种方式在循环内构建一个长字符串!?并且所有StringBuffer的方法都声明为synchronized.值得庆幸的是(我认为)Java 5他们引入了StringBuilder,它与没有同步的StringBuffer相同.
循环如:
String s = "";
for (int i = 0 ; i < 1000 ; ++i)
s += " " + i; // Really an Object instantiation & 3 method invocations!
Run Code Online (Sandbox Code Playgroud)
可以(应该)在您的代码中重写为:
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();
Run Code Online (Sandbox Code Playgroud)
并且比原始循环运行速度快大约80 +%!(我运行的一些基准测试高达180%)
dme*_*ter 11
最终的例如变量:
对多线程代码非常有用,它可以更容易地争论实例状态和正确性.在行业环境中没有看到太多,并且在java类中经常没有想到.
static {something;}:
用于初始化静态成员(我也更喜欢静态方法来做它(因为它有一个名字).没想到.
Pet*_*ore 11
我今天(刚刚)了解到,$是Java中方法或变量的合法名称.结合静态导入,它可以使一些稍微更易读的代码,具体取决于您的可读视图:
http://garbagecollected.org/2008/04/06/dollarmaps/
Mic*_*ers 10
"const"是关键字,但您无法使用它.
int const = 1; // "not a statement"
const int i = 1; // "illegal start of expression"
Run Code Online (Sandbox Code Playgroud)
我想编译器编写者认为它可能会在未来使用,他们最好保留它.
Dav*_*vis 10
一种优化技巧,使您的代码更易于维护,并且不易受并发错误的影响.
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 )
;
}
}
Run Code Online (Sandbox Code Playgroud)
$ time java Slow
real 0m15.397s
$ time java
slow real 0m20.012s
$ time java
slow real 0m18.645s
平均值:18.018s
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;
}
}
Run Code Online (Sandbox Code Playgroud)
$ time java Fast
real 0m12.003s
$ time java fast
real 0m9.840s
$ time java fast
real 0m9.686s
平均值:10.509秒
它需要更多的字节码来引用类范围变量而不是方法范围变量.在关键循环之前添加方法调用会增加很少的开销(无论如何,调用可能会被编译器内联).
这种技术的另一个优点(总是使用访问器)是它消除了Slow类中的潜在错误.如果第二个线程不断地将i的值重置为0(slow.setI( 0 )
例如,通过调用),则Slow类永远不会结束其循环.调用访问器并使用局部变量消除了这种可能性.
在Linux 2.6.27-14上使用J2SE 1.6.0_13进行测试.
Las*_*ico 10
使用StringBuilder
而不是StringBuffer
在不需要同步管理时使用StringBuilder
.它将提高您的应用程序的性能.
Java 7的改进甚至比任何隐藏的Java功能都要好:
不要在instanciation使用那些无限<>语法:
Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
// Can now be replaced with this:
Map<String, List<String>> anagrams = new HashMap<>();
Run Code Online (Sandbox Code Playgroud)
在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;
}
Run Code Online (Sandbox Code Playgroud)
这个旧代码:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
现在可以用这个更简单的代码替换:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
您选择的编码中的属性文件怎么样?以前,当您加载属性时,您提供了一个InputStream,并且该load()
方法将其解码为ISO-8859-1.您实际上可以将文件存储在其他一些编码中,但是在加载以正确解码数据之后,您必须使用这样的令人厌恶的黑客:
String realProp = new String(prop.getBytes("ISO-8859-1"), "UTF-8");
Run Code Online (Sandbox Code Playgroud)
但是,从JDK 1.6开始,有一种load()
方法可以使用Reader而不是InputStream,这意味着您可以从头开始使用正确的编码(还有store()
一种采用Writer 的方法).这对我来说似乎是一件非常重要的事情,但它似乎一直没有大张旗鼓地进入JDK.几个星期前我偶然发现了它,并且快速谷歌搜索只是提到了它.
让我感到惊讶的是自定义序列化机制.
虽然这些方法是私密的!! ,它们在对象序列化期间由JVM " 神秘地 "调用.
private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
Run Code Online (Sandbox Code Playgroud)
通过这种方式,您可以创建自己的自定义序列化,使其更"无所不能"(安全,快速,稀有,简单等)
如果必须通过节点传递大量信息,则应该考虑这一点.可以改变序列化机制以发送一半数据.很多时候瓶颈不在平台上,但是通过电线发送的数量,可以在硬件中节省数千个dll.
这是一篇文章. http://java.sun.com/developer/technicalArticles/Programming/serialization/
标识符可以包含像变音符号这样的外语字符:
而不是写:
String title="";
Run Code Online (Sandbox Code Playgroud)
有人可以写:
String Überschrift="";
Run Code Online (Sandbox Code Playgroud)
小智 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();
Run Code Online (Sandbox Code Playgroud)
当人们意识到可以使用反射调用私有方法和访问/更改私有字段时,人们有时会感到有些惊讶......
考虑以下课程:
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+"]";
}
}
Run Code Online (Sandbox Code Playgroud)
执行这个程序......
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);
}
}
Run Code Online (Sandbox Code Playgroud)
...将产生以下输出:
Foo[bar=17]
Foo[bar=42]
Foo[bar=23]
Run Code Online (Sandbox Code Playgroud)
小智 8
大多数人都不知道他们可以克隆阵列.
int[] arr = {1, 2, 3};
int[] arr2 = arr.clone();
Run Code Online (Sandbox Code Playgroud)
小智 7
您可以拥有的垃圾收集器以及它如何管理对象收集的功能非常强大,特别是对于长时间运行和时间敏感的应用程序.它从java.lang.ref包中的weak,soft和phantom引用开始.看看那些,尤其是构建缓存(已经有java.util.WeakHashMap).现在深入了解ReferenceQueue,您将开始拥有更多控制权.最后抓住垃圾收集器本身的文档,你将能够控制它运行的频率,不同收集区域的大小以及所使用的算法类型(对于Java 5,请参阅http://java.sun.com/docs /hotspot/gc5.0/gc_tuning_5.html).
您可以访问初始化块中的最终局部变量和参数以及本地类的方法.考虑一下:
final String foo = "42";
new Thread() {
public void run() {
dowhatever(foo);
}
}.start();
Run Code Online (Sandbox Code Playgroud)
有点像关闭,不是吗?
您可以使用String.format()构建字符串sprintf样式.
String w = "world";
String s = String.format("Hello %s %d", w, 3);
Run Code Online (Sandbox Code Playgroud)
您当然也可以使用特殊说明符来修改输出.
更多信息:http://java.sun.com/j2se/1.5.0/docs/api/java/util/Formatter.html#syntax
实际上,我喜欢Java的是有多少隐藏的技巧.这是一种非常明显的语言.这么多,经过15年,我能想到的几乎每一个都已列在这几页上.
也许大多数人都知道Collections.synchronizedList()会将同步添加到列表中.除非您阅读文档,否则您无法知道的是,您可以通过同步列表对象本身来安全地迭代该列表的元素.
某些人可能不知道CopyOnWriteArrayList,而Future代表了一种抽象多线程结果访问的有趣方式.
您可以通过各种管理,代理和附加API附加到VM(本地或远程),获取有关GC活动,内存使用,文件描述符甚至对象大小的信息.
虽然TimeUnit可能比long更好,但我更喜欢Wicket的Duration类.
finally
围绕return
声明的一些控制流技巧:
int getCount() {
try { return 1; }
finally { System.out.println("Bye!"); }
}
Run Code Online (Sandbox Code Playgroud)
明确赋值的规则将检查始终通过简单的控制流分析分配最终变量:
final int foo;
if(...)
foo = 1;
else
throw new Exception();
foo+1;
Run Code Online (Sandbox Code Playgroud)
同一个类的实例可以访问其他实例的私有成员:
class Thing {
private int x;
public int addThings(Thing t2) {
return this.x + t2.x; // Can access t2's private value!
}
}
Run Code Online (Sandbox Code Playgroud)
源代码网址.例如,这里有一些合法的java源代码:
http://google.com
Run Code Online (Sandbox Code Playgroud)
(是的,它出现在Java Puzzlers中.我笑了......)
没看过这个
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!
Run Code Online (Sandbox Code Playgroud)
通过搜索java的整数池(内部'缓存'从-128到127进行自动装箱)或者查看Integer.valueOf来了解更多相关信息.
字符串参数化类工厂.
Class.forName( className ).newInstance();
Run Code Online (Sandbox Code Playgroud)
从部署jar文件加载资源(属性文件,xml,xslt,image等).
this.getClass().getClassLoader().getResourceAsStream( ... ) ;
Run Code Online (Sandbox Code Playgroud)
Java 1.6 Update 10及更高版本中的下一代Java插件具有一些非常简洁的功能:
此处记录的许多其他内容:http://jdk6.dev.java.net/plugin2/
更多来自此版本:http://jdk6.dev.java.net/6u10ea.html
交集类型允许您(有点排序)执行具有继承层次结构的枚举.您不能继承实现,但可以将其委托给辅助类.
enum Foo1 implements Bar {}
enum Foo2 implements Bar {}
class HelperClass {
static <T extends Enum<T> & Bar> void fooBar(T the enum) {}
}
Run Code Online (Sandbox Code Playgroud)
当您有许多实现某种模式的不同枚举时,这很有用.例如,许多具有父子关系的枚举对.
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;}
Run Code Online (Sandbox Code Playgroud)
您可以编写通用方法,说"好的,给定一个枚举值,该值是某些其他枚举值的父级,子类型的所有可能子枚举中有多少百分比将此特定父值作为其父级?",并且全部使用类型安全,没有铸造完成.(例如:"Sea"占所有可能车辆的33%,"Green"占所有可能车辆的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;
}
}
Run Code Online (Sandbox Code Playgroud)
已经提到过,可以使用final数组从匿名内部类中传递变量.
另一个可以说是更好和更不丑的方法是使用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();
}
}
}
});
Run Code Online (Sandbox Code Playgroud)
在这个特定的例子中,我们可以简单地等待消息使其变为非空,但是null通常可以是有效值,然后您需要使用单独的标志来完成等待.
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里我假设在接收到消息时,另一个线程调用messageHandler(如果它不为null)handleMessage(…)
方法.messageHandler不能只是MessageHandler类型:这样你就会对变化的变量进行同步,这显然是一个bug.
当然,它不需要是InterruptedException,它可能类似于IOException,或者在特定代码段中有意义的东西.
Java 6(来自Sun)附带一个嵌入式JavaScrip解释器.
http://java.sun.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html#jsengine
归档时间: |
|
查看次数: |
211713 次 |
最近记录: |