Java, 400
Java เป็นความสุข (?) กับหลายException
และError
s มีหลายException
s ที่เฉพาะกับการดำเนินงานของชั้นเดียว เป็นตัวอย่างของหนึ่งในกรณีที่มากที่สุดที่มีมากกว่า 10 Exception
s (ทั้งหมดเป็น subclass ของIllegalFormatException
) ที่ทุ่มเทให้กับFormatter
ชั้นเรียนเพียงอย่างเดียวและฉันได้ใช้เวลาในการทำให้โค้ดโยน (เกือบ) ทั้งหมด
คำตอบปัจจุบันของฉันมี 40 Exception
s / s ที่แตกต่างกันError
และพวกเขาได้รับการดำเนินการแบบสุ่มขึ้นอยู่กับ modulo ของSystem.nanoTime()
ด้วยจำนวนเต็มบางส่วน
วิธีนี้สามารถใช้เพื่อวัดเวลาที่ผ่านไปและไม่เกี่ยวข้องกับความคิดอื่น ๆ ของระบบหรือเวลานาฬิกาแขวน ค่าที่ส่งคืนแสดงถึง nanoseconds ตั้งแต่บางเวลาคงที่ แต่กำเนิดโดยพลการ (อาจเป็นในอนาคตดังนั้นค่าอาจเป็นค่าลบ) ต้นกำเนิดเดียวกันถูกใช้โดยการเรียกใช้เมธอดนี้ทั้งหมดในอินสแตนซ์ของเครื่องเสมือน Java; อินสแตนซ์ของเครื่องเสมือนอื่น ๆ มีแนวโน้มที่จะใช้ต้นกำเนิดที่แตกต่างกัน
ควรอนุญาตวิธีการข้างต้นเนื่องจากตรงกับกรณี"3. ไม่สามารถใช้จำนวนของสำบัดสำนวนหรือรอบ cpu ยกเว้นว่าพวกเขาจะถูกนับค่อนข้างเริ่มต้นของเธรดโปรแกรมหลัก"ไม่สามารถใช้จำนวนสำบัดสำนวนหรือรอบซีพียูจนกว่าพวกเขาจะถูกนับค่อนข้างที่จะเริ่มด้ายโปรแกรมหลัก"
การรวบรวมการเรียนการสอน
แนะนำให้ใช้JRE / JDK หรือ OpenJDK ของ Oracleสำหรับการเรียกใช้รหัส มิฉะนั้นข้อยกเว้นบางอย่างอาจไม่ถูกโยนเนื่องจากบางคนอาศัยรายละเอียดภายในของการดำเนินการอ้างอิงและฉันไม่มีข้อผิดพลาดที่น่าเชื่อถือ
โค้ดข้างล่างนี้รวบรวมประสบความสำเร็จกับและผลิตทั้งหมดในข้อยกเว้นjavac 1.7.0_11
java 1.7.0_51
ในการเรียกใช้รหัสนี้คุณต้องคัดลอกและวางรหัสด้านล่างไปยังตัวแก้ไขการรับรู้ Unicode (เช่น Notepad ++) บันทึกใน UTF-16 (Big-Endian หรือ Little-Endian ไม่สำคัญตราบใดที่เขียน BOM) .
เปลี่ยนไดเร็กตอรี่การทำงาน ( cd
) เป็นตำแหน่งที่จะบันทึกซอร์สโค้ด ( ซึ่งเป็นสิ่งสำคัญ )
รวบรวมรหัสด้วยคำสั่งต่อไปนี้:
javac G19115.java -encoding "UTF-16"
และเรียกใช้รหัส:
java G19115
ไม่มีอะไรเป็นอันตรายในรหัสของฉันเนื่องจากฉันต้องการทดสอบเรียกใช้บนคอมพิวเตอร์ของฉัน รหัส "อันตราย" ที่สุดคือการลบToBeRemoved.class
ไฟล์ในโฟลเดอร์ปัจจุบัน นอกจากนั้นส่วนที่เหลือไม่ได้แตะระบบไฟล์หรือเครือข่าย
import java.util.*;
import java.util.regex.*;
import java.lang.reflect.*;
import java.text.*;
import java.io.*;
import java.nio.*;
import java.nio.charset.*;
import java.security.*;
class G19115 {
// The documentation says System.nanoTime() does not return actual time, but a relative
// time to some fixed origin.
private static int n = (int) ((System.nanoTime() % 40) + 40) % 40;
@SuppressWarnings("deprecation")
public static void main(String args[]) {
/**
* If the code is stated to be a bug, then it is only guaranteed to throw Exception on
* Oracle's JVM (or OpenJDK). Even if you are running Oracle's JVM, there is no
* guarantee it will throw Exception in all future releases future either (since bugs
* might be fixed, classes might be reimplemented, and an asteroid might hit the earth,
* in order from the least likely to most likely).
*/
System.out.println(n);
switch (n) {
case 0:
// Bug JDK-7080302
// https://bugs.openjdk.java.net/browse/JDK-7080302
// PatternSyntaxException
System.out.println(Pattern.compile("a(\u0041\u0301\u0328)", Pattern.CANON_EQ));
System.out.println(Pattern.compile("öö", Pattern.CANON_EQ));
// Leave this boring pattern here just in case
System.out.println(Pattern.compile("??+*"));
break;
case 1:
// Bug JDK-6984178
// https://bugs.openjdk.java.net/browse/JDK-6984178
// StringIndexOutOfBoundsException
System.out.println(new String(new char[42]).matches("(?:(?=(\\2|^))(?=(\\2\\3|^.))(?=(\\1))\\2)+."));
// Leave this boring code here just in case
System.out.println("".charAt(1));
break;
case 2:
// IllegalArgumentException
// Bug JDK-8035975
// https://bugs.openjdk.java.net/browse/JDK-8035975
// Should throw IllegalArgumentException... by documentation, but does not!
System.out.println(Pattern.compile("pattern", 0xFFFFFFFF));
// One that actually throws IllegalArgumentException
System.out.println(new SimpleDateFormat("Nothing to see here"));
break;
case 3:
// Bug JDK-6337993 (and many others...)
// https://bugs.openjdk.java.net/browse/JDK-6337993
// StackOverflowError
StringBuffer buf = new StringBuffer(2000);
for (int i = 0; i < 1000; i++) {
buf.append("xy");
}
System.out.println(buf.toString().matches("(x|y)*"));
// Leave this boring code here just in case
main(args);
break;
case 4:
// NumberFormatException
String in4 = "123\r\n";
Matcher m4 = Pattern.compile("^\\d+$").matcher(in4);
if (m4.find()) {
System.out.println(Integer.parseInt(in4));
} else {
System.out.println("Bad input");
}
// NotABug(TM) StatusByDesign(TM)
// $ by default can match just before final trailing newline character in Java
// This is why matches() should be used, or we can call m.group() to get the string matched
break;
case 5:
// IllegalStateException
String in5 = "123 345 678 901";
Matcher m5 = Pattern.compile("\\d+").matcher(in5);
System.out.println(m5.group(0));
// The Matcher doesn't start matching the string by itself...
break;
case 6:
// ArrayIndexOutOfBoundsException
// Who is the culprit?
String[] in6 = {
"Nice weather today. Perfect for a stroll along the beach.",
" Mmmy keeyboaardd iisss bbrokkkkeeen ..",
"",
"\t\t\t \n\n"};
for (String s: in6) {
System.out.println("First token: " + s.split("\\s+")[0]);
}
// Culprit is "\t\t\t \n\n"
// String.split() returns array length 1 with empty string if input is empty string
// array length 0 if input is non-empty and all characters match the regex
break;
case 7:
// ConcurrentModificationException
List<Integer> l7 = testRandom(42);
Integer prev = null;
// Remove duplicate numbers from the list
for (Integer i7: l7) {
if (prev == null) {
prev = i7;
} else {
if (i7.equals(prev)) {
l7.remove(i7);
}
}
}
System.out.println(l7);
// This is one of the typical mistakes that Java newbies run into
break;
case 8:
// ArithmeticException
// Integer division by 0 seems to be the only way to trigger this exception?
System.out.println(0/0);
break;
case 9:
// ExceptionInInitializerError
// Thrown when there is an Exception raised during initialization of the class
// What Exception will be thrown here?
Static s9 = null;
System.out.println(s9.k);
// A bit less interesting
Static ss9 = new Static();
// ----
// A class is only initialized when any of its method/field is
// used for the first time (directly or indirectly)
// Below code won't throw Exception, since we never access its fields or methods
// Static s;
// OR
// Static s = null;
break;
case 10:
// BufferOverflowException
short s10 = 20000;
ShortBuffer b10 = ShortBuffer.allocate(0).put(s10);
// Boring stuff...
break;
case 11:
// BufferUnderflowException
ShortBuffer.allocate(0).get();
// Another boring stuff...
break;
case 12:
// InvalidMarkException
ShortBuffer.allocate(0).reset();
// Boring stuff again...
// reset() cannot be called if mark() is not called before
break;
case 13:
// IndexOutOfBoundsException
System.out.println("I lost $m dollars".replaceAll("[$]m\\b", "$2"));
// $ needs to be escaped in replacement string, since it is special
break;
case 14:
// ClassCastException
Class c14 = Character.class;
for (Field f: c14.getFields()) {
System.out.println(f);
try {
int o = (int) f.get(c14);
// If the result is of primitive type, it is boxed before returning
// Check implementation of sun.reflect.UnsafeStaticIntegerFieldAccessorImpl
System.out.println(o);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
break;
case 15:
// NoSuchElementException
List<Integer> l15 = new ArrayList<Integer>();
Iterator i = l15.iterator();
System.out.println(i.next());
// Another boring one...
break;
case 16:
// ArrayStoreException
Object x[] = new String[3];
x[0] = new Integer(0);
// Straight from the documentation
// I don't even know that this exists...
break;
case 17:
// IllegalThreadStateException
Thread t17 = new Thread();
t17.start();
t17.setDaemon(true);
// setDaemon can only be called when the thread has not started or has died
break;
case 18:
// EmptyStackException
Stack<Integer> s18 = new Stack<Integer>();
s18.addAll(testRandom(43));
while (s18.pop() != null);
// Originally ThreadDeath, which works when running from Dr. Java but not when
// running on cmd line. Seems that Dr. Java provides its own version of
// Thread.UncaughtExceptionHandler that prints out ThreadDeath.
// Please make do with this boring Exception
break;
case 19:
// NegativeArraySizeException
Array.newInstance(Integer.TYPE, -1);
// Do they have to create such a specific Exception?
break;
case 20:
// OutOfMemoryError
Array.newInstance(Integer.TYPE, 1000, 1000, 1000, 1000);
break;
case 21:
// UnsupportedCharsetException
// UCS-2 is superseded by UTF-16
Charset cs21 = Charset.forName("UCS-2");
CharsetEncoder ce21 = cs21.newEncoder();
// Just in case...
cs21 = Charset.forName("o_O");
// "o_O" is a (syntactically) valid charset name, so it throws UnsupportedCharsetException
break;
case 22:
// IllegalCharsetNameException
boolean isSupported;
isSupported = Charset.isSupported("o_O");
isSupported = Charset.isSupported("+_+");
Charset cs22 = Charset.forName("MerryChristmas!Hohoho!");
// This is getting stupid...
break;
case 23:
// NoClassDefFoundError
File f = new File("ToBeRemoved.class");
f.delete();
ToBeRemoved o23 = new ToBeRemoved();
// This shows that class is loaded on demand
break;
case 24:
// InputMismatchException
Scanner sc = new Scanner("2987654321");
sc.nextInt();
// Out of range
break;
case 25:
// Formatter class has many RuntimeException defined
// DuplicateFormatFlagsException
System.out.printf("%0000000000000000000000000000000000000000000000000005%d\n", 42);
break;
case 26:
// FormatFlagsConversionMismatchException
System.out.printf("%,d\n", Integer.MAX_VALUE);
System.out.printf("%,x\n", Integer.MAX_VALUE);
// Thousand separator is only applicable to base 10
System.out.printf("%(5.4f\n", Math.PI);
System.out.printf("%(5.4f\n", -Math.PI);
System.out.printf("%(5.4a\n", -Math.PI);
// '(' flag is used to surround negative value with "( )" instead of prefixing with '-'
// '(' can't be used with conversion 'a'
break;
case 27:
// IllegalFormatCodePointException
System.out.printf("%c", Character.MAX_CODE_POINT + 1);
// Larger than current Unicode maximum code point (0x10FFFF)
break;
case 28:
// IllegalFormatConversionException
String i28 = "0";
System.out.printf("%d", i28);
// A boring example
break;
case 29:
// IllegalFormatFlagsException
System.out.printf("% d\n", Integer.MAX_VALUE);
System.out.printf("% d\n", Integer.MIN_VALUE);
System.out.printf("%+d\n", Integer.MAX_VALUE);
System.out.printf("%+d\n", Integer.MIN_VALUE);
System.out.printf("% +d\n", Integer.MIN_VALUE);
// Use either ' ' or '+ ' flag, not both, since they are mutually exclusive
break;
case 30:
// IllegalFormatPrecisionException
System.out.printf("%5.4f\n", Math.PI);
System.out.printf("%5.4a\n", Math.PI);
System.out.printf("%5.4x\n", Math.PI);
// Precision does not apply to 'x', which is integer hexadecimal conversion
// To print a floating point number in hexadecimal, use conversion 'a'
break;
case 31:
// IllegalFormatWidthException
System.out.printf("%3n");
// For conversion n, width is not supported
break;
case 32:
// MissingFormatArgumentException
System.out.printf("%s\n%<s", "Pointing to previous argument\n");
System.out.printf("%<s", "Pointing to previous argument");
// No previous argument
break;
case 33:
// MissingFormatWidthException
System.out.printf("%5d %<d\n", 42); // Pad left
System.out.printf("%-5d %<d\n", 42); // Pad right
System.out.printf("%-d\n", 42);
// Missing width
break;
case 34:
// UnknownFormatConversionException
System.out.printf("%q", "Shouldn't work");
// No format conversion %q
// UnknownFormatFlagsException cannot be thrown by Formatter class in
// Oracle's implementation, since the flags have been checked in the regex
// used to recognize the format string
break;
case 35:
// IllformedLocaleException
System.out.printf(new Locale("ja"), "%tA %<tB %<tD %<tT %<tZ %<tY\n", new Date());
System.out.printf(new Locale.Builder().setLanguage("ja").setScript("JA").setRegion("JA").build(), "%tA %<tB %<tD %<tT %<tZ %<tf\n", new Date());
// Thrown by Locale.Builder.setScript()
break;
case 36:
// NullPointerException
Pattern p36 = Pattern.compile("a(b)?c");
Matcher m36 = p36.matcher("ac");
if (m36.find()) {
for (int i36 = 0; i36 <= m36.groupCount(); i36++) {
// Use Matcher#end(num) - Matcher#start(num) for length instead
System.out.printf("%3d [%d]: %s\n", i36, m36.group(i36).length(), m36.group(i36));
}
}
break;
case 37:
// AccessControlException
System.setSecurityManager(new SecurityManager());
System.setSecurityManager(new SecurityManager());
break;
case 38:
// SecurityException
// Implementation-dependent
Class ϲlass = Class.class;
Constructor[] constructors = ϲlass.getDeclaredConstructors();
for (Constructor constructor: constructors) {
constructor.setAccessible(true);
try {
Class Сlass = (Class) constructor.newInstance();
} catch (Throwable e) {
System.out.println(e.getMessage());
}
// The code should reach here without any Exception... right?
}
// It is obvious once you run the code
// There are very few ways to get SecurityException (and not one of its subclasses)
// This is one of the ways
break;
case 39:
// UnknownFormatFlagsException
// Implementation-dependent
try {
System.out.printf("%=d", "20");
} catch (Exception e) {
// Just to show the original Exception
System.out.println(e.getClass());
}
Class classFormatter = Formatter.class;
Field[] fs39 = classFormatter.getDeclaredFields();
boolean patternFound = false;
for (Field f39: fs39) {
if (Pattern.class.isAssignableFrom(f39.getType())) {
f39.setAccessible(true);
// Add = to the list of flags
try {
f39.set(classFormatter, Pattern.compile("%(\\d+\\$)?([-#+ 0,(\\<=]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])"));
} catch (IllegalAccessException e) {
System.out.println(e.getMessage());
}
patternFound = true;
}
}
if (patternFound) {
System.out.printf("%=d", "20");
}
// As discussed before UnknownFormatFlagsException cannot be thrown by Oracle's
// current implementation. The reflection code above add = to the list of flags
// to be parsed to enable the path to the UnknownFormatFlagsException.
break;
}
}
/*
* This method is used to check whether all numbers under d are generated when we call
* new Object().hashCode() % d.
*
* However, hashCode() is later replaced by System.nanoTime(), since it got stuck at
* some values when the JVM is stopped and restarted every time (running on command line).
*/
private static List<Integer> testRandom(int d) {
List<Integer> k = new ArrayList<Integer>();
for (int i = 0; i < 250; i++) {
k.add(new Object().hashCode() % d);
}
Collections.sort(k);
System.out.println(k);
return k;
}
}
class ToBeRemoved {};
class Static {
static public int k = 0;
static {
System.out.println(0/0);
}
}
รายการข้อยกเว้นและข้อผิดพลาด
ตามลำดับที่ประกาศไว้ในคำสั่ง switch-case มีทั้งหมด 37 Exception
วินาทีและ 3 Error
วินาที
- PatternSyntaxException (ผ่านจุดบกพร่อง
Pattern
ด้วยกรณีที่น่าเบื่อเป็นการสำรองข้อมูล)
- StringIndexOutOfBoundsException (ผ่านจุดบกพร่องใน
Pattern
มีกรณีที่น่าเบื่อเป็นการสำรองข้อมูล)
- IllegalArgumentException (ช่วยฉันหาจุดบกพร่อง
Pattern
ด้วยเคสที่น่าเบื่อเป็นการสำรองข้อมูล)
- StackOverflowError (ผ่านการใช้งานแบบเรียกซ้ำ
Pattern
โดยมีกรณีที่น่าเบื่อเป็นการสำรองข้อมูล)
- NumberFormatException (แสดงให้เห็นว่า
$
ในPattern
สามารถจับคู่ก่อนที่จะสิ้นสุดบรรทัดสุดท้าย)
- IllegalStateException (ผ่านการเข้าถึงกลุ่มที่จับคู่ด้วย
Matcher
โดยไม่ต้องทำการจับคู่)
- ArrayIndexOutOfBoundsException (แสดงพฤติกรรมที่สับสนของ
split(String regex)
)
- ConcurrentModificationException (ผ่านการแก้ไขคอลเล็กชันระหว่างลูปสำหรับแต่ละวง)
- ArithmeticException (ผ่านการหารจำนวนเต็มด้วย 0)
- ExceptionInInialializerError (ผ่านสาเหตุ
Exception
ในระหว่างการเริ่มต้นของคลาส)
- BufferOverflowException (-
java.nio.*
เฉพาะException
)
- BufferUnderflowException (-
java.nio.*
เฉพาะException
)
- InvalidMarkException (-
java.nio.*
เฉพาะException
)
- IndexOutOfBoundsException (ผ่านการอ้างอิงถึงกลุ่มการดักจับที่ไม่มีอยู่เพื่อทดแทน)
- ClassCastException
- NoSuchElementException
- ArrayStoreException
- IllegalThreadStateException
- EmptyStackException (-
java.util.Stack
เฉพาะException
)
- NegativeArraySizeException
- OutOfMemoryError (ผ่านการจัดสรรอาร์เรย์ขนาดใหญ่ที่น่าเบื่อ)
- UnsupportedCharsetException
- IllegalCharsetNameException (แสดงเมื่อ
Charset.isSupported(String name)
ส่งคืนเท็จหรือพ่นException
)
- NoClassDefFoundError (แสดงว่าคลาสถูกโหลดในการเข้าถึงเมธอด / ตัวสร้างหรือฟิลด์แรก)
- InputMismatchException (-
java.util.Scanner
เฉพาะException
)
- DuplicateFormatFlagsException (จากที่นี่ถึง 35 เป็น
java.util.Formatter
-specific Exception
s)
- FormatFlagsConversionMismatchException (พร้อมตัวอย่างที่น่าสนใจของไวยากรณ์รูปแบบ)
- IllegalFormatCodePointException
- IllegalFormatConversionException
- IllegalFormatFlagsException
- IllegalFormatPrecisionException
- IllegalFormatWidthException
- MissingFormatArgumentException (พร้อมตัวอย่างรูปแบบไวยากรณ์ที่น่าสนใจ)
- MissingFormatWidthException
- UnknownFormatConversionException
- IllformedLocaleException
- NullPointerException
- AccessControlException (แสดงว่าค่าเริ่มต้น
SecurityManager
สามารถใช้งานได้)
- SecurityException (ผ่านการเรียกใช้คอนสตรัคเตอร์ของ
Class
คลาส)
- UnknownFormatFlagsException (แสดงว่า
Exception
ไม่สามารถโยนได้ในการติดตั้งของ Oracle, ไม่มีการสำรองข้อมูล)