Sau khi đọc các tính năng ẩn của C #, tôi tự hỏi, một số tính năng ẩn của Java là gì?
Sau khi đọc các tính năng ẩn của C #, tôi tự hỏi, một số tính năng ẩn của Java là gì?
Câu trả lời:
Double Brace Khởi tạo làm tôi ngạc nhiên một vài tháng trước khi tôi lần đầu tiên phát hiện ra nó, chưa bao giờ nghe về nó trước đây.
ThreadLocals thường không được biết đến rộng rãi như là một cách để lưu trữ trạng thái trên mỗi luồng.
Do JDK 1.5 Java đã có các công cụ đồng thời mạnh mẽ và được triển khai rất tốt ngoài các khóa, chúng sống trong java.util.concản và một ví dụ thú vị đặc biệt là gói con java.util.concản.atomic có chứa các nguyên hàm an toàn luồng thực hiện so sánh -và hoạt động hoán đổi và có thể ánh xạ tới các phiên bản hỗ trợ phần cứng thực tế của các hoạt động này.
Liên minh chung trong phương sai tham số loại:
public class Baz<T extends Foo & Bar> {}
Ví dụ: nếu bạn muốn lấy một tham số cả So sánh và Bộ sưu tập:
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);
}
Phương thức giả định này trả về true nếu hai tập hợp đã cho bằng nhau hoặc nếu một trong hai tập hợp đó chứa phần tử đã cho, ngược lại là false. Điểm cần chú ý là bạn có thể gọi các phương thức của cả So sánh và Thu thập trên các đối số b1 và b2.
Tôi đã ngạc nhiên bởi các trình khởi tạo cá thể vào ngày khác. Tôi đã xóa một số phương thức gấp mã và cuối cùng tạo ra nhiều bộ khởi tạo cá thể:
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");
}
}
Thực hiện main
phương thức sẽ hiển thị:
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
Tôi đoán những thứ này sẽ hữu ích nếu bạn có nhiều hàm tạo và cần mã chung
Họ cũng cung cấp đường cú pháp để khởi tạo các lớp học của bạn:
List<Integer> numbers = new ArrayList<Integer>(){{ add(1); add(2); }};
Map<String,String> codes = new HashMap<String,String>(){{
put("1","one");
put("2","two");
}};
JDK 1.6_07 + chứa một ứng dụng có tên VisualVM (bin / jvisualvm.exe) là một GUI đẹp trên nhiều công cụ. Nó có vẻ toàn diện hơn JConsole.
Thẻ hoang dã classpath kể từ Java 6.
java -classpath ./lib/* so.Main
Thay vì
java -classpath ./lib/log4j.jar:./lib/commons-codec.jar:./lib/commons-httpclient.jar:./lib/commons-collections.jar:./lib/myApp.jar so.Main
Xem http://java.sun.com/javase/6/docs/technotes/tools/windows/ classpath.html
Đối với hầu hết mọi người, tôi phỏng vấn cho các vị trí nhà phát triển Java được dán nhãn là rất đáng ngạc nhiên. Đây là một ví dụ:
// 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;
}
}
}
}
Ai nói goto
trong java chỉ là một từ khóa? :)
Làm thế nào về các kiểu trả về covariant đã có tại JDK 1.5? Nó được công bố khá kém, vì nó là một bổ sung unsexy, nhưng theo tôi hiểu, nó hoàn toàn cần thiết cho thuốc generic hoạt động.
Về cơ bản, trình biên dịch bây giờ cho phép một lớp con thu hẹp kiểu trả về của một phương thức được ghi đè thành một lớp con của kiểu trả về của phương thức ban đầu. Vì vậy, điều này được cho phép:
class Souper {
Collection<String> values() {
...
}
}
class ThreadSafeSortedSub extends Souper {
@Override
ConcurrentSkipListSet<String> values() {
...
}
}
Bạn có thể gọi của lớp con values
phương pháp và có được một sợi an toàn sắp xếp Set
của String
s mà không cần phải cast xuống đến ConcurrentSkipListSet
.
Chuyển quyền kiểm soát trong một khối cuối cùng ném đi bất kỳ ngoại lệ. Đoạn mã sau không ném RuntimeException - nó bị mất.
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;
}
}
Từ http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
Không thấy ai đề cập đến trường hợp được thực hiện theo cách mà việc kiểm tra null là không cần thiết.
Thay vì:
if( null != aObject && aObject instanceof String )
{
...
}
chỉ dùng:
if( aObject instanceof String )
{
...
}
free
ing hoặc delete
ing trong C / C ++. Như một khái niệm cơ bản.
Cho phép các phương thức và các nhà xây dựng trong enums làm tôi ngạc nhiên. Ví dụ:
enum Cats {
FELIX(2), SHEEBA(3), RUFUS(7);
private int mAge;
Cats(int age) {
mAge = age;
}
public int getAge() {
return mAge;
}
}
Bạn thậm chí có thể có một "thân lớp cụ thể không đổi" cho phép một giá trị enum cụ thể để ghi đè các phương thức.
Thêm tài liệu ở đây .
mAge
nên là cuối cùng. Hiếm khi có một lý do cho các feld không cuối cùng trong enums.
Các tham số loại cho các phương thức chung có thể được chỉ định rõ ràng như vậy:
Collections.<String,Integer>emptyMap()
public static <T> T foo(T t)
. Sau đó, bạn có thể thực hiện cuộc gọi đếnClass.<Type>foo(t);
return set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList()
. Nó cũng hữu ích cho một số lời gọi phương thức trong đó một Collections.emptyMap () đơn giản sẽ đưa ra một lỗi biên dịch.
Bạn có thể sử dụng enums để thực hiện một giao diện.
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; }
}
EDIT: Nhiều năm sau ....
Tôi sử dụng tính năng này ở đây
public enum AffinityStrategies implements AffinityStrategy {
Bằng cách sử dụng một giao diện, các nhà phát triển có thể xác định chiến lược của riêng họ. Sử dụng một enum
phương tiện tôi có thể định nghĩa một bộ sưu tập (gồm năm) được xây dựng trong những bộ.
Kể từ Java 1.5, Java hiện có một cú pháp rõ ràng hơn để viết các hàm của arity biến. Vì vậy, thay vì chỉ truyền một mảng, bây giờ bạn có thể làm như sau
public void foo(String... bars) {
for (String bar: bars)
System.out.println(bar);
}
các thanh được tự động chuyển thành mảng của loại được chỉ định. Không phải là một chiến thắng lớn, nhưng dù sao cũng là một chiến thắng.
Yêu thích của tôi: đổ tất cả dấu vết ngăn xếp chủ đề để tiêu chuẩn ra.
cửa sổ: CTRL- Breaktrong cửa sổ java cmd / console của bạn
unix: kill -3 PID
Break
phím.
Một vài người đã đăng bài về khởi tạo cá thể, đây là một cách sử dụng tốt cho nó:
Map map = new HashMap() {{
put("a key", "a value");
put("another key", "another value");
}};
Là một cách nhanh chóng để khởi tạo bản đồ nếu bạn chỉ cần làm một việc gì đó nhanh chóng và đơn giản.
Hoặc sử dụng nó để tạo một nguyên mẫu khung đu nhanh:
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 );
Tất nhiên nó có thể bị lạm dụng:
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");
}
});
}});
}});
}};
Proxy động (được thêm vào trong 1.3) cho phép bạn xác định loại mới trong thời gian chạy phù hợp với giao diện. Nó có ích một số lần đáng ngạc nhiên.
khởi tạo cuối cùng có thể được hoãn lại.
Nó đảm bảo rằng ngay cả với một luồng giá trị trả về logic phức tạp luôn được đặt. Thật quá dễ dàng để bỏ lỡ một trường hợp và vô tình trở về null. Nó không làm cho việc trả về null là không thể, chỉ rõ ràng là nó có chủ đích:
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;
}
Tôi nghĩ một tính năng "bị bỏ qua" khác của java là chính JVM. Nó có lẽ là VM tốt nhất hiện có. Và nó hỗ trợ rất nhiều ngôn ngữ thú vị và hữu ích (Jython, JRuby, Scala, Groovy). Tất cả những ngôn ngữ có thể dễ dàng và liền mạch hợp tác.
Nếu bạn thiết kế một ngôn ngữ mới (như trong trường hợp scala), ngay lập tức bạn có sẵn tất cả các thư viện hiện có và ngôn ngữ của bạn là "hữu ích" ngay từ đầu.
Tất cả các ngôn ngữ đó sử dụng tối ưu hóa HotSpot. VM rất tốt theo dõi và gỡ lỗi.
Bạn có thể định nghĩa một lớp con ẩn danh và gọi trực tiếp một phương thức trên nó ngay cả khi nó không thực hiện giao diện.
new Object() {
void foo(String s) {
System.out.println(s);
}
}.foo("Hello");
start()
) không thực sự được xác định trong lớp con ...
Các asList phương pháp trong java.util.Arrays
cho phép một sự kết hợp tốt đẹp của varargs, phương pháp chung chung và autoboxing:
List<Integer> ints = Arrays.asList(1,2,3);
Arrays.asList
tính năng bất thường mà bạn có thể set()
yếu tố nhưng không add()
hoặc remove()
. Vì vậy, tôi thường bọc nó trong một new ArrayList(...)
hoặc trong một Collections.unmodifiableList(...)
, tùy thuộc vào việc tôi muốn danh sách có thể sửa đổi hay không.
Sử dụng từ khóa này để truy cập các trường / phương thức chứa lớp từ một lớp bên trong. Trong ví dụ bên dưới, khá giả định, chúng tôi muốn sử dụng trường sắp xếp tăng dần của lớp container từ lớp bên trong ẩn danh. Sử dụng ContainerClass.this.sortAsceinating thay vì this.sortAsceinating thực hiện thủ thuật.
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;
}
}
MyActivity.this
.
Không thực sự là một tính năng, nhưng một mẹo thú vị mà tôi đã phát hiện gần đây trong một số trang Web:
class Example
{
public static void main(String[] args)
{
System.out.println("Hello World!");
http://Phi.Lho.free.fr
System.exit(0);
}
}
là một chương trình Java hợp lệ (mặc dù nó tạo ra một cảnh báo). Nếu bạn không thấy lý do tại sao, hãy xem câu trả lời của Gregory! ;-) Vâng, cú pháp tô sáng ở đây cũng cho một gợi ý!
Đây không phải là "tính năng ẩn" chính xác và không hữu ích lắm, nhưng có thể cực kỳ thú vị trong một số trường hợp:
Class sun.misc.Unsafe - sẽ cho phép bạn thực hiện quản lý bộ nhớ trực tiếp trong Java (thậm chí bạn có thể viết mã Java tự sửa đổi bằng Điều này nếu bạn cố gắng nhiều):
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);
}
};
}
Khi làm việc trong Swing tôi thích tính năng ẩn Ctrl- Shift- F1.
Nó kết xuất cây thành phần của cửa sổ hiện tại.
(Giả sử bạn không bị ràng buộc phím đó với thứ khác.)
Mỗi tệp lớp bắt đầu với giá trị hex 0xCAFEBABE để xác định nó là mã byte JVM hợp lệ.
( Giải thích )
Phiếu bầu của tôi thuộc về java.util.conc hiện với các bộ sưu tập đồng thời và các trình thực thi linh hoạt cho phép các nhóm luồng khác, các tác vụ theo lịch trình và các tác vụ được phối hợp. DelayQueue là sở thích cá nhân của tôi, nơi các yếu tố được cung cấp sau một độ trễ được chỉ định.
java.util.Timer và TimerTask có thể được đưa vào phần còn lại một cách an toàn.
Ngoài ra, không chính xác ẩn nhưng trong một gói khác với các lớp khác liên quan đến ngày và thời gian. java.util.concản.TimeUnit rất hữu ích khi chuyển đổi giữa các nano giây, micro giây, mili giây và giây.
Nó đọc tốt hơn rất nhiều so với someValue * 1000 hoặc someValue / 1000 thông thường.
CountDownLatch
và CyclicBarrier
- rất hữu ích!
Từ khóa khẳng định trình độ ngôn ngữ .
Không thực sự là một phần của ngôn ngữ Java, nhưng trình phân tách javap đi kèm với JDK của Sun không được biết đến hoặc sử dụng rộng rãi.
Việc bổ sung cấu trúc vòng lặp for cho mỗi vòng lặp trong 1.5. Tôi <3 nó.
// For each Object, instantiated as foo, in myCollection
for(Object foo: myCollection) {
System.out.println(foo.toString());
}
Và có thể được sử dụng trong các trường hợp lồng nhau:
for (Suit suit : suits)
for (Rank rank : ranks)
sortedDeck.add(new Card(suit, rank));
Cấu trúc for-every cũng có thể áp dụng cho các mảng, trong đó nó ẩn biến chỉ số thay vì iterator. Phương thức sau đây trả về tổng của các giá trị trong một mảng int:
// Returns the sum of the elements of a
int sum(int[] a) {
int result = 0;
for (int i : a)
result += i;
return result;
}
i
ở đây là rất khó hiểu, vì hầu hết mọi người mong đợi tôi là một chỉ mục chứ không phải là thành phần mảng.
Cá nhân tôi phát hiện ra java.lang.Void
rất muộn - cải thiện khả năng đọc mã kết hợp với thuốc generic, vdCallable<Void>