जावा में अनाम कक्षाओं का उपयोग क्या है? क्या हम कह सकते हैं कि अनाम वर्ग का उपयोग जावा के लाभों में से एक है?
जावा में अनाम कक्षाओं का उपयोग क्या है? क्या हम कह सकते हैं कि अनाम वर्ग का उपयोग जावा के लाभों में से एक है?
जवाबों:
एक "अनाम वर्ग" से, मुझे लगता है कि इसका मतलब है अनाम आंतरिक वर्ग ।
एक अनाम आंतरिक वर्ग उपयोगी तब आ सकता है जब किसी वस्तु का उदाहरण "एक्स्ट्रा" के साथ हो, जैसे कि ओवरराइड करने के तरीके, वास्तव में एक वर्ग को उपवर्ग के बिना।
मैं इवेंट श्रोता को संलग्न करने के लिए शॉर्टकट के रूप में इसका उपयोग करता हूं:
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// do something
}
});
इस विधि का उपयोग करने से कोडिंग थोड़ी तेज हो जाती है, क्योंकि मुझे एक अतिरिक्त वर्ग बनाने की आवश्यकता नहीं है ActionListener
- मैं वास्तव में एक अलग वर्ग बनाने के बिना एक अनाम आंतरिक वर्ग को त्वरित कर सकता हूं।
मैं केवल "त्वरित और गंदे" कार्यों के लिए इस तकनीक का उपयोग करता हूं, जहां पूरी कक्षा को अनावश्यक लगता है। कई अनाम आंतरिक वर्ग जो वास्तव में एक ही काम करते हैं, को वास्तविक कक्षा में बदल दिया जाना चाहिए, यह एक आंतरिक वर्ग या एक अलग वर्ग होना चाहिए।
overloading methods
और नहीं overriding methods
?
अनाम आंतरिक कक्षाएं प्रभावी रूप से बंद हो जाती हैं, इसलिए उनका उपयोग लंबोदर अभिव्यक्तियों या "प्रतिनिधियों" का अनुकरण करने के लिए किया जा सकता है। उदाहरण के लिए, इस इंटरफ़ेस को लें:
public interface F<A, B> {
B f(A a);
}
जावा में प्रथम श्रेणी का कार्य बनाने के लिए आप इसे गुमनाम रूप से उपयोग कर सकते हैं । मान लें कि आपके पास निम्न विधि है जो दी गई सूची में आई की तुलना में पहले नंबर को बड़ा करती है, या यदि कोई संख्या बड़ी नहीं है:
public static int larger(final List<Integer> ns, final int i) {
for (Integer n : ns)
if (n > i)
return n;
return i;
}
और फिर आपके पास एक और तरीका है जो दिए गए सूची में पहले नंबर को छोटा करता है, या अगर कोई संख्या छोटी नहीं है, तो:
public static int smaller(final List<Integer> ns, final int i) {
for (Integer n : ns)
if (n < i)
return n;
return i;
}
ये विधियां लगभग समान हैं। प्रथम श्रेणी के फ़ंक्शन प्रकार F का उपयोग करते हुए, हम इन्हें निम्न तरीके से एक विधि में फिर से लिख सकते हैं:
public static <T> T firstMatch(final List<T> ts, final F<T, Boolean> f, T z) {
for (T t : ts)
if (f.f(t))
return t;
return z;
}
आप FirstMatch विधि का उपयोग करने के लिए एक अनाम वर्ग का उपयोग कर सकते हैं:
F<Integer, Boolean> greaterThanTen = new F<Integer, Boolean> {
Boolean f(final Integer n) {
return n > 10;
}
};
int moreThanMyFingersCanCount = firstMatch(xs, greaterThanTen, x);
यह एक बहुत ही विपरीत उदाहरण है, लेकिन यह देखने में आसान है कि कार्यों को पास करने में सक्षम होने के रूप में मानो वे एक बहुत ही उपयोगी विशेषता है। खुद योएल द्वारा "कैन योर प्रोग्रामिंग लैंग्वेज डू दिस" देखें ।
इस शैली में जावा प्रोग्रामिंग के लिए एक अच्छा पुस्तकालय: कार्यात्मक जावा।
अनाम आंतरिक वर्ग का उपयोग निम्नलिखित परिदृश्य में किया जाता है:
1.) ओवरराइडिंग (सब क्लासिंग) के लिए, जब वर्तमान मामले को छोड़कर कक्षा की परिभाषा उपयोगी नहीं है:
class A{
public void methodA() {
System.out.println("methodA");
}
}
class B{
A a = new A() {
public void methodA() {
System.out.println("anonymous methodA");
}
};
}
2.) इंटरफ़ेस लागू करने के लिए, जब इंटरफ़ेस का कार्यान्वयन केवल वर्तमान मामले के लिए आवश्यक है:
interface interfaceA{
public void methodA();
}
class B{
interfaceA a = new interfaceA() {
public void methodA() {
System.out.println("anonymous methodA implementer");
}
};
}
3.) तर्क परिभाषित बेनामी आंतरिक वर्ग:
interface Foo {
void methodFoo();
}
class B{
void do(Foo f) { }
}
class A{
void methodA() {
B b = new B();
b.do(new Foo() {
public void methodFoo() {
System.out.println("methodFoo");
}
});
}
}
मैं मानचित्र मानचित्रण के लिए सिंटैक्स हैक के रूप में कभी-कभी उनका उपयोग करता हूं:
Map map = new HashMap() {{
put("key", "value");
}};
बनाम
Map map = new HashMap();
map.put("key", "value");
बहुत सारे पुट बयान करते समय यह कुछ अतिरेक बचाता है। हालाँकि, मैं इसे करने में आने वाली समस्याओं में भी भाग ले चुका हूँ, जब बाहरी वर्ग को रीमोटिंग के माध्यम से क्रमबद्ध करना पड़ता है।
वे आमतौर पर कॉलबैक की क्रिया रूप के रूप में उपयोग किए जाते हैं।
मुझे लगता है कि आप कह सकते हैं कि उनके पास न होने की तुलना में एक फायदा है, और हर बार नामांकित वर्ग बनाने के लिए, लेकिन अन्य भाषाओं में समान अवधारणाओं को बेहतर तरीके से लागू किया जाता है (जैसे क्लोजर या ब्लॉक)
यहाँ एक स्विंग उदाहरण है
myButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// do stuff here...
}
});
हालाँकि यह अभी भी गड़बड़ है, यह आपको इस तरह के हर फेंक श्रोता के लिए एक नामित वर्ग को परिभाषित करने के लिए मजबूर करने से बहुत बेहतर है (हालांकि स्थिति और पुन: उपयोग के आधार पर, यह अभी भी बेहतर दृष्टिकोण हो सकता है)
myButton.addActionListener(e -> { /* do stuff here */})
या myButton.addActionListener(stuff)
terser होगा।
आप इसे उन परिस्थितियों में उपयोग करते हैं जहां आपको किसी अन्य फ़ंक्शन के अंदर एक विशिष्ट उद्देश्य के लिए एक वर्ग बनाने की आवश्यकता होती है, उदाहरण के लिए, एक श्रोता के रूप में, एक रननेबल के रूप में (एक धागा को स्पॉन करने के लिए), आदि।
विचार यह है कि आप उन्हें किसी फ़ंक्शन के कोड के अंदर से कॉल करते हैं ताकि आप उन्हें कहीं और न देखें, इसलिए आपको उन्हें नाम देने की आवश्यकता नहीं है। संकलक बस उन्हें enumerates।
वे अनिवार्य रूप से सिंथेटिक चीनी हैं, और आम तौर पर बड़े होने के साथ कहीं और स्थानांतरित किए जाने चाहिए।
मुझे यकीन नहीं है कि यह जावा के फायदों में से एक है, हालांकि यदि आप उनका उपयोग करते हैं (और हम सभी अक्सर उनका उपयोग करते हैं, दुर्भाग्य से), तो आप तर्क दे सकते हैं कि वे एक हैं।
अनाम वर्ग के लिए गाइडलाइन।
बेनामी वर्ग एक साथ घोषित और आरंभिक है।
अनाम वर्ग को एक या केवल एक वर्ग या इंटरफ़ेस सम्मान का विस्तार या कार्यान्वयन करना चाहिए।
चूंकि अनाम वर्ग का कोई नाम नहीं है, इसलिए इसे केवल एक बार उपयोग किया जा सकता है।
उदाहरण के लिए:
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
});
ref.getClass().newInstance()
।
हां, अनाम आंतरिक कक्षाएं निश्चित रूप से जावा के फायदों में से एक हैं।
एक अनाम आंतरिक वर्ग के साथ आपके पास आसपास के वर्ग के अंतिम और सदस्य चर तक पहुंच है, और यह श्रोताओं आदि के काम में आता है।
लेकिन एक प्रमुख लाभ यह है कि आंतरिक वर्ग कोड, जो (कम से कम होना चाहिए) कसकर आसपास के वर्ग / विधि / ब्लॉक से जुड़ा होता है, का एक विशिष्ट संदर्भ (आसपास का वर्ग, विधि और ब्लॉक) होता है।
new Thread() {
public void run() {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
System.out.println("Exception message: " + e.getMessage());
System.out.println("Exception cause: " + e.getCause());
}
}
}.start();
यह भी धागे का उपयोग कर गुमनाम आंतरिक प्रकार के लिए एक उदाहरण है
मैं नए धागे कॉल करने के लिए अनाम वस्तुओं का उपयोग करें ..
new Thread(new Runnable() {
public void run() {
// you code
}
}).start();
एक आंतरिक वर्ग बाहरी वर्ग के एक उदाहरण के साथ जुड़ा हुआ है और दो विशेष प्रकार हैं: स्थानीय वर्ग और अनाम वर्ग । एक अनाम वर्ग हमें एक ही समय में एक वर्ग घोषित करने और तत्काल करने में सक्षम बनाता है, इसलिए कोड को संक्षिप्त बनाता है। हम उनका उपयोग तब करते हैं जब हमें एक स्थानीय वर्ग की आवश्यकता होती है जब उनका नाम नहीं होता है।
डॉक्टर के पास एक उदाहरण पर विचार करें जहां हमारा एक Person
वर्ग है:
public class Person {
public enum Sex {
MALE, FEMALE
}
String name;
LocalDate birthday;
Sex gender;
String emailAddress;
public int getAge() {
// ...
}
public void printPerson() {
// ...
}
}
और हमारे पास खोज मापदंड से मेल खाने वाले सदस्यों को मुद्रित करने की एक विधि है:
public static void printPersons(
List<Person> roster, CheckPerson tester) {
for (Person p : roster) {
if (tester.test(p)) {
p.printPerson();
}
}
}
CheckPerson
इंटरफ़ेस कहाँ है:
interface CheckPerson {
boolean test(Person p);
}
अब हम अनाम वर्ग का उपयोग कर सकते हैं जो खोज मापदंड को निर्दिष्ट करने के लिए इस इंटरफ़ेस को लागू करता है:
printPersons(
roster,
new CheckPerson() {
public boolean test(Person p) {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
}
);
यहां इंटरफ़ेस बहुत सरल है और अनाम वर्ग का वाक्यविन्यास अस्पष्ट और अस्पष्ट लगता है।
जावा 8 ने एक कार्यात्मक फंक्शनल शब्द पेश किया है, जो केवल एक सार पद्धति वाला एक इंटरफ़ेस है, इसलिए हम कह सकते हैं कि CheckPerson
यह एक कार्यात्मक इंटरफ़ेस है। हम लैम्ब्डा एक्सप्रेशन का उपयोग कर सकते हैं जो हमें विधि तर्क के रूप में फ़ंक्शन को पास करने की अनुमति देता है:
printPersons(
roster,
(Person p) -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
);
हम इंटरफ़ेस Predicate
के स्थान पर एक मानक कार्यात्मक इंटरफ़ेस का उपयोग कर सकते हैं CheckPerson
, जो आवश्यक कोड की मात्रा को और कम कर देगा।
विभिन्न वस्तुओं के लिए अलग-अलग कार्यान्वयन देते समय अनाम आंतरिक वर्ग फायदेमंद हो सकता है। लेकिन बहुत ही संयम से इस्तेमाल किया जाना चाहिए क्योंकि यह प्रोग्राम पठनीयता के लिए समस्या पैदा करता है।
कक्षा-फाइनल में अनाम कक्षाओं के प्रमुख उपयोग में से एक जिसे अंतिम संरक्षक कहा जाता है । जावा दुनिया में अंतिम तरीकों का उपयोग करने से बचना चाहिए जब तक कि आपको वास्तव में उनकी आवश्यकता न हो। आपको याद रखना होगा, जब आप उप-वर्गों के लिए अंतिम विधि को ओवरराइड करते हैं, तो आपको हमेशा ही लागू करना चाहिए super.finalize()
, क्योंकि सुपर क्लास का अंतिम तरीका स्वचालित रूप से नहीं होगा और आपको मेमोरी लीक की समस्या हो सकती है।
इसलिए ऊपर वर्णित तथ्य को देखते हुए, आप बस अनाम वर्गों का उपयोग कर सकते हैं जैसे:
public class HeavyClass{
private final Object finalizerGuardian = new Object() {
@Override
protected void finalize() throws Throwable{
//Finalize outer HeavyClass object
}
};
}
इस तकनीक का उपयोग करके आप अपने और अपने दूसरे डेवलपर्स को राहत देने के लिए super.finalize()
प्रत्येक उप-वर्ग पर कॉल कर सकते हैं, HeavyClass
जिसकी अंतिम विधि की आवश्यकता है।
यहाँ किसी का उल्लेख नहीं किया गया है, लेकिन आप सामान्य प्रकार के तर्क को रखने के लिए अनाम वर्ग का भी उपयोग कर सकते हैं (जो सामान्य रूप से प्रकार के क्षरण के कारण खो गया है) :
public abstract class TypeHolder<T> {
private final Type type;
public TypeReference() {
// you may do do additional sanity checks here
final Type superClass = getClass().getGenericSuperclass();
this.type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}
public final Type getType() {
return this.type;
}
}
यदि आप अनाम तरीके से इस वर्ग को तुरंत भेज देंगे
TypeHolder<List<String>, Map<Ineger, Long>> holder =
new TypeHolder<List<String>, Map<Ineger, Long>>() {};
फिर ऐसे holder
उदाहरण में पारित प्रकार की गैर-मिटाई गई परिभाषा होगी।
यह सत्यापनकर्ता / डिसेरिएलिज़ेटर्स के निर्माण के लिए बहुत उपयोगी है। इसके अलावा आप प्रतिबिंब के साथ जेनेरिक प्रकार को तुरंत कर सकते हैं (इसलिए यदि आप कभी भी new T()
पैरामीट्रिक प्रकार में करना चाहते थे - आपका स्वागत है) ।
कोड को ऑप्टिमाइज़ करने का सबसे अच्छा तरीका। इसके अलावा, हम एक वर्ग या इंटरफ़ेस की ओवरराइडिंग विधि के लिए उपयोग कर सकते हैं।
import java.util.Scanner;
abstract class AnonymousInner {
abstract void sum();
}
class AnonymousInnerMain {
public static void main(String []k){
Scanner sn = new Scanner(System.in);
System.out.println("Enter two vlaues");
int a= Integer.parseInt(sn.nextLine());
int b= Integer.parseInt(sn.nextLine());
AnonymousInner ac = new AnonymousInner(){
void sum(){
int c= a+b;
System.out.println("Sum of two number is: "+c);
}
};
ac.sum();
}
}
एक अनाम इनर क्लास का उपयोग एक ऐसी वस्तु बनाने के लिए किया जाता है जिसे फिर से संदर्भित नहीं किया जाएगा। इसका कोई नाम नहीं है और एक ही बयान में घोषित और बनाया गया है। यह वह जगह है जहाँ आप सामान्य रूप से किसी वस्तु के चर का उपयोग करेंगे। आप new
कीवर्ड के साथ वेरिएबल को बदलते हैं , एक कंस्ट्रक्टर को कॉल करते हैं और क्लास की परिभाषा को अंदर {
और }
।
जावा में थ्रेडेड प्रोग्राम लिखते समय, यह आमतौर पर इस तरह दिखेगा
ThreadClass task = new ThreadClass();
Thread runner = new Thread(task);
runner.start();
यहां ThreadClass
उपयोग उपयोगकर्ता परिभाषित किया जाएगा। यह वर्ग उन Runnable
इंटरफ़ेस को लागू करेगा जो थ्रेड बनाने के लिए आवश्यक है। में विधि (केवल में विधि ) के रूप में अच्छी तरह से लागू किया जाना चाहिए। यह स्पष्ट है कि छुटकारा पाना अधिक कुशल होगा और यही कारण है कि बेनामी इनर क्लासेस मौजूद हैं।ThreadClass
run()
Runnable
ThreadClass
निम्नलिखित कोड को देखें
Thread runner = new Thread(new Runnable() {
public void run() {
//Thread does it's work here
}
});
runner.start();
यह कोड task
सबसे ऊपर के उदाहरण में किए गए संदर्भ को बदल देता है । एक अलग वर्ग होने के बजाय, Thread()
निर्माणकर्ता के अंदर बेनामी इनर क्लास एक अनाम वस्तु देता है जो Runnable
इंटरफ़ेस को लागू करता है और run()
विधि को ओवरराइड करता है। विधि run()
में कथन शामिल होंगे जो थ्रेड द्वारा आवश्यक कार्य करते हैं।
बेनामी इनर क्लासेस जावा के फायदों में से एक है, इस सवाल का जवाब देते हुए, मुझे यह कहना होगा कि मुझे यकीन नहीं है क्योंकि मैं इस समय कई प्रोग्रामिंग भाषाओं से परिचित नहीं हूं। लेकिन मैं जो कह सकता हूं वह निश्चित रूप से कोडिंग का एक तेज और आसान तरीका है।
संदर्भ: Sams 21 दिनों के सातवें संस्करण में अपने आप को जावा सिखाओ