इसलिए, हमारे पास एक ऐसी स्थिति है जब हमें MyClass.classसिंटैक्स के स्पष्ट उपयोग के बिना सांख्यिकीय रूप से वर्ग वस्तु या एक वर्ग पूर्ण / सरल नाम प्राप्त करने की आवश्यकता होती है ।
यह वास्तव में कुछ मामलों में आसान हो सकता है, उदाहरण के लिए लकड़हारा उदाहरण kotlin ऊपरी-स्तरीय फ़ंक्शन (इस मामले में कोटलिन एक स्थिर जावा वर्ग बनाता है जो कोटलिन कोड से सुलभ नहीं है)।
इस जानकारी को प्राप्त करने के लिए हमारे पास कुछ भिन्न प्रकार हैं:
new Object(){}.getClass().getEnclosingClass();
टॉम हॉकिन
ने उल्लेख किया है - डीललाइन
getClassContext()[0].getName();से SecurityManager
द्वारा नोट क्रिस्टोफ़र
new Throwable().getStackTrace()[0].getClassName();
गिनती के
द्वारा
Thread.currentThread().getStackTrace()[1].getClassName();
से Keksi
और अंत में रेन
MethodHandles.lookup().lookupClass();
से कमाल
मैंने तैयार किया है JMH सभी प्रकारों और परिणामों के लिए बेंचमार्क हैं:
# Run complete. Total time: 00:04:18
Benchmark Mode Cnt Score Error Units
StaticClassLookup.MethodHandles_lookup_lookupClass avgt 30 3.630 ± 0.024 ns/op
StaticClassLookup.AnonymousObject_getClass_enclosingClass avgt 30 282.486 ± 1.980 ns/op
StaticClassLookup.SecurityManager_classContext_1 avgt 30 680.385 ± 21.665 ns/op
StaticClassLookup.Thread_currentThread_stackTrace_1_className avgt 30 11179.460 ± 286.293 ns/op
StaticClassLookup.Throwable_stackTrace_0_className avgt 30 10221.209 ± 176.847 ns/op
निष्कर्ष
- उपयोग करने के लिए सबसे अच्छा संस्करण , बल्कि साफ और राक्षसी रूप से तेज।
केवल जावा 7 और एंड्रॉइड एपीआई 26 के बाद से उपलब्ध है!
MethodHandles.lookup().lookupClass();
- यदि आपको एंड्रॉइड या जावा 6 के लिए इस कार्यक्षमता की आवश्यकता है, तो आप दूसरे सर्वश्रेष्ठ संस्करण का उपयोग कर सकते हैं। यह बहुत तेज़ है, लेकिन उपयोग के प्रत्येक स्थान में एक अनाम वर्ग बनाता है :(
new Object(){}.getClass().getEnclosingClass();
यदि आपको कई स्थानों पर इसकी आवश्यकता है और नहीं चाहते हैं कि आपका बाइटकोड गुमनाम वर्गों के टन के कारण फूल जाए - SecurityManagerआपका मित्र है (तीसरा सबसे अच्छा विकल्प)।
लेकिन आप सिर्फ कॉल नहीं कर सकते getClassContext()- यह SecurityManagerकक्षा में संरक्षित है । आपको कुछ सहायक वर्ग की आवश्यकता होगी:
// Helper class
public final class CallerClassGetter extends SecurityManager
{
private static final CallerClassGetter INSTANCE = new CallerClassGetter();
private CallerClassGetter() {}
public static Class<?> getCallerClass() {
return INSTANCE.getClassContext()[1];
}
}
// Usage example:
class FooBar
{
static final Logger LOGGER = LoggerFactory.getLogger(CallerClassGetter.getCallerClass())
}
- संभवतः आपको
getStackTrace()अपवाद या के आधार पर अंतिम दो वेरिएंट का उपयोग करने की आवश्यकता नहीं है Thread.currentThread()। बहुत अकुशल और केवल वर्ग के नाम को एक के रूप में वापस कर सकता है String, Class<*>उदाहरण के लिए नहीं ।
पुनश्च
यदि आप स्थैतिक कोटलीन बर्तनों के लिए एक लकड़हारा उदाहरण बनाना चाहते हैं (जैसे :), आप इस सहायक का उपयोग कर सकते हैं:
import org.slf4j.Logger
import org.slf4j.LoggerFactory
// Should be inlined to get an actual class instead of the one where this helper declared
// Will work only since Java 7 and Android API 26!
@Suppress("NOTHING_TO_INLINE")
inline fun loggerFactoryStatic(): Logger
= LoggerFactory.getLogger(MethodHandles.lookup().lookupClass())
उपयोग उदाहरण:
private val LOGGER = loggerFactoryStatic()
/**
* Returns a pseudo-random, uniformly distributed value between the
* given least value (inclusive) and bound (exclusive).
*
* @param min the least value returned
* @param max the upper bound (exclusive)
*
* @return the next value
* @throws IllegalArgumentException if least greater than or equal to bound
* @see java.util.concurrent.ThreadLocalRandom.nextDouble(double, double)
*/
fun Random.nextDouble(min: Double = .0, max: Double = 1.0): Double {
if (min >= max) {
if (min == max) return max
LOGGER.warn("nextDouble: min $min > max $max")
return min
}
return nextDouble() * (max - min) + min
}
try{ throw new RuntimeEsception();} catch(RuntimeEcxeption e){return e.getstackTrace()[1].getClassName();}