স্থির এবং গতিশীল বাঁধাই আসলে কীভাবে কাজ করে তা বোঝার জন্য ? বা কীভাবে তারা সংকলক এবং জেভিএম দ্বারা চিহ্নিত হয়?
আসুন নীচের উদাহরণটি নেওয়া যাক যেখানে Mammal
কোনও প্যারেন্ট ক্লাস যেখানে একটি পদ্ধতি রয়েছে speak()
এবং Human
শ্রেণিটি প্রসারিত হয় Mammal
, সেই speak()
পদ্ধতিটি ওভাররাইড করে এবং তারপরে আবার এটি দিয়ে ওভারলোড হয় speak(String language)
।
public class OverridingInternalExample {
private static class Mammal {
public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
}
private static class Human extends Mammal {
@Override
public void speak() { System.out.println("Hello"); }
public void speak(String language) {
if (language.equals("Hindi")) System.out.println("Namaste");
else System.out.println("Hello");
}
@Override
public String toString() { return "Human Class"; }
}
public static void main(String[] args) {
Mammal anyMammal = new Mammal();
anyMammal.speak();
Mammal humanMammal = new Human();
humanMammal.speak();
Human human = new Human();
human.speak();
human.speak("Hindi");
}
}
যখন আমরা উপরের কোডটি সংকলন করি এবং বাইটকোড ব্যবহার করে দেখার চেষ্টা javap -verbose OverridingInternalExample
করি, আমরা দেখতে পাই যে সংকলকটি একটি ধ্রুবক সারণী উত্পন্ন করে যেখানে এটি প্রোগ্রামের জন্য প্রতিটি পদ্ধতি কল এবং বাইট কোডের জন্য পূর্ণসংখ্যা কোড নির্ধারণ করে যা আমি নিজেই প্রোগ্রামটিতে অন্তর্ভুক্ত করেছি এবং অন্তর্ভুক্ত করেছি ( প্রতিটি পদ্ধতি কল নীচের মন্তব্য দেখুন)
উপরের কোড দিকে তাকিয়ে আমরা যে bytecodes দেখতে পারেন humanMammal.speak()
, human.speak()
এবং human.speak("Hindi")
সম্পূর্ণ ভিন্ন হয় ( invokevirtual #4
, invokevirtual #7
, invokevirtual #9
) কারণ কম্পাইলার যুক্তি তালিকা এবং বর্গ রেফারেন্স উপর ভিত্তি করে তাদের মধ্যে পার্থক্য করতে সক্ষম হয়। কারণ এগুলি সমস্তই সংকলনের সময়ে স্থিরভাবে সমাধান হয়ে যায় সেজন্যই মেথড ওভারলোডিং স্ট্যাটিক পলিমারফিজম বা স্ট্যাটিক বাইন্ডিং হিসাবে পরিচিত ।
তবে বাইটকোড anyMammal.speak()
এবং humanMammal.speak()
একই ( invokevirtual #4
) কারণ সংকলক অনুসারে উভয় পদ্ধতি Mammal
রেফারেন্সে ডাকা হয় ।
সুতরাং এখন প্রশ্ন আসে যদি উভয় পদ্ধতির কলগুলিতে একই বাইটোকোড থাকে তবে জেভিএম কীভাবে কল করবে যে পদ্ধতিটি কল করতে হবে?
ঠিক আছে, উত্তরটি বাইকোডে নিজেই লুকানো আছে এবং এটি invokevirtual
নির্দেশের সেট। জেভিএম invokevirtual
সি ++ ভার্চুয়াল পদ্ধতির জাভা সমতুল্য প্রার্থনা করতে নির্দেশ ব্যবহার করে । সি ++ এ আমরা যদি অন্য পদ্ধতিতে একটি পদ্ধতিকে ওভাররাইড করতে চাই তবে আমাদের এটিকে ভার্চুয়াল হিসাবে ঘোষণা করতে হবে, তবে জাভাতে, সমস্ত পদ্ধতিগুলি ডিফল্টরূপে ভার্চুয়াল হয় কারণ আমরা শিশু শ্রেণিতে প্রতিটি পদ্ধতি ওভাররাইড করতে পারি (ব্যক্তিগত, চূড়ান্ত এবং স্থির পদ্ধতি বাদে)।
জাভাতে, প্রতিটি রেফারেন্স ভেরিয়েবল দুটি লুকানো পয়েন্টার ধারণ করে
- টেবিলের জন্য একটি পয়েন্টার যা আবার বস্তুর পদ্ধতি এবং শ্রেণি অবজেক্টের একটি পয়েন্টার ধারণ করে। যেমন [কথা (), কথা (স্ট্রিং) শ্রেণি অবজেক্ট]
- Object বস্তুর ডেটা যেমন উদাহরণ ভেরিয়েবলের মানগুলির জন্য হিপগুলিতে বরাদ্দ হওয়া মেমোরিটির একটি পয়েন্টার।
সুতরাং সমস্ত অবজেক্ট রেফারেন্স অপ্রত্যক্ষভাবে একটি টেবিলের রেফারেন্স ধরে রাখে যা সেই বস্তুর সমস্ত পদ্ধতি রেফারেন্স ধারণ করে। জাভা এই ধারণাটি সি ++ থেকে ধার নিয়েছে এবং এই টেবিলটি ভার্চুয়াল টেবিল (vtable) হিসাবে পরিচিত।
একটি ভেটেবল হ'ল কাঠামোর মতো একটি অ্যারে যা ভার্চুয়াল পদ্ধতির নাম এবং অ্যারে সূচকগুলিতে তাদের রেফারেন্স ধারণ করে। JVM ক্লাসটি মেমরিতে লোড করলে প্রতি ক্লাসে কেবল একটি vtable তৈরি করে।
সুতরাং যখনই কোন invokevirtual
নির্দেশের সেটগুলির সাথে জেভিএমের মুখোমুখি হয় , এটি পদ্ধতি রেফারেন্সের জন্য class শ্রেণীর ভিটিবেলটি পরীক্ষা করে এবং নির্দিষ্ট পদ্ধতিটি আহ্বান করে যা আমাদের ক্ষেত্রে কোনও অবজেক্ট থেকে রেফারেন্স নয় পদ্ধতি।
কারণ এগুলি সমস্তই কেবল রানটাইম এ সমাধান হয়ে যায় এবং রানটাইম সময়ে জেভিএম জানতে পারে যে কোন পদ্ধতিটি চালু করতে হবে, সে কারণেই মেথড ওভাররাইডিং ডায়নামিক পলিমারফিজম বা কেবল পলিমারফিজম বা ডায়নামিক বাইন্ডিং হিসাবে পরিচিত ।
আপনি এটি আমার নিবন্ধে আরও বিশদটি পড়তে পারেন কীভাবে জেভিএম অভ্যন্তরীণভাবে ওভারলোডিং এবং ওভাররাইডিং পদ্ধতিটি পরিচালনা করে ।