หลังจากอ่านคุณสมบัติที่ซ่อนของ C #ฉันสงสัยว่าอะไรคือคุณสมบัติที่ซ่อนอยู่ของ Java?
หลังจากอ่านคุณสมบัติที่ซ่อนของ C #ฉันสงสัยว่าอะไรคือคุณสมบัติที่ซ่อนอยู่ของ Java?
คำตอบ:
การเริ่มต้น Double Braceทำให้ฉันประหลาดใจเมื่อไม่กี่เดือนที่ผ่านมาเมื่อฉันค้นพบครั้งแรกไม่เคยได้ยินมาก่อน
ThreadLocalsโดยทั่วไปจะไม่รู้จักกันอย่างกว้างขวางว่าเป็นวิธีการจัดเก็บสถานะต่อเธรด
ตั้งแต่ JDK 1.5 Java ได้ได้ดำเนินการเป็นอย่างดีและเครื่องมือที่เห็นพ้องที่แข็งแกร่งกว่าเพียงแค่ล็อคพวกเขาอาศัยอยู่ในjava.util.concurrentและตัวอย่างที่น่าสนใจโดยเฉพาะเป็นjava.util.concurrent.atomicแพ็กเกจย่อยที่มีพื้นฐานด้ายปลอดภัยที่ใช้เปรียบเทียบ - and -swapและสามารถแมปกับเวอร์ชันดั้งเดิมที่สนับสนุนฮาร์ดแวร์ดั้งเดิมของการดำเนินการเหล่านี้
สหภาพร่วมในความแปรปรวนพารามิเตอร์ประเภท:
public class Baz<T extends Foo & Bar> {}
ตัวอย่างเช่นหากคุณต้องการใช้พารามิเตอร์ที่มีทั้งแบบเทียบเคียงและแบบสะสม:
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);
}
เมธอดที่ถูกประดิษฐ์นี้จะคืนค่าเป็นจริงหากทั้งสองคอลเลกชันที่กำหนดมีค่าเท่ากันหรือหากหนึ่งในนั้นมีองค์ประกอบที่กำหนดมิฉะนั้นจะเป็นเท็จ จุดสังเกตคือคุณสามารถเรียกใช้เมธอดทั้ง Comparable และ Collection บนอาร์กิวเมนต์ b1 และ b2
ฉันรู้สึกประหลาดใจโดย initializers อินสแตนซ์วันอื่น ๆ ฉันกำลังลบวิธีการพับโค้ดบางส่วนและสร้างการเริ่มต้นอินสแตนซ์หลายรายการ:
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");
}};
JDK 1.6_07 + มีแอปที่เรียกว่า VisualVM (bin / jvisualvm.exe) ซึ่งเป็น GUI ที่ดีอยู่ด้านบนของเครื่องมือมากมาย ดูเหมือนว่าครอบคลุมมากกว่า JConsole
Classpath wild cards ตั้งแต่ 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
สำหรับคนส่วนใหญ่ฉันสัมภาษณ์ตำแหน่งนักพัฒนาซอฟต์แวร์ 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 เป็นเพียงคำหลัก? :)
แล้วประเภทการคืนค่า covariantที่มีมาตั้งแต่ JDK 1.5 ล่ะ? มันเป็นการประชาสัมพันธ์ที่ไม่ดีเท่าที่ควรเพราะมันเป็นการเพิ่มที่ไม่ปลอดภัย แต่อย่างที่ฉันเข้าใจมันเป็นสิ่งที่จำเป็นอย่างยิ่งสำหรับยาสามัญประจำการ
โดยพื้นฐานแล้วคอมไพเลอร์อนุญาตให้คลาสย่อย จำกัด ประเภทการส่งคืนของเมธอด overridden ให้แคบลงเป็นประเภทย่อยของประเภทการส่งคืนของวิธีดั้งเดิม ดังนั้นจึงได้รับอนุญาต:
class Souper {
Collection<String> values() {
...
}
}
class ThreadSafeSortedSub extends Souper {
@Override
ConcurrentSkipListSet<String> values() {
...
}
}
คุณสามารถเรียก subclass ของvalues
วิธีการและได้รับความปลอดภัยด้ายเรียงลำดับSet
ของString
s โดยไม่ต้องโยนลงConcurrentSkipListSet
ไป
การถ่ายโอนการควบคุมในบล็อกในที่สุดก็ทิ้งข้อยกเว้นใด ๆ รหัสต่อไปนี้ไม่ทิ้ง 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
ไม่เคยเห็นใครพูดถึงอินสแตนซ์ของการใช้งานในลักษณะที่ไม่จำเป็นต้องตรวจสอบค่าว่าง
แทน:
if( null != aObject && aObject instanceof String )
{
...
}
เพียงใช้:
if( aObject instanceof String )
{
...
}
free
หรือออกdelete
ใน C / C ++ แนวคิดพื้นฐานดังกล่าว
การอนุญาตให้วิธีการและผู้สร้างใน enums ทำให้ฉันประหลาดใจ ตัวอย่างเช่น:
enum Cats {
FELIX(2), SHEEBA(3), RUFUS(7);
private int mAge;
Cats(int age) {
mAge = age;
}
public int getAge() {
return mAge;
}
}
คุณยังสามารถมี "คลาสเฉพาะค่าคงที่" ซึ่งอนุญาตให้ค่า enum เฉพาะเพื่อแทนที่เมธอด
mAge
ควรเป็นที่สิ้นสุด ไม่ค่อยมีเหตุผลสำหรับ felds ที่ไม่ใช่คนสุดท้ายใน enums
พารามิเตอร์ประเภทสำหรับวิธีการทั่วไปสามารถระบุได้อย่างชัดเจนเช่น:
Collections.<String,Integer>emptyMap()
public static <T> T foo(T t)
นี้เป็นจริงที่มีประโยชน์มากในสถานการณ์ที่คุณได้ประกาศวิธีการทั่วไปคงที่เช่น จากนั้นคุณสามารถโทรไปที่Class.<Type>foo(t);
return set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList()
เช่น นอกจากนี้ยังมีประโยชน์สำหรับการเรียกใช้เมธอดบางอย่างที่ Collections.emptyMap แบบง่าย () จะให้ข้อผิดพลาดในการคอมไพล์
คุณสามารถใช้ enums เพื่อนำอินเตอร์เฟสมาใช้
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 {
โดยใช้อินเทอร์เฟซผู้พัฒนาสามารถกำหนดกลยุทธ์ของตนเอง การใช้enum
วิธีการที่ฉันสามารถกำหนดคอลเลกชัน (ห้า) ในตัว
ในฐานะของ Java 1.5 ตอนนี้ Java มีไวยากรณ์ที่สะอาดกว่าสำหรับการเขียนฟังก์ชันของตัวแปร arity ดังนั้นแทนที่จะผ่านอาร์เรย์ตอนนี้คุณสามารถทำสิ่งต่อไปนี้
public void foo(String... bars) {
for (String bar: bars)
System.out.println(bar);
}
บาร์จะถูกแปลงเป็นประเภทที่ระบุโดยอัตโนมัติ ไม่ใช่การชนะครั้งใหญ่ แต่เป็นการชนะอย่างไรก็ตาม
สิ่งที่ฉันชอบ: ทิ้งร่องรอยสแต็กสแต็กทั้งหมดให้เป็นมาตรฐาน
windows: CTRL- Breakในหน้าต่างjava cmd / console ของคุณ
ยูนิกซ์: kill -3 PID
Break
กุญแจ
มีคนสองคนโพสต์เกี่ยวกับอินสแตนซ์ initializers ต่อไปนี้เป็นประโยชน์อย่างมากสำหรับมัน:
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");
}
});
}});
}});
}};
พร็อกซีไดนามิก (เพิ่มใน 1.3) ช่วยให้คุณสามารถกำหนดชนิดใหม่ที่รันไทม์ที่สอดคล้องกับอินเตอร์เฟซ มันมีประโยชน์หลายครั้ง
สามารถเลื่อนการเริ่มต้นขั้นสุดท้ายได้
ตรวจสอบให้แน่ใจว่าแม้จะมีการไหลเวียนที่ซับซ้อนของค่าส่งคืนแบบลอจิกก็จะถูกตั้งค่าเสมอ มันง่ายเกินไปที่จะพลาดเคสและคืนค่าว่างเปล่าโดยไม่ได้ตั้งใจ มันไม่ได้ทำให้การคืนค่าเป็นโมฆะเป็นไปไม่ได้ แต่เห็นได้ชัดว่ามันมีวัตถุประสงค์:
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;
}
ฉันคิดว่าฟีเจอร์อื่นที่“ มองข้าม” ของจาวาคือ JVM มันน่าจะเป็น VM ที่ดีที่สุด และรองรับภาษาที่น่าสนใจและมีประโยชน์มากมาย (Jython, JRuby, Scala, Groovy) ทุกภาษาเหล่านั้นสามารถร่วมมือกันได้อย่างง่ายดายและราบรื่น
หากคุณออกแบบภาษาใหม่ (เช่นใน scala-case) คุณจะต้องมีไลบรารีที่มีอยู่ทั้งหมดทันทีดังนั้นภาษาของคุณจึงมี "ประโยชน์" ตั้งแต่เริ่มต้น
ทุกภาษาเหล่านั้นใช้ประโยชน์จากการปรับให้เหมาะสมที่สุดของ HotSpot VM นั้นตรวจสอบและ debuggable ได้เป็นอย่างดี
คุณสามารถกำหนดคลาสย่อยที่ไม่ระบุชื่อและเรียกเมธอดได้โดยตรงแม้ว่าจะไม่มีส่วนต่อประสาน
new Object() {
void foo(String s) {
System.out.println(s);
}
}.foo("Hello");
start()
) ไม่ได้กำหนดไว้ในคลาสย่อยจริง ๆ ...
asListวิธีการในการjava.util.Arrays
ช่วยให้การรวมกันที่ดีของ varargs วิธีการทั่วไปและ autoboxing:
List<Integer> ints = Arrays.asList(1,2,3);
Arrays.asList
มีลักษณะที่ผิดปกติที่คุณสามารถset()
องค์ประกอบ แต่ไม่หรือadd()
remove()
ดังนั้นฉันมักจะห่อในnew ArrayList(...)
หรือCollections.unmodifiableList(...)
ขึ้นอยู่กับว่าฉันต้องการแก้ไขรายการหรือไม่
การใช้คำสำคัญนี้เพื่อเข้าถึงฟิลด์ / วิธีการบรรจุคลาสจากคลาสภายใน ในตัวอย่างด้านล่างนี้เราต้องการใช้เขตข้อมูล 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;
}
}
MyActivity.this
ในการสั่งซื้อที่จะได้รับบริบทจากการพูดฟังปุ่มเพียงปุ่มเดียวด้วย
ไม่ใช่คุณสมบัติจริงๆ แต่เป็นเคล็ดลับที่สนุกที่ฉันค้นพบเมื่อเร็ว ๆ นี้ในบางเว็บเพจ:
class Example
{
public static void main(String[] args)
{
System.out.println("Hello World!");
http://Phi.Lho.free.fr
System.exit(0);
}
}
เป็นโปรแกรม Java ที่ถูกต้อง (แม้ว่าจะสร้างคำเตือน) หากคุณไม่เห็นสาเหตุให้ดูคำตอบของ Gregory! ;-) การเน้นไวยากรณ์ที่นี่ก็ให้คำแนะนำด้วย!
นี่ไม่ใช่ "คุณสมบัติที่ซ่อนอยู่" และไม่มีประโยชน์มาก แต่อาจเป็นที่น่าสนใจอย่างมากในบางกรณี:
คลาส 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);
}
};
}
เมื่อทำงานในสวิงผมชอบที่ซ่อนอยู่Ctrl- Shift- F1คุณลักษณะ
มันทิ้งต้นไม้องค์ประกอบของหน้าต่างปัจจุบัน
(สมมติว่าคุณไม่ได้กดแป้นพิมพ์นั้นกับสิ่งอื่น)
ไฟล์คลาสทุกไฟล์เริ่มต้นด้วยค่า hex 0xCAFEBABEเพื่อระบุว่าเป็น JVM bytecode ที่ถูกต้อง
( คำอธิบาย )
การลงคะแนนของฉันไปที่java.util.concurrentพร้อมด้วยคอลเลกชันที่เกิดขึ้นพร้อมกันและตัวเรียกใช้งานที่ยืดหยุ่นช่วยให้กลุ่มเธรดพูลงานกำหนดเวลาและงานประสานงานอื่น ๆ The DelayQueue เป็นรายการโปรดส่วนตัวของฉันซึ่งองค์ประกอบต่างๆจะมีให้หลังจากการล่าช้าที่ระบุ
java.util.Timer และ TimerTask อาจถูกพักอย่างปลอดภัย
นอกจากนี้ยังไม่ถูกซ่อนอยู่อย่างแน่นอน แต่อยู่ในแพ็คเกจอื่นจากคลาสอื่น ๆ ที่เกี่ยวข้องกับวันที่และเวลา java.util.concurrent.TimeUnit มีประโยชน์เมื่อแปลงระหว่างนาโนวินาที, ไมโครวินาที, มิลลิวินาทีและวินาที
มันอ่านดีกว่าค่าปกติบางอย่าง * 1000 หรือ someValue / 1000
CountDownLatch
และCyclicBarrier
- เพื่อประโยชน์!
คำหลักยืนยันระดับภาษา
ไม่ใช่ส่วนหนึ่งของภาษา Java แต่ javap disassembler ซึ่งมาพร้อมกับ JDK ของ Sun นั้นไม่เป็นที่รู้จักหรือใช้กันอย่างแพร่หลาย
การเพิ่มโครงสร้างวนรอบสำหรับแต่ละรายการใน 1.5 ฉัน <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));
การสร้างสำหรับแต่ละยังใช้กับอาร์เรย์ซึ่งซ่อนตัวแปรดัชนีมากกว่าตัววนซ้ำ วิธีการต่อไปนี้จะคืนค่าผลรวมของค่าในอาร์เรย์ 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
ที่นี่มีความสับสนอย่างมากเนื่องจากคนส่วนใหญ่คาดหวังว่าฉันจะเป็นดัชนีและไม่ใช่องค์ประกอบอาร์เรย์
ฉันค้นพบโดยส่วนตัวjava.lang.Void
ช้ามาก - ปรับปรุงการอ่านโค้ดร่วมกับยาชื่อสามัญเช่นCallable<Void>