নিচের কোনটি ভাল?
a instanceof B
অথবা
B.class.isAssignableFrom(a.getClass())
আমি কেবল যে পার্থক্যটি জানি তা হ'ল, যখন 'এ' নਾਲ হয়, প্রথমটি মিথ্যা দেয়, দ্বিতীয়টি ব্যতিক্রম ছুঁড়ে দেয়। তা ছাড়া তারা কি সর্বদা একই ফল দেয়?
নিচের কোনটি ভাল?
a instanceof B
অথবা
B.class.isAssignableFrom(a.getClass())
আমি কেবল যে পার্থক্যটি জানি তা হ'ল, যখন 'এ' নਾਲ হয়, প্রথমটি মিথ্যা দেয়, দ্বিতীয়টি ব্যতিক্রম ছুঁড়ে দেয়। তা ছাড়া তারা কি সর্বদা একই ফল দেয়?
উত্তর:
ব্যবহার করার সময় instanceof
, আপনাকে B
সংকলন সময়ে ক্লাসটি জানতে হবে । isAssignableFrom()
এটি ব্যবহার করার সময় গতিশীল এবং রানটাইমের সময় পরিবর্তন হতে পারে।
a instanceof Bref.getClass()
। এত অল্প ব্যাখ্যা দিয়ে (বা এর অভাব) কীভাবে এটি গ্রহণযোগ্য উত্তর হতে পারে?
a instanceof Bref
না a instanceof Bref.class
। উদাহরণস্বরূপ অপারেটরের দ্বিতীয় তর্কটি একটি শ্রেণীর নাম, কোনও শ্রেণীর অবজেক্টের দৃষ্টান্তের সাথে সমাধান করা কোনও অভিব্যক্তি নয়।
B.class.isAssignableFrom(a.getClass())
বি পরিচিত, এবং a instanceof B
আরও ভাল। রাইট?
instanceof
প্রারম্ভিক ধরণের নয়, কেবলমাত্র রেফারেন্স ধরণের সাথে ব্যবহার করা যেতে পারে। isAssignableFrom()
যে কোনও শ্রেণীর অবজেক্টের সাথে ব্যবহার করা যেতে পারে:
a instanceof int // syntax error
3 instanceof Foo // syntax error
int.class.isAssignableFrom(int.class) // true
দেখা http://java.sun.com/javase/6/docs/api/java/lang/Class.html#isAssignableFrom(java.lang.Class) ।
পারফরম্যান্সের বিচারে:
টি এল; ডিআর
আইস ইনস্ট্যান্স বা উদাহরণস্বরূপ ব্যবহার করুন যা একই রকম পারফরম্যান্স করে। #SignignFrom সামান্য ধীর।
সম্পাদনা অনুসারে বাছাই করা:
20 ওয়ার্মআপ পুনরাবৃত্তি সহ জাভা 8 উইন্ডোজ এক্স 64 এ 2000 পুনরাবৃত্তির মানদণ্ডের উপর ভিত্তি করে।
ধারণায়
বাইটকোড দর্শকের মতো নরম ব্যবহার করে আমরা প্রতিটি অপারেটরকে বাইটকোডে অনুবাদ করতে পারি।
এর প্রেক্ষাপটে:
package foo;
public class Benchmark
{
public static final Object a = new A();
public static final Object b = new B();
...
}
জাভা:
b instanceof A;
বাইটকোড:
getstatic foo/Benchmark.b:java.lang.Object
instanceof foo/A
জাভা:
A.class.isInstance(b);
বাইটকোড:
ldc Lfoo/A; (org.objectweb.asm.Type)
getstatic foo/Benchmark.b:java.lang.Object
invokevirtual java/lang/Class isInstance((Ljava/lang/Object;)Z);
জাভা:
A.class.isAssignableFrom(b.getClass());
বাইটকোড:
ldc Lfoo/A; (org.objectweb.asm.Type)
getstatic foo/Benchmark.b:java.lang.Object
invokevirtual java/lang/Object getClass(()Ljava/lang/Class;);
invokevirtual java/lang/Class isAssignableFrom((Ljava/lang/Class;)Z);
প্রতিটি অপারেটর কতগুলি বাইটকোড নির্দেশাবলী ব্যবহার করে তা পরিমাপ করে আমরা উদাহরণস্বরূপ আশা করতে পারি এবং আইসনস্ট্যান্স isAsignableFrom এর চেয়ে দ্রুত হবে । তবে, আসল পারফরম্যান্স বাইটকোড দ্বারা নয় বরং মেশিন কোড (যা প্ল্যাটফর্ম নির্ভর) দ্বারা নির্ধারিত হয় না। প্রতিটি অপারেটরের জন্য একটি মাইক্রো বেনমার্ক করি।
মানদণ্ড
ক্রেডিট: @ অ্যালেক্সান্দ্র-ডাবিনস্কি পরামর্শ দিয়েছেন এবং বেস কোড সরবরাহ করার জন্য @ ইউুরাকে ধন্যবাদ, এখানে একটি জেএমএইচ বেঞ্চমার্ক রয়েছে (এই টিউনিং গাইডটি দেখুন ):
class A {}
class B extends A {}
public class Benchmark {
public static final Object a = new A();
public static final Object b = new B();
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public boolean testInstanceOf()
{
return b instanceof A;
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public boolean testIsInstance()
{
return A.class.isInstance(b);
}
@Benchmark
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public boolean testIsAssignableFrom()
{
return A.class.isAssignableFrom(b.getClass());
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(TestPerf2.class.getSimpleName())
.warmupIterations(20)
.measurementIterations(2000)
.forks(1)
.build();
new Runner(opt).run();
}
}
নিম্নলিখিত ফলাফল দিয়েছেন (স্কোর একটি একক ইউনিটের বেশ কয়েকটি ক্রিয়াকলাপ , সুতরাং স্কোরটি আরও ভাল):
Benchmark Mode Cnt Score Error Units
Benchmark.testIsInstance thrpt 2000 373,061 ± 0,115 ops/us
Benchmark.testInstanceOf thrpt 2000 371,047 ± 0,131 ops/us
Benchmark.testIsAssignableFrom thrpt 2000 363,648 ± 0,289 ops/us
সতর্কতা
instanceof
আপনার কোডের প্রসঙ্গে isInstance
উদাহরণের চেয়ে আরও সহজেই অনুকূলিত হয়ে উঠতে পারে ...আপনাকে উদাহরণ দেওয়ার জন্য, নিম্নলিখিত লুপটি নিন:
class A{}
class B extends A{}
A b = new B();
boolean execute(){
return A.class.isAssignableFrom(b.getClass());
// return A.class.isInstance(b);
// return b instanceof A;
}
// Warmup the code
for (int i = 0; i < 100; ++i)
execute();
// Time it
int count = 100000;
final long start = System.nanoTime();
for(int i=0; i<count; i++){
execute();
}
final long elapsed = System.nanoTime() - start;
জেআইটি-কে ধন্যবাদ, কোডটি এক পর্যায়ে অনুকূলিত হয়েছে এবং আমরা পেয়েছি:
বিঃদ্রঃ
প্রকৃতপক্ষে এই পোস্টটি নিজস্ব বেঞ্চমার্ক একটি ব্যবহার করছেন জন্য কাঁচা জাভা লুপ, যা ঠিক সময়ে মত কিছু অপ্টিমাইজেশান লুপ বাদ দিতে পারে যেমন অবিশ্বস্ত ফলাফল দিলেন। সুতরাং এটি বেশিরভাগই পরিমাপ করছিল যে লুটের অনুকূলকরণ করতে জেআইটি সংকলকটি কতটা সময় নিয়েছিল: আরও তথ্যের জন্য পুনরাবৃত্তির সংখ্যার চেয়ে পারফরম্যান্স টেস্ট দেখুন
সম্পর্কিত প্রশ্নাবলী
instanceof
একটি বাইটকোড যা মূলত একই যুক্তি checkcast
(কাস্টিংয়ের পিছনে বাইটকোড) ব্যবহার করে। এটি জেআইটিসি অপ্টিমাইজেশনের ডিগ্রি নির্বিশেষে অন্যান্য বিকল্পগুলির থেকে সহজাতভাবে দ্রুত হবে।
isAssignableFrom()
গতিশীল।
একটি আরো সরাসরি সমতুল্য a instanceof B
হয়
B.class.isInstance(a)
এই কাজ (রিটার্ন মিথ্যা) যখন a
হয় null
খুব।
উপরে বর্ণিত মৌলিক পার্থক্যগুলি ছাড়াও ক্লাসে উদাহরণস্বরূপ অপারেটর এবং isAignignFrom পদ্ধতির মধ্যে একটি মূল সূক্ষ্ম পার্থক্য রয়েছে।
পড়ুন instanceof
যেমন "এই (বাম অংশ) হয় (ডান অংশ) এই দৃষ্টান্ত বা এই কোন উপশ্রেণী" এবং পড়া x.getClass().isAssignableFrom(Y.class)
হিসাবে "ক্যান আমি লিখি X x = new Y()
"। অন্য কথায়, উদাহরণস্বরূপ অপারেটর চেক করে যে বাম বস্তুটি সমান বা ডান শ্রেণীর সাবক্লাস, isAssignableFrom
যদি পরীক্ষা করা হয় তবে আমরা প্যারামিটার ক্লাসের অবজেক্টটি নির্ধারণ করতে পারি কিনা (যা থেকে) পদ্ধতিটি বলা হয়।
নোট করুন যে এই দু'টিই প্রকৃত উদাহরণ বিবেচনা করে রেফারেন্স ধরণের নয়।
A, B এবং C শ্রেণীর 3 টি উদাহরণ বিবেচনা করুন যেখানে C এবং B এবং B বিস্তৃত হয় A.
B b = new C();
System.out.println(b instanceof A); //is b (which is actually class C object) instance of A, yes. This will return true.
System.out.println(b instanceof B); // is b (which is actually class C object) instance of B, yes. This will return true.
System.out.println(b instanceof C); // is b (which is actually class C object) instance of C, yes. This will return true. If the first statement would be B b = new B(), this would have been false.
System.out.println(b.getClass().isAssignableFrom(A.class));//Can I write C c = new A(), no. So this is false.
System.out.println(b.getClass().isAssignableFrom(B.class)); //Can I write C c = new B(), no. So this is false.
System.out.println(b.getClass().isAssignableFrom(C.class)); //Can I write C c = new C(), Yes. So this is true.
b instanceof A
এর সমতুল্য A.class.isAssignableFrom(b.getClass())
(যেমন ওপি লক্ষ্য করেছে)। আপনার উদাহরণটি সঠিক তবে অপ্রাসঙ্গিক।
new Y()
আইনী নাও হতে পারে Y
, তাই আপনি X x = (Y)null
যদি সঠিক হন এবং কেবল x.getClass().isAssignableFrom(Y.class)
সত্য হয় তা বলতে পারেন ।
আরও একটি পার্থক্য রয়েছে:
এক্স নাল উদাহরণস্বরূপ false
তা বিচার্য নয়
null.getClass ()। isAignignableFrom (X) একটি নালপয়েন্টার এক্সেকশন নিক্ষেপ করবে
null instanceof X
(যেখানে সংকলনের সময় এক্স কিছু শ্রেণি হিসাবে পরিচিত) সর্বদা ফিরে আসবে false
।
X.class.isAssignableFrom(null.getClass())
উচিত? তবে হ্যাঁ, getClass()
নাল রেফারেন্সে কল করার ফলে এনপিই হবে।
getClass()
ব্যবহার করা উচিত নয় isAssignableFrom
- অপারেশনটি কোনও বস্তু না থাকার পরিস্থিতির জন্য বোঝানো হয়। আপনি অবজেক্ট রেফারেন্স থাকে a
, ব্যবহার a instanceof SomeClass
(যদি আপনি না টাইপ জানেন SomeClass
) অথবা someObject.getClass().isInstance(a)
(যদি আপনি না ধরণ জানেন someObject
)।
আরও একটি পার্থক্য আছে। যদি পরীক্ষার জন্য (শ্রেণি) টাইপটি গতিশীল হয়, উদাহরণস্বরূপ কোনও পদ্ধতি প্যারামিটার হিসাবে পাস করা হয়, তবে উদাহরণস্বরূপ এটি আপনার জন্য কাটবে না।
boolean test(Class clazz) {
return (this instanceof clazz); // clazz cannot be resolved to a type.
}
তবে আপনি এটি করতে পারেন:
boolean test(Class clazz) {
return (clazz.isAssignableFrom(this.getClass())); // okidoki
}
উফ, আমি দেখছি এই উত্তরটি ইতিমধ্যে কভার করা আছে। এই উদাহরণটি কারও পক্ষে সহায়ক।
this
), clazz.isInstance(this)
আপনার উদাহরণে আরও ভাল।
এই থ্রেডটি আমাকে কীভাবে instanceof
পৃথক করেছে তার কিছুটা অন্তর্দৃষ্টি দিয়েছিল isAssignableFrom
, তাই আমি ভেবেছিলাম যে আমি নিজের কিছু ভাগ করব।
আমি এটি ব্যবহার করে খুঁজে পেয়েছি isAssignableFrom
একমাত্র শ্রেণিটির রেফারেন্স অন্য শ্রেণীর উদাহরণ নিতে পারে, তবে যখন কারও সাথে তুলনা না করার উদাহরণ রয়েছে তখন নিজেকে জিজ্ঞাসা করার একমাত্র (সম্ভবত একমাত্র নয়, সম্ভবত সবচেয়ে সহজ) উপায় way
অতএব, আমি instanceof
অপারেটরটি অ্যাসাইনবিলিটি তুলনা করতে ভাল ধারণা হিসাবে খুঁজে পাইনি যখন আমার সমস্ত ক্লাস ছিল, যদি না আমি ক্লাসগুলির মধ্যে একটির থেকে উদাহরণ তৈরি করার চিন্তা না করি; আমি ভেবেছিলাম এই হবে।
উদাহরণটি আদিম ধরণের বা জেনেরিক প্রকারের সাথে ব্যবহার করা যায় না। নিম্নলিখিত কোড হিসাবে:
//Define Class< T > type ...
Object e = new Object();
if(e instanceof T) {
// Do something.
}
ত্রুটিটি হ'ল: প্যারামিটার টি টাইপের বিরুদ্ধে চেক পরীক্ষা করতে পারবেন না instead এর পরিবর্তে এর ক্ষয়কারী অবজেক্টটি ব্যবহার করুন কারণ আরও জেনেরিক ধরণের তথ্য রানটাইমে মুছে ফেলা হবে।
রানটাইম রেফারেন্স অপসারণ করে টাইপ মুছে ফেলার কারণে সংকলন করে না। তবে নীচের কোডটি সংকলন করবে:
if( type.isAssignableFrom(e.getClass())){
// Do something.
}
নিম্নলিখিত পরিস্থিতি বিবেচনা করুন। ধরুন আপনি টাইপ এ প্রকারের ধরণের একটি সুপার ক্লাস কিনা তা আপনি যাচাই করতে চান, আপনি যে কোনও জায়গায় যেতে পারেন
... A.class.isAignignFFrom (obj.getClass ()) ...
অথবা
... আপত্তি উদাহরণ এ ...
তবে isAignignFrom সমাধানের জন্য এখানে আপত্তিটির ধরণটি দৃশ্যমান হওয়া দরকার। যদি এটি না হয় (উদাঃ, আপত্তিটির ধরণটি কোনও ব্যক্তিগত অভ্যন্তর শ্রেণীর হতে পারে), এই বিকল্পটি বাইরে is তবে উদাহরণস্বরূপ সমাধানটি সর্বদা কার্যকর হবে work
obj
এই উদাহরণস্বরূপ) নন-নাল রেফারেন্স থাকে তবে আপনি প্রয়োগকারী শ্রেণীর প্রতিচ্ছবি মেটাডেটা পেতে এটিতে সর্বজনীন পদ্ধতিতে কল করতে পারেন । এটি সত্য যে এমনকি সংকলনের সময় শ্রেণীর প্রয়োগকারী শ্রেণিটি আইনীভাবে দৃশ্যমান হবে না। এটা তোলে এর রানটাইম এ ঠিক আছে, কারণ আপনি রাখা জন্য রেফারেন্স, কিছু কোড পথ যা পরিণামে করেনি বর্গ আইনি এক্সেস আছে এক সৃষ্টি করেছি এবং তোমাদেরকে দিয়েছেন (ফাঁস?) করুন। getClass()
obj
isAssignableFrom(A, B) =
if (A == B) return true
else if (B == java.lang.Object) return false
else return isAssignableFrom(A, getSuperClass(B))
উপরের সিউডো কোডটি একটি সংজ্ঞা, টাইপ / শ্রেণি বি এর রেফারেন্স টাইপ / শ্রেণি বি এর রেফারেন্স থেকে নির্ধারিত হয় এটি একটি পুনরাবৃত্ত সংজ্ঞা। কারও কাছে এটি সহায়ক হতে পারে, অন্যের জন্য এটি বিভ্রান্তিকর হতে পারে। কারওর পক্ষে এটির দরকারী হওয়া উচিত যদি আমি এটি যুক্ত করি। এটি আমার বোঝাপড়াটি কেবল ধরা দেওয়ার চেষ্টা, এটি সরকারী সংজ্ঞা নয়। এটি একটি নির্দিষ্ট জাভা ভিএম বাস্তবায়নে ব্যবহৃত হয় এবং অনেকগুলি উদাহরণস্বরূপ প্রোগ্রামগুলির জন্য কাজ করে, তাই আমি নিশ্চিত করতে পারি না যে এটি isignableFrom এর সমস্ত দিক ক্যাপচার করে, এটি সম্পূর্ণভাবে বন্ধ নয়।
পারফরম্যান্স "2" (জেএমএইচ সহ) এর সাথে কথা বলছি:
class A{}
class B extends A{}
public class InstanceOfTest {
public static final Object a = new A();
public static final Object b = new B();
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public boolean testInstanceOf()
{
return b instanceof A;
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public boolean testIsInstance()
{
return A.class.isInstance(b);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public boolean testIsAssignableFrom()
{
return A.class.isAssignableFrom(b.getClass());
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(InstanceOfTest.class.getSimpleName())
.warmupIterations(5)
.measurementIterations(5)
.forks(1)
.build();
new Runner(opt).run();
}
}
এটি দেয়:
Benchmark Mode Cnt Score Error Units
InstanceOfTest.testInstanceOf avgt 5 1,972 ? 0,002 ns/op
InstanceOfTest.testIsAssignableFrom avgt 5 1,991 ? 0,004 ns/op
InstanceOfTest.testIsInstance avgt 5 1,972 ? 0,003 ns/op
সুতরাং আমরা এই উপসংহারে আসতে পারি যে: instanceof যত দ্রুত isInstance () এবং isAssignableFrom () না দূরে (+ + 0.9% executon সময়)। সুতরাং আপনি যা পছন্দ করুন কোনও আসল পার্থক্য নেই
এটি কার্যকরভাবে দেখানোর জন্য কয়েকটি উদাহরণ সম্পর্কে কীভাবে ...
@Test
public void isInstanceOf() {
Exception anEx1 = new Exception("ex");
Exception anEx2 = new RuntimeException("ex");
RuntimeException anEx3 = new RuntimeException("ex");
//Base case, handles inheritance
Assert.assertTrue(anEx1 instanceof Exception);
Assert.assertTrue(anEx2 instanceof Exception);
Assert.assertTrue(anEx3 instanceof Exception);
//Other cases
Assert.assertFalse(anEx1 instanceof RuntimeException);
Assert.assertTrue(anEx2 instanceof RuntimeException);
Assert.assertTrue(anEx3 instanceof RuntimeException);
}
@Test
public void isAssignableFrom() {
Exception anEx1 = new Exception("ex");
Exception anEx2 = new RuntimeException("ex");
RuntimeException anEx3 = new RuntimeException("ex");
//Correct usage = The base class goes first
Assert.assertTrue(Exception.class.isAssignableFrom(anEx1.getClass()));
Assert.assertTrue(Exception.class.isAssignableFrom(anEx2.getClass()));
Assert.assertTrue(Exception.class.isAssignableFrom(anEx3.getClass()));
//Incorrect usage = Method parameter is used in the wrong order
Assert.assertTrue(anEx1.getClass().isAssignableFrom(Exception.class));
Assert.assertFalse(anEx2.getClass().isAssignableFrom(Exception.class));
Assert.assertFalse(anEx3.getClass().isAssignableFrom(Exception.class));
}
আমাদের দলে আমরা কিছু পরীক্ষা করেছি যা তার A.class.isAssignableFrom(B.getClass())
চেয়ে দ্রুত কাজ করে B instanceof A
। আপনার যদি এটি প্রচুর পরিমাণে উপাদানগুলিতে পরীক্ষা করতে হয় তবে এটি খুব কার্যকর হতে পারে।
instanceof
আমি বিশ্বাস করি আপনার ডিজাইনের মারাত্মক সমস্যা রয়েছে ...