সরাসরি পর্বে যান
পর্ব ৫৭ · ৫৯-এর মধ্যে · মডিউল ৮

MCQ প্রশ্নব্যাংক — Java-র ১২৫টি প্রশ্নে যেকোনো পরীক্ষার প্রস্তুতি

Java MCQ Question Bank — 125 Questions, Every Option Explained

Taught in Bangla, this question bank has 125 Java MCQs in 7 sections following the course modules, from JDK, JVM and core syntax to OOP, records, generics, collections, streams, threads, Maven, JUnit, JDBC and Spring. Every option is explained, answers are verified on OpenJDK 21, and deep dives cover classic traps like String == and the Integer cache.

এই পর্বে যা করবেন

  • MCQ পরীক্ষা Java-র কোন কোন দিক যাচাই করে, তা চেনা
  • বাদ দেওয়ার পদ্ধতি, “সব সময়/কখনো না” ধরনের শব্দের ফাঁদ আর সময় ভাগের কৌশল শেখা
  • পুরো কোর্সের ১২৫টি প্রশ্নে নিজের দুর্বল জায়গা খুঁজে বের করা
  • সবচেয়ে প্রচলিত ফাঁদ — String-এর ==, Integer cache, equals-hashCode, pass-by-value, checked exception, ConcurrentModificationException — গভীরভাবে বোঝা
  • AI দিয়ে আরও প্রশ্ন বানানো, আর সেগুলোর “সঠিক উত্তর” কোড চালিয়ে যাচাই করা

১ · MCQ পরীক্ষা Java-কে কীভাবে যাচাই করে — আর উত্তর বাছাইয়ের কৌশল

রাকিব একটি সফটওয়্যার কোম্পানির অনলাইন পরীক্ষার জন্য পড়ছেন। একই মাসে একটি ব্যাংকের আইটি পদের লিখিত পরীক্ষাও আছে। দুই জায়গাতেই প্রথম ধাপ MCQ — চারটি অপশন, একটি সঠিক। রাকিব Spring Boot দিয়ে প্রজেক্ট করেছেন, ArrayList আর HashMap রোজ ব্যবহার করেন। তবু প্রথম অনুশীলন সেটে ৪০টির মধ্যে ঠিক হলো ২৫টি। কেন?

কারণ MCQ প্রোগ্রাম লেখার পরীক্ষা নয়। এটি নিখুঁত খুঁটিনাটির পরীক্ষা। IDE-তে কোড লেখার সময় লাল দাগ ভুল ধরিয়ে দেয়, আপনি ঠিক করে নেন। MCQ-তে IDE নেই — আপনার মাথাই javac আর JVM. আর প্রশ্নকর্তা জেনেশুনে এমন ভুল অপশন রাখেন, যা দেখতে একদম ঠিক মনে হয়। এমন বিভ্রান্তিকর অপশনকে বলে distractor. Java-তে distractor বানানো সহজ, কারণ ভাষাটির অনেক নিয়মের পেছনে লুকানো কারণ আছে — String pool, autoboxing, overload বাছাই, dynamic dispatch.

সাত ধরনের প্রশ্ন

Java-র MCQ মোটামুটি সাতটি ছাঁচে পড়ে। কোন ছাঁচের প্রশ্ন, সেটা চিনতে পারলে অর্ধেক কাজ হয়ে যায়:

ধরনউদাহরণআসলে কী মাপে
ধারণা মনে রাখা“JIT compiler কী করে?”সংজ্ঞা সঠিকভাবে জানেন কি না
বৈধ কোনটি?“কোন লাইনটি compile হবে না?”টাইপ, access আর overload-এর নিয়ম
OOP-এর পরিভাষা“কোনটি interface-এ রাখা যায় না?”class, inheritance, interface-এর শব্দভান্ডার
আউটপুট কী?ছোট কোড, চারটি সম্ভাব্য আউটপুটমাথায় কোড চালানো — String জোড়া, constructor-এর ক্রম
কোন exception?“চলার সময় কী হবে?”exception-এর সঠিক নাম আর কখন আসে
Collections ও কমপ্লেক্সিটি“TreeMap.get-এর সময়?”কোন collection কোন কাজে কত দ্রুত
কোনটি মিথ্যা?চারটি বাক্য, একটি ভুলপুরো বিষয়ের ওপর দখল — প্রতিটি বাক্য যাচাই

কৌশল ১ · বাদ দেওয়ার পদ্ধতি

সঠিক উত্তর সরাসরি খোঁজার চেয়ে ভুলগুলো বাদ দেওয়া প্রায়ই সহজ। একে বলে elimination method. প্রতিটি অপশনকে আলাদা করে জিজ্ঞেস করুন: “এটি ঠিক হতে হলে কোন নিয়মটি সত্য হতে হবে?” যে অপশনের পেছনের নিয়মটি মিথ্যা, সেটি কেটে দিন। নিচের ডায়াগ্রামে একটি চতুর প্রশ্ন এভাবে ধাপে ধাপে সমাধান করা হয়েছে।

  1. বিষয় চেনাremove(1)overload
  2. compile হবে?হ্যাঁঘ বাদ
  3. কোন overload?remove(int)গ বাদ
  4. index 1 কোনটি?20ক বাদ
  5. যাচাই[10, 30]উত্তর খ
প্রশ্নOpenJDK 21
List<Integer> list = new ArrayList<>(List.of(10, 20, 30));
list.remove(1);
System.out.println(list);

ক) [20, 30]   খ) [10, 30]
গ) [10, 20, 30]   ঘ) Compile error
ধাপ ২কোডটি কি compile হবে?
List<Integer>-এ remove(int index) আছে
আর remove(Object o)-ও আছে → দুটিই বৈধ

ক) [20, 30]   খ) [10, 30]
গ) [10, 20, 30]   ঘ) Compile error
ধাপ ৩1 কোন method-এ যায়?
1 একটি int literal
remove(int)    → boxing ছাড়াই মেলে  ✔
remove(Object) → আগে boxing লাগত

ক) [20, 30]   খ) [10, 30]
গ) [10, 20, 30]   ঘ) Compile error
ধাপ ৪index 1-এ কে আছে?
index:  0    1    2
       [10, 20, 30]
index শূন্য থেকে শুরু → 20 সরবে

ক) [20, 30]   খ) [10, 30]
গ) [10, 20, 30]   ঘ) Compile error
ধাপ ৫উত্তর ও ফাঁদের চেক
উত্তর: খ) [10, 30]

যদি লেখা থাকত  list.remove(Integer.valueOf(10));
তাহলে মান 10 সরত → [20, 30]
  1. আগে বিষয় চিনুন। কোডে কোনো লুপ বা হিসাব নেই — আছে একটি remove ডাক। List-এ এই নামের দুটি method আছে: একটি index নেয়, আরেকটি মান (object) নেয়। তাই প্রশ্নটি আসলে overload resolution-এর — compiler কোনটি বাছবে?
  2. কোডটি কি আদৌ compile হবে? দুটি method-ই বৈধ, আর ডাকটি অন্তত একটির সাথে মেলে, তাই “Compile error” (ঘ) বাদ। এই প্রশ্ন সব সময় আগে করুন, কারণ প্রশ্নকর্তা প্রায়ই সঠিক উত্তর হিসেবেই এই অপশন রাখেন — এখানে রাখেননি।
  3. কোন overload? Java overload বাছাই করে ধাপে ধাপে: প্রথমে boxing ছাড়া মেলে এমন method খোঁজে, না পেলে তবেই autoboxing বিবেচনা করে। 1 একটি int, তাই remove(int index) প্রথম ধাপেই জেতে। “কিছুই সরেনি” (গ) মানে হতো মান 1 খোঁজা হয়েছে আর পাওয়া যায়নি — সেটি ঘটে না।
  4. index 1-এ কে? Java-তে index শূন্য থেকে শুরু: index 0-তে 10, index 1-এ 20. তাই 20 সরবে। “[20, 30]” (ক) এসেছে index এক থেকে গোনার ভুল থেকে। এখন বাকি একটিই।
  5. উত্তর খ — তারপর ফাঁদটি মনে রাখুন। শেষে ভাবুন, প্রশ্নকর্তা ক আর গ কেন রেখেছিলেন। মান ধরে সরাতে চাইলে লিখতে হয় list.remove(Integer.valueOf(10)) — তখন উত্তর হতো ক. ভুল অপশন দেখেই বোঝা যায় প্রশ্নটি কোন ভুল ধারণা ধরতে চায়।

কৌশল ২ · “Compile error”, “Exception” আর “নিশ্চিত নয়” অপশন

Java-র MCQ-তে প্রায়ই একটি অপশন থাকে “Compile error” বা “Runtime exception”. অনেকে এগুলো “ফাঁকা ঘর” ভেবে এড়িয়ে যান। ভুল। এগুলো প্রায়ই সঠিক উত্তর। তিনটির পার্থক্য পরিষ্কার রাখুন:

Compile error

javac কোডটি মানে না, তাই .class ফাইলই তৈরি হয় না। যেমন byte b = b + 1;, abstract class-এর object, ধরা হয়নি এমন checked exception.

প্রোগ্রাম চলেই না

Runtime exception

Compile হয়, কিন্তু চলার সময় JVM একটি exception ছোড়ে। উত্তরে নাম হুবহু চিনতে হয়: ArithmeticException, NullPointerException, ClassCastException, ConcurrentModificationException.

নাম জানতে হবে

নিশ্চিত নয়

Java-তে C-এর মতো undefined behavior খুব কম। কিন্তু HashSet-এর ক্রম, দুই thread-এর একসাথে লেখা, বা default toString()-এর hash মান — এগুলোর ফল নির্দিষ্ট নয়।

“ক্রম নিশ্চিত নয়” বৈধ উত্তর
মূল ধারণা

প্রশ্নে কোড থাকলে আউটপুট খোঁজার আগে দুটি প্রশ্ন করুন। এক, “এটি কি compile হবে?” — টাইপ সরু হচ্ছে কি (int থেকে byte), checked exception ধরা হয়েছে কি, final বদলানো হচ্ছে কি, private জিনিস বাইরে থেকে ছোঁয়া হচ্ছে কি? দুই, “চলার সময় কি exception?” — শূন্য দিয়ে ভাগ, null-এ method ডাকা, ভুল cast, লুপের ভেতরে collection বদলানো? দুটির কোনোটির উত্তর “হ্যাঁ” হলে সংখ্যা নিয়ে মাথা ঘামানোর দরকার নেই।

কৌশল ৩ · শব্দের ফাঁদ — “সব সময়”, “কখনো না”, “শুধু”

“কোনটি সত্য?” আর “কোনটি মিথ্যা?” প্রশ্নে চরম শব্দ খুঁজুন। “সব সময়”, “কখনো না”, “শুধু”, “নিশ্চিতভাবে” — এমন শব্দ একটি বাক্যকে খুব শক্ত দাবি বানায়, আর একটি ব্যতিক্রমই সেটিকে মিথ্যা করে দেয়। যেমন “System.gc() ডাকলে GC সব সময় সাথে সাথে চলে” — মিথ্যা, কারণ এটি শুধু অনুরোধ। “== দিয়ে দুটি Integer তুলনা কখনো true দেয় না” — এটিও মিথ্যা, কারণ ছোট মানে cache কাজ করে।

উল্টোটাও মনে রাখুন: “সাধারণত”, “বেশিরভাগ ক্ষেত্রে”, “গড়ে” শব্দওয়ালা বাক্য প্রায়ই সত্য — যেমন “HashMap-এর get গড়ে O(1)”. তবে এটি একটি ইঙ্গিত, নিয়ম নয়। শেষ সিদ্ধান্ত নিন বিষয়ের জ্ঞান দিয়ে।

“কোনটি মিথ্যা?” প্রশ্নে সবচেয়ে বেশি ভুল হয় তাড়াহুড়োয় — প্রথম সত্য বাক্যটি দেখেই সেটি বেছে ফেলা। প্রশ্নের “মিথ্যা” বা “ভুল” শব্দটির নিচে মনে মনে দাগ দিন, তারপর প্রতিটি বাক্যের পাশে “স” বা “মি” লিখে এগোন।

কৌশল ৪ · ভুলে নম্বর কাটলে কখন আন্দাজ করবেন

যেসব পরীক্ষায় ভুল উত্তরে নম্বর কাটে (negative marking), সেখানে আন্দাজ করা একটি হিসাবের প্রশ্ন। নিয়ম পরীক্ষাভেদে আলাদা, তাই নিজের পরীক্ষার নিয়ম আগে জেনে নিন। হিসাবটি সহজ: (ঠিক হওয়ার সম্ভাবনা × ১) − (ভুল হওয়ার সম্ভাবনা × কাটা নম্বর)। যেমন দুটি অপশন বাকি আর ভুলে ০.৫ কাটে: ০.৫ − ০.৫ × ০.৫ = +০.২৫. আবার কিছুই না জেনে চারটি থেকে আন্দাজ করলে আর ০.৫ কাটলে: ০.২৫ − ০.৭৫ × ০.৫ = −০.১২৫ — ক্ষতি। শিক্ষা পরিষ্কার: অন্তত দুটি অপশন নিশ্চিতভাবে বাদ দিতে পারলে আন্দাজ সাধারণত লাভজনক; কিছুই না জানলে আর কাটা নম্বর বেশি হলে ছেড়ে দিন।

কৌশল ৫ · সময় ভাগ করা

ধরুন ১০০টি প্রশ্ন ৬০ মিনিটে — প্রতিটির জন্য গড়ে ৩৬ সেকেন্ড। একটি inheritance-এর আউটপুট প্রশ্নেই দুই মিনিট চলে যেতে পারে। তাই দুই দফায় চলুন। প্রথম দফায় সংজ্ঞা, keyword, কমপ্লেক্সিটি, HTTP status-এর মতো সরাসরি প্রশ্ন দ্রুত শেষ করুন। কোড-ভারী প্রশ্নে দাগ দিয়ে এগিয়ে যান। দ্বিতীয় দফায় ফিরে এসে সেগুলো ধরুন। এক প্রশ্নে আটকে থেকে শেষের পাঁচটি সহজ প্রশ্ন না দেখা — MCQ পরীক্ষায় এটিই সবচেয়ে দামি ভুল।

এই পাতার প্রশ্নগুলো সম্পর্কে: প্রশ্নগুলো এ ধরনের পরীক্ষায় প্রায়ই আসে এমন ধারণা নিয়ে বানানো — কোনোটিই কোনো নির্দিষ্ট পরীক্ষার আসল প্রশ্ন নয়। প্রতিটি কোড-প্রশ্নের আউটপুট, compile error আর exception OpenJDK 21-এ চালিয়ে যাচাই করা। প্রশ্নের শুরুতে কঠিনতার মাত্রা দেওয়া আছে: (সহজ), (মাঝারি), (কঠিন)। কোড-প্রশ্নে ছোট অংশ দেখানো হলে ধরে নিন সেটি একটি সাধারণ main-এর ভেতরে আছে, আর দরকারি import (যেমন java.util.*) দেওয়া আছে।

C/C++/Python জানলে

C ও C++-এর MCQ-তে বড় অংশ জুড়ে থাকে undefined behavior আর প্ল্যাটফর্মভেদে আকার; Java-তে int সব জায়গায় ৩২ বিট, আর বেশিরভাগ ভুল একটি নির্দিষ্ট exception দেয় — তাই উত্তর বেশি নিশ্চিত। Python-এর is বনাম ==-এর ফাঁদ Java-তে আসে == বনাম equals হয়ে। একই ধাঁচের প্রশ্নব্যাংক আছে C++, Python আর C কোর্সে; যিনি এগুলো শেখেননি, তিনি এই বাক্সটি বাদ দিতে পারেন।

২ · ভিত্তি — JDK, JVM, bytecode আর প্রথম প্রোগ্রাম

এই অংশের প্রশ্ন সহজ মনে হয়, তাই সবাই তাড়াহুড়া করেন — আর ঠিক সেখানেই ভুল হয়। সবচেয়ে বেশি আসে: Java-র ইতিহাস, JDK, JRE আর JVM-এর সম্পর্ক, bytecode কে বানায় আর কে চালায়, আর JIT ও garbage collection-এর আসল কাজ।

(সহজ) Java ভাষা মূলত কোন প্রতিষ্ঠানে, কার নেতৃত্বে তৈরি হয়েছিল?

  • Bell Labs, Dennis Ritchie
  • Sun Microsystems, James Gosling
  • Oracle, Larry Ellison
  • Microsoft, Anders Hejlsberg

(সহজ) Java-র “Write once, run anywhere” কথাটি সম্ভব হয় মূলত কোন কারণে?

  • javac প্রতিটি অপারেটিং সিস্টেমের জন্য আলাদা machine code বানায়
  • Java প্রোগ্রাম সব সময় source কোড আকারে বিতরণ হয়
  • javac প্ল্যাটফর্ম-নিরপেক্ষ bytecode বানায়, আর প্রতিটি প্ল্যাটফর্মের JVM সেটি চালায়
  • Java অপারেটিং সিস্টেম ছাড়াই সরাসরি hardware-এ চলে

(সহজ) JDK, JRE আর JVM-এর সম্পর্ক কোনটি ঠিকভাবে বলে?

  • JDK-এর ভেতরে JRE, আর JRE-এর ভেতরে JVM
  • JVM-এর ভেতরে JRE, আর JRE-এর ভেতরে JDK
  • তিনটি সম্পূর্ণ আলাদা, কোনোটি অন্যটির অংশ নয়
  • JRE-তে javac থাকে, JDK-তে থাকে না

(সহজ) javac Hello.java সফল হলে কোন ফাইলটি তৈরি হয়?

  • Hello.exe
  • Hello.o
  • Hello.jar
  • Hello.class

(মাঝারি) HotSpot JVM-এর JIT compiler কী করে?

  • source কোড থেকে bytecode বানায়
  • প্রোগ্রাম চলার সময় বারবার চলা (hot) bytecode-কে native machine code-এ রূপান্তর করে
  • অপ্রয়োজনীয় object মুছে মেমরি ফেরত দেয়
  • .class ফাইল নিরাপদ কি না যাচাই করে

(মাঝারি) Java 21-এ (কোনো preview সুবিধা চালু না করে) java Main চালালে JVM কোন method-কে প্রোগ্রামের শুরু হিসেবে খোঁজে?

  • public static void main(String[] args)
  • public static int main(String[] args)
  • public void main(String[] args)
  • public static void Main(String[] args)

(মাঝারি) JVM-এর bytecode verifier-এর প্রধান কাজ কী?

  • bytecode-কে দ্রুত machine code-এ বদলানো
  • source কোডের বানান ও ব্যাকরণ যাচাই করা
  • লোড হওয়া class-এর bytecode নিয়ম মানে কি না, চালানোর আগে যাচাই করা
  • অব্যবহৃত class মেমরি থেকে সরানো

(মাঝারি) Java-র garbage collection নিয়ে কোনটি সত্য?

  • প্রোগ্রামার delete লিখে object মুছে দেন
  • System.gc() ডাকলে GC সব সময় সাথে সাথে চলে
  • reference-এর সংখ্যা শূন্য হওয়া মাত্র object মুছে যায়, তাই চক্রাকার reference কখনো মোছে না
  • যে object-এ আর পৌঁছানো যায় না, তার মেমরি GC ফেরত নেয় — কখন নেবে, তা JVM ঠিক করে

(কঠিন) নিচের কোন বাক্যটি মিথ্যা?

  • একই .class ফাইল Windows আর Linux-এর JVM-এ চলে
  • JVM নিজে প্ল্যাটফর্ম-নির্ভর একটি প্রোগ্রাম
  • Java কোড সব সময় শুধু interpret হয়, কখনো native code-এ যায় না
  • Kotlin-এর মতো অন্য ভাষাও JVM bytecode-এ compile হয়

(সহজ) JShell কী?

  • JDK-র সাথে আসা একটি REPL, যেখানে এক লাইন করে Java কোড চালিয়ে দেখা যায়
  • Java দিয়ে লেখা Linux-এর একটি terminal
  • IntelliJ-এর মতো একটি পূর্ণ IDE
  • jar ফাইল বানানোর টুল

(সহজ) একটি ফাইলে public class Student লেখা থাকলে ফাইলটির নাম কী হতে হবে?

  • student.java
  • Student.java
  • Student.class
  • যেকোনো নাম, শুধু এক্সটেনশন .java হলেই চলে

৩ · মূল ভাষা — টাইপ, অপারেটর, String, নিয়ন্ত্রণ, method আর array

এখানে ছোট একটি লাইনে অনেক নিয়ম লুকিয়ে থাকে — primitive type-এর আকার, numeric promotion, integer overflow, String জোড়ার ক্রম, String pool, Integer cache, switch-এর fall-through আর pass-by-value. প্রশ্নকর্তারা এই অংশ সবচেয়ে বেশি ভালোবাসেন, কারণ এক লাইনের কোডেই চারটি বিশ্বাসযোগ্য অপশন বানানো যায়। অংশের শেষে আছে regex-এর পাঁচটি প্রশ্ন — matches() বনাম find(), greedy বনাম reluctant, backslash, split আর বাংলা অঙ্ক।

(সহজ) Java-তে int-এর আকার কত?

  • ১৬ বিট
  • প্ল্যাটফর্মের ওপর নির্ভর করে
  • সব প্ল্যাটফর্মে ঠিক ৩২ বিট
  • ৬৪ বিট

(সহজ) Java-র char টাইপ সম্পর্কে কোনটি সত্য?

  • ৮ বিট, ASCII অক্ষর রাখে
  • ১৬ বিট, unsigned — একটি UTF-16 code unit
  • ১৬ বিট, signed
  • ৩২ বিট, যেকোনো Unicode অক্ষর এক char-এ

(মাঝারি) একটি class-এর field হিসেবে boolean flag; আর একটি method-এর ভেতরে local variable হিসেবে boolean ok; ঘোষণা করা হলো, কোথাও মান দেওয়া হয়নি। কোনটি সত্য?

  • দুটিরই ডিফল্ট মান false
  • দুটিরই ডিফল্ট মান null
  • দুটিতেই যেকোনো আবর্জনা মান থাকতে পারে
  • flag-এর মান false; ok মান না দিয়ে পড়লে compile error

(মাঝারি) byte b = 10; b = b + 1; — দ্বিতীয় লাইনে কী হয়?

  • Compile error — possible lossy conversion from int to byte
  • b = ১১
  • b = −১১৭, overflow
  • চলার সময় ArithmeticException

(সহজ) System.out.println(1 + 2 + "3" + 4 + 5); কী ছাপবে?

  • 15
  • 12345
  • 3345
  • 339

(মাঝারি) int x = 5; x = x++ + ++x; System.out.println(x); কী ছাপবে?

  • 11
  • 12
  • 13
  • Compile error

(মাঝারি) System.out.println(7 / 2 + " " + 7 % -3 + " " + -7 % 3); কী ছাপবে?

  • 3.5 1 -1
  • 3 -1 -1
  • 3 1 2
  • 3 1 -1

(মাঝারি) System.out.println(0.1 + 0.2 == 0.3); কী ছাপবে?

  • false
  • true
  • Compile error
  • ArithmeticException

(কঠিন) long big = 1_000_000 * 1_000_000; System.out.println(big); কী ছাপবে?

  • 1000000000000
  • Compile error — integer number too large
  • -727379968
  • ArithmeticException

উপরের পাঁচটি সংখ্যার প্রশ্ন একসাথে চালিয়ে দেখুন। কোডে কোনো লুকানো কৌশল নেই — প্রতিটি লাইন একটি প্রশ্নের উত্তর:

class Main {
    public static void main(String[] args) {
        System.out.println(1 + 2 + "3" + 4 + 5);
        int x = 5;
        x = x++ + ++x;
        System.out.println(x);
        System.out.println(7 / 2 + " " + 7 % -3 + " " + -7 % 3);
        System.out.println(0.1 + 0.2);
        long big = 1_000_000 * 1_000_000;          // গুণ হয় int-এ
        System.out.println(big + " " + 1_000_000L * 1_000_000);
        System.out.println('A' + 1);
        System.out.println((char) ('A' + 1));
        System.out.println((byte) 200 + " " + (int) -3.99 + " " + Math.round(-2.5));
    }
}

আউটপুট: 3345, 12, 3 1 -1, 0.30000000000000004, -727379968 1000000000000, 66, B, আর শেষে -56 -3 -2. শেষের তিনটি নতুন: 'A' + 1-এ char আগে int-এ ওঠে, তাই ৬৬ (অক্ষর নয়); cast করলে আবার অক্ষর B. (byte) 200 শুধু নিচের ৮ বিট রাখে — ২০০ − ২৫৬ = −৫৬। (int) -3.99 শূন্যের দিকে কাটে, তাই −৩, −৪ নয়। আর Math.round(-2.5) হলো −২, কারণ Java-র round আসলে “০.৫ যোগ করে নিচের দিকে নামানো” — floor(−২.০) = −২।

(কঠিন) Integer a = 127, b = 127, c = 128, d = 128; থাকলে System.out.println((a == b) + " " + (c == d)); ডিফল্ট JVM সেটিংয়ে কী ছাপবে?

  • true true
  • false false
  • false true
  • true false

(মাঝারি) String s = "abc"; s.toUpperCase(); System.out.println(s); কী ছাপবে?

  • ABC
  • abc
  • Compile error
  • NullPointerException

(কঠিন) নিচের কোড কী ছাপবে?

String s1 = "Java";
String s2 = "Ja" + "va";
String s3 = new String("Java");
System.out.println((s1 == s2) + " " + (s1 == s3) + " " + s1.equals(s3));
  • true false true
  • true true true
  • false false true
  • true false false

(মাঝারি) StringBuilder আর StringBuffer-এর মূল পার্থক্য কী?

  • StringBuilder immutable, StringBuffer mutable
  • শুধু StringBuffer-এ append আছে
  • StringBuffer-এর method synchronized (thread-safe), StringBuilder-এর নয় — তাই এক thread-এ StringBuilder দ্রুত
  • StringBuilder ব্যবহার করতে আলাদা লাইব্রেরি লাগে
class Main {
    public static void main(String[] args) {
        String s1 = "Java";
        String s2 = "Ja" + "va";            // compile-time constant
        String part = "Ja";
        String s3 = part + "va";            // চলার সময় তৈরি
        String s4 = new String("Java");
        System.out.println((s1 == s2) + " " + (s1 == s3) + " " + (s1 == s4));
        System.out.println(s1.equals(s4) + " " + (s1 == s3.intern()));
        String s = "abc";
        s.toUpperCase();
        System.out.println(s);
        Integer a = 127, b = 127, c = 128, d = 128;
        System.out.println((a == b) + " " + (c == d) + " " + c.equals(d));
        String n = null;
        n += "x";
        System.out.println(n);
    }
}

আউটপুট: true false false, true true, abc, true false true, nullx. লক্ষ করুন s3: part একটি সাধারণ ভ্যারিয়েবল (final নয়), তাই জোড়াটি চলার সময় হয়, আর নতুন object তৈরি হয় — s1 == s3 false. intern() pool থেকে একই লেখার object ফেরত দেয়, তাই তখন true. শেষ লাইনটি ফাঁদ: null-এর সাথে += দিয়ে String জোড়া NullPointerException দেয় না — null লেখা হিসেবে “null” বসে যায়। part-কে final String part = "Ja"; লিখলে সেটি compile-time constant হতো, আর s1 == s3 true হতো।

(মাঝারি) k = 2 হলে কী ছাপা হবে? (কোনো case-এ break নেই)

switch (k) {
    case 1: System.out.print("a");
    case 2: System.out.print("b");
    case 3: System.out.print("c");
    default: System.out.print("d");
}
  • b
  • bc
  • bcd
  • abcd

(মাঝারি) Java 14 থেকে স্থায়ী switch expression সম্পর্কে কোনটি সত্য?

  • arrow (->) লেখার পরও break না দিলে পরের case চলে
  • এটি একটি মান ফেরত দেয়, সব সম্ভাব্য মান ধরতে হয় (exhaustive), আর block থেকে মান দিতে yield লাগে
  • শুধু int-এর ওপর চলে
  • block থেকে মান দিতে return লেখা হয়

(কঠিন) নিচের কোড কী ছাপবে?

outer:
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        if (j == 2) continue outer;
        if (i == 2) break outer;
        System.out.print(i + "" + j + " ");
    }
}
  • 00 01 02 10 11 12
  • 00 01 10 11 20
  • 00 01
  • 00 01 10 11

(কঠিন) একটি class-এ তিনটি method আছে: m(long x), m(Integer x) আর m(int... x). m(5) ডাকলে কোনটি চলবে?

  • m(long x)
  • m(Integer x)
  • m(int... x)
  • Compile error — reference to m is ambiguous

(মাঝারি) নিচের কোড কী ছাপবে?

static void change(int[] a) {
    a[0] = 99;
    a = new int[]{7};
}
// main-এ:
int[] arr = {1, 2};
change(arr);
System.out.println(arr[0] + " " + arr.length);
  • 1 2
  • 7 1
  • 99 2
  • 99 1

(সহজ) int[] a = new int[3]; System.out.println(a[3]); চালালে কী হবে?

  • 0 ছাপবে
  • চলার সময় ArrayIndexOutOfBoundsException
  • Compile error
  • একটি এলোমেলো আবর্জনা মান

(মাঝারি) int z = 0; boolean ok = (z != 0) && (10 / z > 1); System.out.println(ok); কী ছাপবে?

  • ArithmeticException
  • true
  • Compile error
  • false

(মাঝারি) var সম্পর্কে নিচের কোন বাক্যটি মিথ্যা?

  • var দিয়ে ঘোষিত local variable-এর টাইপ compile-এর সময় ঠিক হয়
  • initializer ছাড়া var x; লেখা যায় না
  • var দিয়ে class-এর field ঘোষণা করা যায়
  • var পূর্ণ keyword নয়, তাই var var = 1; বৈধ

(সহজ) regex-এ matches() আর find() — কী ছাপা হবে?

System.out.println("abc123".matches("\\d+") + " "
    + Pattern.compile("\\d+").matcher("abc123").find());
  • true true
  • false true
  • false false
  • true false

(মাঝারি) greedy আর reluctant quantifier — কী ছাপা হবে?

System.out.println("aXbXc".replaceAll("a.*X", "-") + " "
    + "aXbXc".replaceAll("a.*?X", "-"));
  • -bXc -c
  • -c -c
  • -c -bXc
  • -bXc -bXc

(সহজ) regex-এ একটি backslash — কী ঘটবে?

System.out.println("2026".matches("\d{4}"));
  • true
  • false
  • চলার সময় PatternSyntaxException
  • Compile error: illegal escape character

(মাঝারি) split আর শেষের ফাঁকা টুকরো — কী ছাপা হবে?

System.out.println("1,2,,".split(",").length + " "
    + "1,2,,".split(",", -1).length);
  • 4 4
  • 2 4
  • 2 2
  • 3 4

(মাঝারি) বাংলা অঙ্কে \d — কী ছাপা হবে?

System.out.println("১২৩".matches("\\d+") + " " + "১২৩".matches("(?U)\\d+"));
  • true true
  • false false
  • false true
  • PatternSyntaxException

৪ · অবজেক্ট-ওরিয়েন্টেড Java — class, constructor, inheritance আর interface

OOP-এর প্রশ্ন দুই ধরনের। এক ধরনের প্রশ্ন পরিভাষা চায় — access modifier-এর তালিকা, abstract class বনাম interface, static আর final-এর নিয়ম। আরেক ধরনের প্রশ্ন ছোট কোড দিয়ে যাচাই করে কোন ডাক dynamic dispatch-এ যায় আর কোনটি যায় না — field, static method আর constructor থেকে ডাকা method. দ্বিতীয় ধরনটিতেই বেশি ভুল হয়।

modifierএকই classএকই packageঅন্য package-এর subclassঅন্য সব জায়গা
private✔✘✘✘
কিছু না লিখলে (package-private)✔✔✘✘
protected✔✔✔✘
public✔✔✔✔

(সহজ) Java-তে একটি সদস্য protected হলে কারা সেটি ব্যবহার করতে পারে?

  • শুধু নিজের class
  • একই package-এর সব class, আর অন্য package-এর subclass
  • শুধু একই package-এর class
  • যেকোনো class, যেকোনো জায়গা থেকে

(মাঝারি) একটি class-এ শুধু NoDef(int v) constructor লেখা আছে। অন্য জায়গায় new NoDef(); লিখলে কী হবে?

  • compiler-এর দেওয়া default constructor চলবে
  • v-এ ০ বসিয়ে constructor চলবে
  • চলার সময় NullPointerException
  • Compile error — constructor-টি এই argument-এ খাটে না

(মাঝারি) একটি class-এ instance field int count; আছে। public static void main-এর ভেতর থেকে সরাসরি System.out.println(count); লিখলে কী হবে?

  • Compile error — non-static variable cannot be referenced from a static context
  • 0 ছাপবে
  • চলার সময় NullPointerException
  • compiler নিজে একটি object বানিয়ে তার count ছাপবে

(মাঝারি) final সম্পর্কে নিচের কোন বাক্যটি মিথ্যা?

  • final class-কে extend করা যায় না
  • final method-কে override করা যায় না
  • final reference যে object দেখায়, তার ভেতরের অবস্থাও আর বদলানো যায় না
  • final field-এ ঠিক একবার মান দেওয়া যায়

(সহজ) একটি Java class সরাসরি কয়টি class-কে extends করতে পারে, আর কয়টি interface implements করতে পারে?

  • অনেকগুলো class, একটি interface
  • একটি class, অনেকগুলো interface
  • একটি class, একটি interface
  • দুটিই যত খুশি

(মাঝারি) class A { A() { System.out.print("A "); } } আর class B extends A { B() { System.out.print("B "); } } থাকলে new B(); কী ছাপবে?

  • B A
  • B
  • A B A
  • A B

(কঠিন) নিচের কোড কী ছাপবে?

class A { String name = "A"; String get() { return name; } }
class B extends A { String name = "B"; String get() { return name; } }
// main-এ:
A o = new B();
System.out.println(o.name + o.get());
  • AB
  • BB
  • AA
  • Compile error — duplicate field

(কঠিন) নিচের কোড কী ছাপবে?

class P { P() { show(); } void show() { System.out.println("P"); } }
class Q extends P {
    int v = 5;
    void show() { System.out.println("Q " + v); }
}
// main-এ:
new Q();
  • P
  • Q 5
  • Q 0
  • Compile error

(মাঝারি) class A { static String who() { return "A"; } }, class B extends A { static String who() { return "B"; } }. A o = new B(); System.out.println(o.who()); কী ছাপবে?

  • B
  • A
  • Compile error
  • NullPointerException
class A {
    String name = "A";
    A() { show(); }
    void show() { System.out.println("A.show"); }
    String get() { return name; }
    static String who() { return "static A"; }
}

class B extends A {
    String name = "B";
    int v = 5;
    @Override void show() { System.out.println("B.show v=" + v); }
    @Override String get() { return name; }
    static String who() { return "static B"; }
}

class Main {
    public static void main(String[] args) {
        A o = new B();
        System.out.println(o.name + " " + o.get());
        System.out.println(o.who());
        System.out.println(o instanceof B b ? b.name : "-");
    }
}

আউটপুট: B.show v=0, A B, static A, B. প্রথম লাইন আসে new B() থেকেই — A-এর constructor show() ডাকে, dynamic dispatch B-এর method-এ যায়, কিন্তু v তখনো ০। দ্বিতীয় লাইনে field আর method-এর পার্থক্য: field বাছাই হয় reference-এর টাইপ দেখে, method আসল object দেখে। তৃতীয় লাইনে static method — reference-এর টাইপ জেতে। শেষ লাইনে instanceof-এর pattern (B b) reference-কে B টাইপে দেখায়, তাই এবার B-এর field. মনে রাখুন: শুধু instance method override হয়; field, static method আর private method হয় না।

(মাঝারি) parent class-এ public void hello() আছে। subclass-এ void hello() (কোনো modifier ছাড়া) লিখে override করতে চাইলে কী হবে?

  • বৈধ override, method public থেকে যায়
  • নতুন একটি আলাদা method হিসেবে গণ্য হয়
  • চলার সময় IllegalAccessError
  • Compile error — attempting to assign weaker access privileges; was public

(মাঝারি) method overloading আর method overriding-এর পার্থক্য কোনটি ঠিক?

  • overloading বাছাই হয় compile-এর সময়, overriding বাছাই হয় চলার সময় আসল object দেখে
  • overloading বাছাই হয় চলার সময়, overriding compile-এর সময়
  • overloading-এ শুধু return type আলাদা হলেই চলে
  • overriding একই class-এর ভেতরে করা হয়

(মাঝারি) Java 21-এ abstract class আর interface নিয়ে কোনটি সত্য?

  • interface-এর কোনো method-এ body থাকতে পারে না
  • interface-এ instance field রাখা যায়, যা প্রতিটি object-এর আলাদা
  • abstract class-এ constructor আর instance field থাকতে পারে; interface-এর field নিজে থেকে public static final
  • abstract class-এ constructor রাখা যায় না

(মাঝারি) interface I আর J দুটিতেই default String hi() আছে। class Both implements I, J {} লিখলে কী হবে?

  • প্রথমে লেখা I-এর method জেতে
  • Compile error — class Both inherits unrelated defaults for hi() from types I and J
  • চলার সময় যেটি আগে লোড হয়, সেটি চলে
  • শেষে লেখা J-এর method জেতে

(সহজ) abstract class Shape { abstract double area(); } থাকলে Shape s = new Shape(); লিখলে কী হবে?

  • area() ০ ফেরত দেয় এমন একটি object তৈরি হবে
  • চলার সময় InstantiationException
  • compiler নিজে একটি subclass বানিয়ে নেবে
  • Compile error — Shape is abstract; cannot be instantiated

(মাঝারি) Object o = Integer.valueOf(1); String s = (String) o; — কী হবে?

  • compile হবে, চলার সময় ClassCastException
  • Compile error — incompatible types
  • s-এ “1” বসবে
  • s-এ null বসবে

৫ · আধুনিক টাইপ ও ভুল সামলানো — equals, enum, record, generics আর exception

এই অংশে দুটি বিষয় প্রায় প্রতিটি পরীক্ষা আর ইন্টারভিউতে আসে: equals-hashCode-এর চুক্তি, আর checked বনাম unchecked exception. নতুন Java-র প্রশ্নে আসে record, sealed class আর pattern matching; generics-এ সবচেয়ে কঠিন হলো invariance, wildcard আর type erasure.

(মাঝারি) equals আর hashCode-এর চুক্তি অনুযায়ী কোনটি বাধ্যতামূলক?

  • দুটি object-এর hashCode সমান হলে equals অবশ্যই true
  • প্রতিটি object-এর hashCode অনন্য হতে হবে
  • দুটি object equals-এ সমান হলে তাদের hashCode অবশ্যই সমান
  • hashCode সব সময় object-এর memory address

(মাঝারি) একটি class equals override করেছে, কিন্তু hashCode করেনি। সমান দুটি object-এর একটি HashSet-এ রেখে অন্যটি দিয়ে contains ডাকলে সাধারণত কী হয়?

  • সাধারণত false — কারণ ভুল bucket-এ খোঁজা হয়
  • সব সময় true — কারণ equals override করা আছে
  • Compile error
  • IllegalStateException

(সহজ) enum Color { RED, GREEN, BLUE } থাকলে Color.valueOf("GREEN").ordinal() + " " + Color.values().length কী দেয়?

  • 2 3
  • 1 3
  • 1 2
  • IllegalArgumentException

(মাঝারি) Java-র enum নিয়ে কোন বাক্যটি মিথ্যা?

  • enum-এ field, constructor আর method রাখা যায়
  • enum interface implement করতে পারে
  • enum constant == দিয়ে তুলনা করা নিরাপদ
  • enum নিজের পছন্দের যেকোনো class extend করতে পারে

(সহজ) record Point(int x, int y) {} থাকলে System.out.println(new Point(1, 2).equals(new Point(1, 2)) + " " + new Point(1, 2)); কী ছাপবে?

  • false Point[x=1, y=2]
  • true Point@1b6d3586
  • true Point[x=1, y=2]
  • true (1, 2)

(মাঝারি) record R(int x)-এর ভেতরে একটি method-এ x = 5; লিখলে কী হবে?

  • Compile error — cannot assign a value to final variable x
  • x বদলে ৫ হবে
  • চলার সময় UnsupportedOperationException
  • একটি নতুন local variable তৈরি হবে

(মাঝারি) sealed interface S permits Sq, Ci {} (দুটিই final class). return switch (s) { case Sq q -> "sq"; }; লিখলে কী হবে?

  • compile হবে, Ci এলে চলার সময় MatchException
  • Compile error — the switch expression does not cover all possible input values
  • compile হবে, Ci এলে null ফেরত দেবে
  • Compile error — pattern matching switch Java 21-এ নেই

(মাঝারি) Object obj = "hello"; if (obj instanceof String str && str.length() > 3) System.out.println(str.toUpperCase()); — কী হবে?

  • Compile error — str অচেনা
  • Compile error — cast লাগবে
  • কিছুই ছাপবে না
  • HELLO

(মাঝারি) List<Object> lo = new ArrayList<String>(); লিখলে কী হবে?

  • Compile error — incompatible types
  • বৈধ, কারণ String হলো Object-এর subclass
  • compile হবে, পরে ClassCastException
  • শুধু একটি unchecked warning আসবে

(মাঝারি) new ArrayList<String>().getClass() == new ArrayList<Integer>().getClass() — এর মান কী, আর কেন?

  • false — দুটি আলাদা class
  • Compile error
  • true — type erasure-এর কারণে চলার সময় দুটিই ArrayList
  • নিশ্চিত নয়, JVM-এর ওপর নির্ভর করে

(কঠিন) একটি method যেকোনো list-এ কিছু Integer যোগ করবে — List<Integer>, List<Number> বা List<Object>. প্যারামিটারের টাইপ কী হওয়া উচিত?

  • List<? extends Integer>
  • List<? super Integer>
  • List<Integer>
  • List<?>

(সহজ) নিচের কোনটি checked exception?

  • NullPointerException
  • ArithmeticException
  • IllegalArgumentException
  • IOException

(মাঝারি) try { ... } catch (Exception e) { } catch (RuntimeException e) { } — এই ক্রমে catch লিখলে কী হবে?

  • Compile error — exception RuntimeException has already been caught
  • বৈধ; RuntimeException এলে দ্বিতীয় catch চলবে
  • শুধু warning আসবে
  • চলার সময় IllegalStateException

(মাঝারি) static int f() { try { return 1; } finally { System.out.println("finally"); } } — System.out.println(f()); কী ছাপবে?

  • শুধু 1
  • 1, তারপর finally
  • finally, তারপর 1
  • Compile error

(মাঝারি) try (Res a = new Res("A"); Res b = new Res("B")) { ... } — block শেষে resource দুটি কোন ক্রমে বন্ধ হয়?

  • আগে A, তারপর B
  • আগে B, তারপর A
  • কখন বন্ধ হবে, GC ঠিক করে
  • শুধু exception এলে বন্ধ হয়
import java.util.ArrayList;

record Point(int x, int y) {}

enum Size { SMALL, MEDIUM, LARGE }

class Res implements AutoCloseable {
    private final String n;
    Res(String n) { this.n = n; System.out.println("open " + n); }
    @Override public void close() { System.out.println("close " + n); }
}

class Main {
    static int f() {
        try { return 1; } finally { System.out.println("finally"); }
    }
    public static void main(String[] args) {
        System.out.println(new Point(1, 2).equals(new Point(1, 2)) + " " + new Point(1, 2));
        System.out.println(Size.valueOf("MEDIUM").ordinal() + " " + Size.values().length);
        System.out.println(f());
        try (Res a = new Res("A"); Res b = new Res("B")) {
            System.out.println("body");
        }
        System.out.println(new ArrayList<String>().getClass() == new ArrayList<Integer>().getClass());
    }
}

আউটপুট পরপর: true Point[x=1, y=2], 1 3, finally, 1, open A, open B, body, close B, close A, true. এই অংশের পাঁচটি প্রশ্নের উত্তর এক জায়গায়: record-এর মান-ভিত্তিক equals ও toString, enum-এর শূন্য থেকে গোনা ordinal, return-এর আগে finally, উল্টো ক্রমে close, আর type erasure. Res-এর close() কোনো checked exception ঘোষণা করেনি, তাই main-এ throws লাগেনি — AutoCloseable.close() নিজে throws Exception ঘোষণা করে, override-এ সেটি বাদ দেওয়া যায়।

৬ · Collections ও functional Java — List, Map, Comparator, lambda, stream আর Optional

Collections-এর প্রশ্নে তিনটি জিনিস জানতে হয়: কোন collection কোন কাজে কত দ্রুত (Big-O), কোনটি ক্রম রাখে আর কোনটি রাখে না, আর কোন কাজ চলার সময় exception দেয় — unmodifiable collection-এ add, বা লুপের ভেতরে list বদলানো। Stream-এর প্রশ্নের মূল চাবি একটিই: intermediate operation অলস, terminal operation না এলে কিছুই চলে না।

collectionখোঁজা / পাওয়াযোগ করাক্রম
ArrayListget(i) O(1), contains O(n)শেষে গড়ে O(1), মাঝে O(n)ঢোকানোর ক্রম
LinkedListget(i) O(n)দুই প্রান্তে O(1)ঢোকানোর ক্রম
HashMap / HashSetগড়ে O(1)গড়ে O(1)নিশ্চিত নয়
LinkedHashMapগড়ে O(1)গড়ে O(1)ঢোকানোর ক্রম
TreeMap / TreeSetO(log n)O(log n)সাজানো (key অনুযায়ী)
PriorityQueuepeek O(1)offer/poll O(log n)শুধু মাথায় সবচেয়ে ছোটটি

(সহজ) ১০ লাখ উপাদানের list-এ বারবার get(i) দিয়ে মাঝের উপাদান পড়তে হবে। কোনটি ভালো, আর কেন?

  • LinkedList, কারণ get(i) O(1)
  • ArrayList, কারণ get(i) O(1)
  • HashSet, কারণ খোঁজা O(1)
  • দুটিই সমান

(মাঝারি) List<Integer> l = List.of(1, 2); l.add(3); — কী হবে?

  • l হবে [1, 2, 3]
  • Compile error
  • IndexOutOfBoundsException
  • চলার সময় UnsupportedOperationException

(মাঝারি) List<Integer> l = new ArrayList<>(List.of(1, 2, 3)); for (Integer i : l) if (i == 1) l.remove(i); — কী হবে?

  • চলার সময় ConcurrentModificationException
  • l হবে [2, 3], কোনো সমস্যা নেই
  • Compile error
  • l হবে [1, 3]

(মাঝারি) একটি HashSet<String>-এ “banana”, “apple”, “cherry” — এই ক্রমে যোগ করে for-each দিয়ে ছাপালে কোন ক্রমে আসবে?

  • ঢোকানোর ক্রমে — banana, apple, cherry
  • বর্ণানুক্রমে — apple, banana, cherry
  • ক্রম নিশ্চিত নয় — hash-এর ওপর নির্ভর করে
  • উল্টো ক্রমে — cherry, apple, banana

(মাঝারি) Map<String, Integer> m = new HashMap<>(); System.out.println(m.put("k", 1) + " " + m.put("k", 2) + " " + m.get("k")); কী ছাপবে?

  • 1 2 2
  • null 1 2
  • null 1 1
  • IllegalStateException

(মাঝারি) PriorityQueue<Integer> pq = new PriorityQueue<>(List.of(5, 1, 4, 2)); থেকে খালি না হওয়া পর্যন্ত poll() করে ছাপালে ক্রম কী?

  • 5 1 4 2
  • 5 4 2 1
  • ক্রম নিশ্চিত নয়
  • 1 2 4 5

(সহজ) Deque<Integer> st = new ArrayDeque<>(); st.push(1); st.push(2); st.push(3); System.out.println(st.pop() + " " + st.peek()); কী ছাপবে?

  • 3 2
  • 1 2
  • 3 3
  • 3 1

(মাঝারি) Comparable আর Comparator-এর পার্থক্য কোনটি ঠিক?

  • Comparable-এর method compare(a, b), Comparator-এর compareTo(o)
  • Comparator ব্যবহার করতে class-টিকে নিজে বদলাতে হয়
  • Comparable class-এর নিজের স্বাভাবিক ক্রম (compareTo); Comparator বাইরের আলাদা নিয়ম (compare), যত খুশি বানানো যায়
  • দুটিই equals-এর বিকল্প

(মাঝারি) ["pear", "fig", "apple", "kiwi"] list-কে Comparator.comparing(String::length).thenComparing(Comparator.naturalOrder()) দিয়ে sort করলে ফল কী?

  • [apple, fig, kiwi, pear]
  • [fig, kiwi, pear, apple]
  • [fig, pear, kiwi, apple]
  • [apple, kiwi, pear, fig]
import java.util.*;

class Main {
    public static void main(String[] args) {
        List<Integer> a = new ArrayList<>(List.of(10, 20, 30));
        a.remove(1);                              // index 1
        List<Integer> b = new ArrayList<>(List.of(10, 20, 30));
        b.remove(Integer.valueOf(10));            // মান 10
        System.out.println(a + " " + b);
        Map<String, Integer> m = new HashMap<>();
        System.out.println(m.put("k", 1) + " " + m.put("k", 2) + " " + m.get("k"));
        PriorityQueue<Integer> pq = new PriorityQueue<>(List.of(5, 1, 4, 2));
        StringBuilder out = new StringBuilder();
        while (!pq.isEmpty()) out.append(pq.poll()).append(' ');
        System.out.println(out.toString().strip());
        Deque<Integer> st = new ArrayDeque<>();
        st.push(1); st.push(2); st.push(3);
        System.out.println(st.pop() + " " + st.peek());
        List<String> w = new ArrayList<>(List.of("pear", "fig", "apple", "kiwi"));
        w.sort(Comparator.comparing(String::length).thenComparing(Comparator.naturalOrder()));
        System.out.println(w + " " + new TreeMap<>(Map.of("b", 2, "a", 1)));
    }
}

আউটপুট: [10, 30] [20, 30], null 1 2, 1 2 4 5, 3 2, আর [fig, kiwi, pear, apple] {a=1, b=2}. প্রথম লাইনটি শুরুর ডায়াগ্রামের প্রশ্ন — remove(1) index ধরে, remove(Integer.valueOf(10)) মান ধরে। শেষে TreeMap key সাজিয়ে রাখে, তাই Map.of-এর এলোমেলো ক্রম থাকলেও ছাপা হয় {a=1, b=2}. এখানে ইচ্ছা করে HashMap বা HashSet ছাপানো হয়নি — তাদের ক্রম নিশ্চিত নয়।

(সহজ) functional interface-এর সংজ্ঞা কোনটি?

  • যে interface-এ কোনো default method নেই
  • যে interface-এ @FunctionalInterface annotation বাধ্যতামূলক
  • যে interface-এ অন্তত দুটি abstract method আছে
  • যে interface-এ ঠিক একটি abstract method আছে

(মাঝারি) java.util.function-এর কোন interface একটি মান নিয়ে boolean ফেরত দেয়?

  • Predicate<T>
  • Function<T, R>
  • Consumer<T>
  • Supplier<T>

(মাঝারি) int n = 5; Runnable r = () -> System.out.println(n); n++; — কী হবে?

  • compile হবে, r.run() ৫ ছাপবে
  • compile হবে, r.run() ৬ ছাপবে
  • Compile error — local variables referenced from a lambda expression must be final or effectively final
  • চলার সময় IllegalStateException

(মাঝারি) Stream.of(1, 2, 3).peek(System.out::print).map(x -> x * 2); — শুধু এই লাইনটি চালালে কী ছাপা হবে?

  • 123
  • কিছুই না
  • 246
  • IllegalStateException

(মাঝারি) Stream<Integer> s = Stream.of(1, 2); s.count(); s.count(); — দ্বিতীয় count()-এ কী হয়?

  • আবার ২ দেয়
  • ০ দেয়
  • Compile error
  • IllegalStateException

(সহজ) Stream.of("a", "bb", "ccc").filter(s -> s.length() > 1).map(String::length).toList() — ফল কী?

  • [2, 3]
  • [bb, ccc]
  • [1, 2, 3]
  • Compile error — toList() নেই

(মাঝারি) Optional নিয়ে কোনটি সত্য?

  • Optional.of(null) একটি খালি Optional দেয়
  • orElse(x)-এর x শুধু Optional খালি হলে হিসাব হয়
  • Optional.ofNullable(null).map(String::valueOf).orElse("none") দেয় “none”
  • Optional সব field আর প্যারামিটারে ব্যবহারের জন্যই বানানো
import java.util.*;
import java.util.stream.*;

class Main {
    static void attempt(String label, Runnable r) {
        try {
            r.run();
            System.out.println(label + ": ok");
        } catch (RuntimeException e) {
            System.out.println(label + ": " + e.getClass().getSimpleName());
        }
    }
    public static void main(String[] args) {
        Stream.of(1, 2, 3).peek(System.out::print).map(x -> x * 2);   // terminal নেই
        System.out.println("[peek printed nothing]");
        System.out.println(Stream.of("a", "bb", "ccc").filter(s -> s.length() > 1).map(String::length).toList());
        attempt("List.of add", () -> List.of(1, 2).add(3));
        attempt("for-each remove", () -> {
            List<Integer> l = new ArrayList<>(List.of(1, 2, 3));
            for (Integer i : l) if (i == 1) l.remove(i);
        });
        attempt("stream reuse", () -> { Stream<Integer> s = Stream.of(1); s.count(); s.count(); });
        attempt("Optional.of(null)", () -> Optional.of(null));
        attempt("Map.get unbox", () -> { int v = new HashMap<String, Integer>().get("x"); });
    }
}

আউটপুট: প্রথম লাইন [peek printed nothing] — তার আগে কিছুই ছাপা হয়নি, কারণ পাইপলাইনে terminal operation নেই। তারপর [2, 3], আর পাঁচটি চেষ্টার ফল: UnsupportedOperationException, ConcurrentModificationException, IllegalStateException, NullPointerException, NullPointerException. শেষেরটি নতুন ফাঁদ: Map.get না পেলে null দেয়, আর int-এ বসাতে গিয়ে auto-unboxing null-এ intValue() ডাকে। exception-গুলো ধরে শুধু class-এর নাম ছাপানো হয়েছে, যাতে আউটপুট সব সময় একই থাকে।

৭ · সিস্টেম ও JVM — ফাইল, তারিখ, serialization, thread আর মেমরি

এই অংশের প্রশ্নে সংস্করণের তথ্য জরুরি: java.nio.file (Java 7), java.time (Java 8), Metaspace (Java 8), virtual thread (Java 21-এ স্থায়ী)। Thread-এর প্রশ্নে সবচেয়ে বেশি আসে start() বনাম run(), synchronized বনাম volatile, আর deadlock-এর শর্ত। শেষে নেটওয়ার্কিংয়ের তিনটি প্রশ্ন — TCP বনাম UDP, socket-এর timeout আর HttpClient-এর ডিফল্ট আচরণ।

(সহজ) java.nio.file দিয়ে একটি ছোট টেক্সট ফাইলের সব লাইন একটি List<String>-এ পড়তে কোনটি ব্যবহার হয়?

  • Path.readLines(path)
  • Files.readAllLines(path)
  • Scanner.readAll(path)
  • new File(path).lines()

(মাঝারি) Files.lines(path) একটি Stream<String> দেয়। এটি ব্যবহারের সঠিক উপায় কোনটি?

  • এটি সাথে সাথে পুরো ফাইল মেমরিতে পড়ে, তাই বন্ধ করার দরকার নেই
  • GC নিজে থেকেই সাথে সাথে ফাইল বন্ধ করে দেয়
  • terminal operation-এর পরে ফাইলটি মুছে যায়
  • try-with-resources-এর ভেতরে রেখে ব্যবহার করা, যাতে ফাইল বন্ধ হয়

(সহজ) শুধু একটি তারিখ (যেমন জন্মদিন) রাখতে হবে — সময় বা time zone ছাড়া। java.time-এর কোন টাইপ?

  • LocalDate
  • LocalDateTime
  • Instant
  • ZonedDateTime

(মাঝারি) System.out.println(LocalDate.of(2024, 1, 31).plusMonths(1)); কী ছাপবে?

  • 2024-02-31
  • 2024-03-02
  • 2024-02-29
  • DateTimeException

(মাঝারি) LocalDate d = LocalDate.of(2025, 3, 10); d.plusDays(1); System.out.println(d); কী ছাপবে?

  • 2025-03-11
  • 2025-03-10
  • Compile error
  • 2025-04-10

(মাঝারি) Duration আর Period-এর পার্থক্য কোনটি?

  • Duration mutable, Period immutable
  • Duration তারিখভিত্তিক (বছর-মাস-দিন), Period সময়ভিত্তিক
  • দুটি একই জিনিস, Period পুরোনো নাম
  • Duration সময়ভিত্তিক (ঘণ্টা-মিনিট-সেকেন্ড), Period তারিখভিত্তিক (বছর-মাস-দিন)
import java.time.*;

class Main {
    public static void main(String[] args) {
        LocalDate d = LocalDate.of(2025, 3, 10);
        d.plusDays(1);                       // ফল ফেলে দেওয়া হলো
        System.out.println(d);
        System.out.println(LocalDate.of(2024, 1, 31).plusMonths(1));
        System.out.println(LocalDate.of(2023, 1, 31).plusMonths(1));
        System.out.println(Duration.ofMinutes(90) + " " + Period.of(1, 2, 3));
        System.out.println(LocalDate.of(2024, 3, 1).minusDays(1).getDayOfMonth());
        System.out.println(Period.between(LocalDate.of(2024, 1, 15), LocalDate.of(2024, 3, 10)));
        try {
            LocalDate.of(2023, 2, 29);
        } catch (DateTimeException e) {
            System.out.println(e.getClass().getSimpleName());
        }
    }
}

আউটপুট: 2025-03-10, 2024-02-29, 2023-02-28, PT1H30M P1Y2M3D, 29, P1M24D, DateTimeException. লক্ষ করুন Period.between: ১৫ জানুয়ারি থেকে ১৫ ফেব্রুয়ারি এক মাস, তারপর ১০ মার্চ পর্যন্ত ২৪ দিন (২০২৪-এর ফেব্রুয়ারি ২৯ দিনের)। আর অধিবর্ষ নয় এমন বছরে ২৯ ফেব্রুয়ারি সরাসরি বানাতে গেলে exception — কিন্তু plusMonths নিজে থেকে শেষ বৈধ দিনে থামে।

(মাঝারি) একটি Serializable class-এর field transient String password;. object-টি serialize করে আবার deserialize করলে password-এ কী থাকবে?

  • null
  • আগের মানটিই
  • NotSerializableException
  • এনক্রিপ্ট করা মান

(সহজ) Thread t = new Thread(task); তৈরির পর t.start()-এর বদলে t.run() ডাকলে কী হয়?

  • একটি নতুন thread-এ task চলে
  • Compile error
  • কোনো নতুন thread তৈরি হয় না; task বর্তমান thread-এই চলে
  • IllegalThreadStateException

(মাঝারি) একটি shared volatile int count-কে দুটি thread ১০,০০০ বার করে count++ করল (কোনো lock ছাড়া)। শেষে count সম্পর্কে কোনটি ঠিক?

  • নিশ্চিতভাবে ২০,০০০, কারণ volatile আছে
  • ২০,০০০ বা তার কম — race condition, প্রতিবার আলাদা হতে পারে
  • ConcurrentModificationException
  • নিশ্চিতভাবে ১০,০০০

(মাঝারি) Thread A lock X ধরে lock Y চায়, আর Thread B lock Y ধরে lock X চায়। এই deadlock এড়ানোর সবচেয়ে সরল উপায় কোনটি?

  • thread-এর priority বাড়ানো
  • lock-এর বদলে field-গুলো volatile করা
  • lock নেওয়ার আগে Thread.sleep() দেওয়া
  • সব thread-কে একই ক্রমে lock নিতে বাধ্য করা (যেমন সবসময় আগে X, তারপর Y)

(মাঝারি) একটি instance method-এ synchronized লিখলে সেটি কোন lock ব্যবহার করে?

  • যে object-এর ওপর method ডাকা হয়েছে, তার (this-এর) lock
  • পুরো JVM-এর একটি সাধারণ lock
  • class-এর Class object-এর lock
  • কোনো lock নয়, শুধু CPU cache খালি করে

(মাঝারি) ExecutorService-এ submit(callable) ডাকলে কী ফেরত আসে?

  • কাজ শেষ হওয়া পর্যন্ত অপেক্ষা করে ফলটি সরাসরি
  • একটি নতুন Thread object
  • একটি Future, যার get() দিয়ে পরে ফল নেওয়া যায়
  • কিছুই না (void)

(মাঝারি) Java 21-এর virtual thread নিয়ে কোন বাক্যটি মিথ্যা?

  • একসাথে লাখ লাখ virtual thread চালানো সম্ভব
  • virtual thread CPU-ভারী হিসাবকে কয়েক গুণ দ্রুত করে
  • virtual thread অল্প কয়েকটি carrier thread-এর ওপর চলে
  • virtual thread pool করে রাখার দরকার নেই

(মাঝারি) একটি method-এর ভেতরে int n = 5; Student s = new Student();. JVM মেমরিতে কোনটি কোথায় থাকে (escape analysis-এর মতো অপ্টিমাইজেশন বাদ দিয়ে)?

  • সবকিছু stack-এ
  • সবকিছু heap-এ
  • n stack-এ, Student object Metaspace-এ
  • n আর reference s stack-এ; Student object heap-এ

(মাঝারি) একটি নিজের বানানো annotation চলার সময় reflection দিয়ে পড়তে হবে। তার retention policy কী হতে হবে?

  • RetentionPolicy.RUNTIME
  • RetentionPolicy.SOURCE
  • RetentionPolicy.CLASS
  • RetentionPolicy.REFLECT

(সহজ) TCP আর UDP নিয়ে কোন বাক্যটি সঠিক?

  • TCP প্রতিটি write-কে আলাদা message হিসেবে পৌঁছে দেয়, তাই framing লাগে না
  • UDP সংযোগভিত্তিক আর নির্ভরযোগ্য, তাই DNS-এ ব্যবহার হয়
  • TCP নির্ভরযোগ্য, ক্রম-ঠিক byte-স্রোত কিন্তু message-এর সীমানা রাখে না; UDP-র প্রতিটি datagram আলাদা message, তবে হারাতে বা উল্টো ক্রমে আসতে পারে
  • Java-তে TCP-র জন্য DatagramSocket আর UDP-র জন্য ServerSocket

(মাঝারি) একটি client Socket-এ setSoTimeout(2000) দেওয়া আছে। সার্ভার সংযোগ খোলা রেখে ২ সেকেন্ড কিছুই পাঠাল না। client-এর read() কী করবে?

  • -1 ফেরত দেবে
  • চিরকাল অপেক্ষা করবে
  • SocketTimeoutException ছুড়বে
  • ConnectException: Connection refused ছুড়বে

(মাঝারি) Java 21-এ HttpClient.newHttpClient() দিয়ে GET পাঠানো হলো। একটি request-এ সার্ভার 301 দিল, আরেকটিতে 404. দুই ক্ষেত্রে send কী করে?

  • 301-এ নিজে থেকে নতুন ঠিকানায় যায়; 404-এ IOException ছোড়ে
  • দুই ক্ষেত্রেই exception ছাড়া উত্তর ফেরত দেয় — statusCode() একটিতে 301, অন্যটিতে 404
  • 301-এ RedirectException, 404-এ FileNotFoundException
  • দুই ক্ষেত্রেই সফল না হওয়া পর্যন্ত একই request আবার পাঠায়

৮ · পেশাদার Java — Maven, JUnit, design pattern, JDBC, Spring, REST আর অ্যালগরিদম

এই অংশের প্রশ্ন সাধারণত কোড চালানো নয়, পরিভাষা আর সিদ্ধান্তের: Maven-এর build lifecycle আর dependency scope, JUnit 5-এর annotation, কোন সমস্যায় কোন design pattern, PreparedStatement কেন, Spring-এর bean scope, আর HTTP-এর method ও status code. শেষে কয়েকটি অ্যালগরিদমের কমপ্লেক্সিটি, আর JPA ও Spring Security-র প্রশ্ন — fetch type, N+1, transaction-এর rollback, optimistic locking, 401 বনাম 403, পাসওয়ার্ড hash, CSRF আর JWT. মনে রাখুন, Spring, JUnit বা JDBC driver Wandbox-এ নেই, তাই এই অংশের তথ্য সংশ্লিষ্ট পর্ব আর অফিসিয়াল ডকুমেন্টেশনের সাথে মিলিয়ে লেখা।

(সহজ) Maven প্রজেক্টে mvn package চালালে কী ঘটে?

  • শুধু jar বানায়, compile বা test চালায় না
  • jar বানিয়ে local repository-তে install করে
  • আগে validate, compile আর test চলে, তারপর jar (বা war) তৈরি হয়
  • jar বানিয়ে remote repository-তে পাঠায়

(মাঝারি) pom.xml-এ JUnit-এর dependency কোন scope-এ রাখা উচিত?

  • test
  • compile
  • provided
  • runtime

(সহজ) JUnit 5-এ প্রতিটি @Test method-এর আগে একবার করে চলে এমন method-এ কোন annotation দেওয়া হয়?

  • @Before
  • @BeforeAll
  • @Setup
  • @BeforeEach

(মাঝারি) JUnit 5-এ “parse("abc") ডাকলে NumberFormatException আসবে” — এটি যাচাইয়ের সঠিক উপায় কোনটি?

  • assertEquals(NumberFormatException.class, parse("abc"));
  • assertThrows(NumberFormatException.class, () -> parse("abc"));
  • assertTrue(parse("abc"));
  • @Test(expected = NumberFormatException.class)

(মাঝারি) new BufferedReader(new FileReader("a.txt")) — একটি reader-কে আরেকটি reader দিয়ে মুড়ে নতুন সুবিধা (buffer, readLine) যোগ করা কোন design pattern?

  • Singleton
  • Observer
  • Decorator
  • Factory Method

(মাঝারি) list.sort(comparator)-এ কোন নিয়মে সাজানো হবে, তা বাইরে থেকে একটি object দিয়ে পাঠানো হয়। এটি কোন design pattern-এর উদাহরণ?

  • Strategy
  • Adapter
  • Builder
  • Proxy

(মাঝারি) JDBC-তে Statement-এ String জোড়া দিয়ে SQL বানানোর বদলে PreparedStatement ব্যবহারের প্রধান কারণ কী?

  • ডেটাবেস সংযোগের প্রয়োজন হয় না
  • ফলাফল JSON আকারে আসে
  • শুধু PreparedStatement-এ transaction চলে
  • ? placeholder-এ মান আলাদাভাবে যায়, তাই SQL injection ঠেকে

(মাঝারি) টাকা পাঠানোয় দুটি UPDATE (একজনের কাটা, আরেকজনের যোগ) — হয় দুটিই হবে, নয় একটিও না। JDBC-তে কোনটি সঠিক?

  • auto-commit চালু রেখে দুটি UPDATE চালানো
  • setAutoCommit(false), দুটি UPDATE, সফল হলে commit(), ব্যর্থ হলে rollback()
  • দুটি UPDATE দুটি আলাদা connection-এ চালানো
  • দুটিই executeQuery দিয়ে চালানো

(মাঝারি) Spring-এ কোনো scope উল্লেখ না করে @Service দিয়ে একটি bean বানালে তার ডিফল্ট scope কী?

  • prototype
  • request
  • singleton
  • session

(মাঝারি) Spring-এ field-এ @Autowired দেওয়ার চেয়ে constructor injection-কে কেন বেশি সুপারিশ করা হয়?

  • dependency final রাখা যায়, আর টেস্টে Spring ছাড়াই object বানানো যায়
  • এটি চলার সময় অনেক দ্রুত
  • এতে Spring container-এর দরকারই পড়ে না
  • field injection Spring Boot 3-এ বাদ দেওয়া হয়েছে

(সহজ) REST API-তে POST /students সফলভাবে নতুন একটি student তৈরি করলে কোন HTTP status code সবচেয়ে উপযুক্ত?

  • 200 OK
  • 204 No Content
  • 302 Found
  • 201 Created

(মাঝারি) কোন HTTP method idempotent নয় — অর্থাৎ একই request দুবার পাঠালে ফল একবার পাঠানোর মতো নাও হতে পারে?

  • GET
  • POST
  • PUT
  • DELETE

(মাঝারি) ব্যবহারকারী লগইন করেছেন, কিন্তু অন্য একজনের তথ্য দেখতে চাইছেন যার অনুমতি তাঁর নেই। সার্ভারের সঠিক status code কোনটি?

  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 500 Internal Server Error

(সহজ) ১০ লাখ উপাদানের সাজানো array-তে binary search করলে সবচেয়ে খারাপ ক্ষেত্রে মোটামুটি কতবার তুলনা লাগে?

  • প্রায় ২০
  • প্রায় ১,০০০
  • প্রায় ৫ লাখ
  • প্রায় ১০ লাখ

(মাঝারি) Java-র sort নিয়ে কোনটি সত্য?

  • সব sort ভেতরে bubble sort, O(n²)
  • Collections.sort unstable — সমান উপাদানের ক্রম এলোমেলো হতে পারে
  • Arrays.sort একটি নতুন সাজানো array ফেরত দেয়
  • object-এর sort (List.sort, Collections.sort) stable, O(n log n)

(মাঝারি) ওজনহীন (unweighted) একটি graph-এ এক node থেকে অন্য node-এ সবচেয়ে কম ধাপের পথ বের করতে কোনটি ব্যবহার হয়, আর তাতে কোন data structure লাগে?

  • DFS, stack দিয়ে
  • BFS, queue দিয়ে
  • Dijkstra, ওজনহীন graph-এ বাধ্যতামূলক
  • binary search, সাজানো array দিয়ে

(সহজ) JPA মানক অনুযায়ী কোন দুটি সম্পর্কের ডিফল্ট fetch type EAGER?

  • @OneToMany আর @ManyToMany
  • @ManyToOne আর @OneToOne
  • সব সম্পর্ক
  • কোনোটিই নয় — সব সম্পর্ক ডিফল্টে LAZY

(মাঝারি) একটি transaction-এ orderRepo.findAll() ৫০টি অর্ডার আনল। প্রতিটির গ্রাহক আলাদা, সম্পর্ক @ManyToOne(fetch = FetchType.LAZY), batch fetching বন্ধ। তারপর লুপে প্রতিটি অর্ডারের getCustomer().getName() ডাকা হলো। মোট কয়টি SELECT যাবে?

  • ১টি
  • ২টি
  • ৫০টি
  • ৫১টি

(কঠিন) Spring-এর একটি public @Transactional service method (ডিফল্ট সেটিং) repository থেকে একটি Product এনে setStock(0) করল, তারপর checked exception IOException ছুড়ল। method বাইরে থেকে ডাকা হয়েছে। transaction-এর কী হবে?

  • rollback — যেকোনো exception-এ Spring rollback করে
  • commit — stock 0 টেবিলে লেখা হয়ে যায়
  • কিছুই লেখা হয় না, কারণ save() ডাকা হয়নি
  • compile error — @Transactional method checked exception ছুড়তে পারে না

(মাঝারি) @Version থাকা একটি entity-র একই সারি দুটি transaction version 3 অবস্থায় পড়ল। প্রথমটি বদলে commit করল। দ্বিতীয়টি এখন নিজের বদল commit করতে গেলে কী হয়?

  • দ্বিতীয়টির লেখা জিতে যায়, প্রথমটির বদল হারায়
  • OptimisticLockException (Spring-এ সাধারণত ObjectOptimisticLockingFailureException), আর rollback
  • দ্বিতীয়টি পড়ার সময়েই প্রথমটি শেষ হওয়া পর্যন্ত আটকে ছিল
  • Hibernate দুটি বদল মিলিয়ে একটি নতুন মান লেখে

(সহজ) একটি token-ভিত্তিক REST API-তে (Spring Security) সঠিক token দিয়ে লগইন করা একজন সাধারণ ব্যবহারকারী শুধু ADMIN-এর endpoint ডাকলেন, আর আরেকজন কোনো token ছাড়াই একই endpoint ডাকলেন। দুজন কোন status পাবেন?

  • দুজনই 403
  • দুজনই 401
  • লগইন করা ব্যবহারকারী 403, token ছাড়া জন 401
  • লগইন করা ব্যবহারকারী 401, token ছাড়া জন 403

(মাঝারি) ব্যবহারকারীর পাসওয়ার্ড সংরক্ষণে BCrypt কেন SHA-256-এর চেয়ে ভালো?

  • BCrypt-এর hash বেশি লম্বা, তাই অনুমান করা কঠিন
  • BCrypt প্রতিটি পাসওয়ার্ডে আলাদা salt নেয় আর ইচ্ছা করে ধীর (বাড়ানো যায় এমন cost factor), তাই ফাঁস হওয়া ডেটাবেসে প্রতিটি অনুমান ব্যয়বহুল
  • BCrypt উল্টানো যায়, তাই ভুলে যাওয়া পাসওয়ার্ড ফেরত দেওয়া যায়
  • SHA-256 ভাঙা হয়ে গেছে, তাই আর কোথাও ব্যবহার হয় না

(মাঝারি) কোন ক্ষেত্রে Spring Security-র CSRF সুরক্ষা বন্ধ রাখা বিপজ্জনক?

  • ব্রাউজারে session cookie দিয়ে লগইন করা ওয়েবসাইট
  • মোবাইল অ্যাপ, যা Authorization: Bearer header-এ token পাঠায়
  • দুটি backend service-এর মধ্যে token দিয়ে কল
  • লগইন ছাড়া শুধু পড়ার GET endpoint

(মাঝারি) একজন ব্যবহারকারী HS256-এ স্বাক্ষর করা নিজের JWT-এর payload খুলে "role":"CUSTOMER"-কে "ADMIN" করলেন, তারপর স্বাক্ষর অংশ আগের মতো রেখে token জোড়া লাগালেন। সঠিকভাবে কনফিগার করা সার্ভার কী করবে?

  • গ্রহণ করবে, কারণ payload এনক্রিপ্ট করা নয়
  • token পড়তেই পারবে না, কারণ payload এনক্রিপ্ট করা
  • প্রত্যাখ্যান করবে (401), কারণ নতুন payload-এর সাথে স্বাক্ষর মেলে না
  • শুধু exp বদলালে ধরা পড়ত, role বদলালে নয়

৯ · AI দিয়ে আরও MCQ বানান — কিন্তু উত্তর কোড চালিয়ে যাচাই করুন

এই পাতার প্রশ্ন শেষ হলে আরও অনুশীলন চাইবেন। AI চ্যাটবট মুহূর্তে শত শত MCQ বানিয়ে দিতে পারে। কিন্তু একটি সতর্কবার্তা মনে রাখুন: Java-র চতুর MCQ-তে AI প্রায়ই ভুল অপশনকে “সঠিক” বলে। কারণ ইন্টারনেটের পুরোনো প্রশ্নব্যাংকে একই ভুল বছরের পর বছর ছড়িয়েছে — যেমন “Java pass-by-reference”, বা “String pool PermGen-এ থাকে” (Java 7-এর আগের তথ্য)। তার ওপর Java প্রতি ছয় মাসে নতুন সংস্করণ পায়; AI অনেক সময় Java 8-এর নিয়ম আর Java 21-এর নিয়ম মিশিয়ে ফেলে, বা JUnit 4-এর annotation দিয়ে JUnit 5-এর প্রশ্ন বানায়।

AI-এর প্রচলিত ভুলউদাহরণকীভাবে ধরবেন
নিশ্চিত নয় এমন ক্রমকে নির্দিষ্ট বলাHashSet ছাপালে “ঢোকানোর ক্রমে আসবে”প্রশ্নে HashMap/HashSet-এর ক্রম চাইলে প্রশ্নটিই বাদ দিন
compile error চিনতে না পারাbyte b = b + 1; → “১১”কোডটি নিজে compile করুন — error বার্তাই উত্তর
পুরোনো সংস্করণের তথ্য“interface-এ কোনো method-এর body থাকে না”প্রশ্নে সংস্করণ লেখা আছে কি না দেখুন; Java 21-এ চালান
exception-এর নাম গুলিয়ে ফেলালুপে remove → “IndexOutOfBoundsException”চালিয়ে getClass().getName() ছাপান
দুটি সঠিক অপশন রাখা“কোনটি entry point?” — String[] args আর String... args দুটিই অপশনেপ্রতিটি অপশন আলাদা করে যাচাই করুন

নিচের প্রম্পটটি AI-কে প্রশ্ন বানাতে বলে, কিন্তু সাথে এমন তথ্যও চায়, যা দিয়ে আপনি উত্তর যাচাই করতে পারবেন। প্রতিটি কোড-প্রশ্নের জন্য একটি পূর্ণ প্রোগ্রাম চাওয়াই এখানে আসল কৌশল:

আমি Java-র MCQ পরীক্ষার প্রস্তুতি নিচ্ছি। ধরে নাও: OpenJDK 21 (LTS), কোনো preview সুবিধা চালু নেই, শুধু JDK-র standard library. বিষয়: [যেমন: inheritance আর polymorphism] কঠিনতা: [সহজ / মাঝারি / কঠিন] ১০টি MCQ বানাও। প্রতিটির জন্য: ১. প্রশ্ন আর ঠিক ৪টি অপশন; শুধু একটি সঠিক। প্রশ্ন নিজে সম্পূর্ণ হবে — “উপরের কোড” ধরনের উল্লেখ থাকবে না। ২. সঠিক উত্তর, আর প্রতিটি ভুল অপশন কেন ভুল — এক লাইনে। ৩. প্রশ্নে কোড থাকলে একটি সম্পূর্ণ, compile করা যায় এমন প্রোগ্রাম দাও (class Main আর main method সহ), যা চালালে উত্তরটি দেখা যায়। ৪. উত্তর compile error হলে javac-এর আসল বার্তাটি লেখো; exception হলে exception class-এর পূর্ণ নাম লেখো। ৫. HashMap/HashSet-এর ক্রম, thread-এর ক্রম বা hashCode-এর মানের ওপর নির্ভর করে এমন প্রশ্ন বানাবে না। ৬. কোন সংস্করণ থেকে নিয়মটি চালু, তা লেখো (যেমন “Java 16 থেকে”)। ৭. কোনো প্রশ্নকে কোনো নির্দিষ্ট পরীক্ষার আসল প্রশ্ন বলে দাবি করবে না।

যাচাইয়ের চেকলিস্ট

কেন এই উত্তর? — যে প্রশ্নগুলোতে সবচেয়ে বেশি ভুল হয়

এই ছয়টি বিষয় এত বেশি ভুল বোঝা হয় যে আলাদা ব্যাখ্যা দরকার। প্রশ্নটি নিয়ে আগে নিজে ভাবুন — তারপর “→ উত্তর” চাপুন।

প্র ০১String কেন immutable? আর একই লেখার দুটি String-এ == কখনো true, কখনো false কেন?

Java-র নকশাকারীরা শুরু থেকেই (Java 1.0, ১৯৯৬) String-কে immutable করেছিলেন — তৈরির পরে কোনো অক্ষর বদলানো যায় না। toUpperCase, replace, concat — সবই নতুন String ফেরত দেয়। এর পেছনে চারটি বাস্তব কারণ:

  • নিরাপত্তা: ফাইলের নাম, URL, ডেটাবেস ঠিকানা, class-এর নাম — সবই String. কেউ একটি String যাচাই করার পরে যদি অন্য কোড সেটি বদলে দিতে পারত, যাচাইয়ের কোনো মূল্য থাকত না।
  • ভাগাভাগি: বদলায় না বলে একই লেখার সব literal একটি object ভাগ করতে পারে — এটিই String pool. হাজার জায়গায় "OK" লিখলেও মেমরিতে একটি।
  • hashCode cache: String-এর hashCode একবার হিসাব করে রাখা যায়, কারণ লেখা কখনো বদলাবে না। তাই HashMap-এর key হিসেবে String দ্রুত আর নিরাপদ।
  • thread-safety: কেউ বদলাতে পারে না, তাই lock ছাড়াই অনেক thread একসাথে পড়তে পারে।

এবার ==. Object-এর ক্ষেত্রে == দেখে দুটি reference একই object দেখায় কি না — লেখা এক কি না নয়। তিনটি পরিস্থিতি মনে রাখুন। এক, দুটি literal ("Java") সব সময় pool-এর একই object, তাই true. দুই, literal-গুলোর জোড়া ("Ja" + "va") বা final constant-এর জোড়া একটি compile-time constant — javac নিজেই জুড়ে একটি literal বানায়, তাই এটিও true. তিন, চলার সময় তৈরি String — সাধারণ ভ্যারিয়েবলের সাথে জোড়া, new String(...), ফাইল বা কিবোর্ড থেকে পড়া — নতুন object, তাই false. intern() চাইলে pool-এর object ফেরত আনে।

একটি ইতিহাসের টুকরো, যা MCQ-তে আসে: Java 6 পর্যন্ত pool থাকত PermGen নামের ছোট, আলাদা জায়গায়, তাই বেশি intern করলে OutOfMemoryError: PermGen space হতো। Java 7-এ pool সাধারণ heap-এ সরানো হয়, আর Java 8-এ PermGen নিজেই সরে গিয়ে Metaspace আসে। তাই “String pool PermGen-এ থাকে” এখন ভুল উত্তর।

পরীক্ষার সহজ নিয়ম: আউটপুট প্রশ্নে == দেখলে আগে জিজ্ঞেস করুন, “দুটি দিকই কি compile-এর সময় জানা literal?” আর বাস্তব কোডে String তুলনায় সব সময় equals (বা equalsIgnoreCase).

মূল উপলব্ধি: String immutable বলেই pool, hashCode cache আর নিরাপদ ভাগাভাগি সম্ভব। == object-এর পরিচয় তুলনা করে — শুধু compile-time constant-এ সেটি লেখার সমতার সাথে মিলে যায়।

প্র ০২Integer-এ ১২৭ == ১২৭ true, কিন্তু ১২৮ == ১২৮ false কেন? এটি কি Java-র বাগ?

বাগ নয়, ইচ্ছাকৃত নকশা — তবে এমন নকশা, যা বহু প্রোগ্রামারকে ভুগিয়েছে। গল্পটা শুরু Java 5 (২০০৪)-এ, যখন autoboxing এলো। এর আগে List-এ সংখ্যা রাখতে লিখতে হতো list.add(new Integer(5)). Autoboxing-এর পর list.add(5) লিখলেই compiler ভেতরে বসিয়ে দেয় Integer.valueOf(5).

সমস্যা হলো, প্রতিবার নতুন Integer object বানানো ব্যয়বহুল — বিশেষ করে ছোট সংখ্যা (লুপের counter, ০, ১, −১) যা বারবার আসে। তাই Java ভাষার নির্দেশিকা (JLS §5.1.7) বলে দিল: −১২৮ থেকে ১২৭ পর্যন্ত মান box করলে সব সময় একই object পাওয়া যাবে। Integer class তাই শুরুতেই এই ২৫৬টি object বানিয়ে একটি cache-এ রাখে, আর valueOf এই সীমার মধ্যে cache থেকে দেয়। সীমার বাইরে নতুন object.

এখন ==. দুটি Integer-এর মধ্যে == মান নয়, object একই কি না দেখে। ১২৭-এর ক্ষেত্রে দুটি reference cache-এর একই object দেখায় → true. ১২৮-এর ক্ষেত্রে দুটি আলাদা object → false. ফলে এমন কোড, যা টেস্টে ছোট সংখ্যা দিয়ে নিখুঁত চলে, প্রোডাকশনে বড় ID-তে হঠাৎ ভুল করে — সবচেয়ে কঠিন ধরনের বাগ।

আরও কয়েকটি খুঁটিনাটি, যা MCQ-তে আসে:

  • উপরের সীমা JVM-এর -XX:AutoBoxCacheMax সেটিং দিয়ে বাড়ানো যায় — তাই সঠিক উত্তর লিখতে “ডিফল্ট সেটিংয়ে” কথাটি জরুরি। নিচের সীমা −১২৮ বদলায় না।
  • Short, Byte, Long, Character (০–১২৭)-এরও cache আছে; Double আর Float-এর নেই।
  • একদিকে primitive থাকলে (Integer a = 128; int b = 128; a == b) unboxing হয়, মান তুলনা হয় → true.
  • new Integer(5) সব সময় নতুন object দিত; এই constructor Java 9-এ deprecated, আর Java 16-এ “for removal” চিহ্নিত হয়েছে।

এই অভিজ্ঞতা থেকেই Project Valhalla-র “value class”-এর ভাবনা — এমন টাইপ, যার কোনো পরিচয় (identity) নেই, শুধু মান; তখন == নিয়ে এই বিভ্রান্তিই থাকবে না।

মূল উপলব্ধি: wrapper object-এ == পরিচয় তুলনা করে, আর −১২৮ থেকে ১২৭-এর cache সেটিকে মাঝে মাঝে “ঠিক” দেখায়। মান তুলনায় সব সময় equals বা primitive.

প্র ০৩equals override করলে hashCode-ও কেন override করতে হয়? HashMap আসলে কীভাবে খোঁজে?

একটি বড় লাইব্রেরির কথা ভাবুন, যেখানে বই রাখা হয় তাকের নম্বর অনুযায়ী। বই খুঁজতে আপনি আগে হিসাব করেন বইটি কোন তাকে থাকার কথা, তারপর শুধু সেই তাকে বই মিলিয়ে দেখেন। HashMap ঠিক এভাবেই কাজ করে। get(key) প্রথমে key.hashCode() থেকে একটি bucket (তাক) ঠিক করে, তারপর শুধু সেই bucket-এর key-গুলোর সাথে equals দিয়ে মেলায়। এ কারণেই গড়ে O(1) — পুরো map খুঁজতে হয় না।

এবার ধরুন আপনি Student-এ equals override করেছেন — roll এক হলে দুটি student সমান। কিন্তু hashCode করেননি, তাই Object-এর ডিফল্টটি চলছে, যা দুটি আলাদা object-এর জন্য সাধারণত আলাদা সংখ্যা দেয়। এখন map.put(new Student(5), "Rina"), তারপর map.get(new Student(5)). দ্বিতীয় object-এর hashCode আলাদা, তাই HashMap অন্য তাকে খোঁজে — সেখানে কিছুই নেই, ফল null. equals ডাকার সুযোগই আসে না। কোনো exception নেই, কোনো warning নেই — নীরব ভুল।

তাই Object-এর Javadoc-এ লেখা চুক্তি:

  • a.equals(b) true হলে a.hashCode() == b.hashCode() হতেই হবে।
  • উল্টোটি বাধ্যতামূলক নয়: আলাদা object-এর একই hashCode হতে পারে (collision) — তখন একই bucket-এ কয়েকটি key থাকে, আর equals সেগুলো আলাদা করে।
  • object-এর যে field equals-এ ব্যবহার হয়, সেটি বদলালে hashCode-ও বদলাতে পারে। তাই map-এর key mutable হলে, key রাখার পরে তা বদলালে object “হারিয়ে” যায়। এ কারণেই key হিসেবে String, Integer, record-এর মতো immutable টাইপ সবচেয়ে ভালো।

collision নিয়ে একটি তথ্য, যা কঠিন MCQ-তে আসে: Java 8 থেকে একটি bucket-এ অনেক key জমলে (সীমা ৮, আর table-এ অন্তত ৬৪টি ঘর থাকলে) linked list-কে একটি balanced tree-তে বদলে দেওয়া হয় (treeification). তাই খারাপ hashCode-এর সবচেয়ে খারাপ ক্ষেত্রেও খোঁজা O(n)-এর বদলে মোটামুটি O(log n) — ইচ্ছাকৃত collision দিয়ে সার্ভার ধীর করার আক্রমণের বিরুদ্ধে একটি সুরক্ষা।

বাস্তবে সহজ সমাধান: Objects.hash(roll, name) দিয়ে hashCode, IDE দিয়ে দুটি একসাথে বানানো — অথবা record ব্যবহার করা, যা দুটিই নিজে থেকে সঠিকভাবে বানায়।

মূল উপলব্ধি: HashMap আগে hashCode দিয়ে bucket বাছে, তারপর equals দিয়ে মেলায়। equals-এ সমান object-এর hashCode আলাদা হলে HashMap তাদের কখনো খুঁজে পায় না — তাই দুটি সব সময় একসাথে।

প্র ০৪Java কি pass-by-reference? method-এর ভেতরে object বদলালে বাইরে বদলায়, তাহলে “Java সব সময় pass-by-value” কথাটি কীভাবে সত্য?

এটি Java-র সবচেয়ে পুরোনো বিতর্কগুলোর একটি, আর ইন্টারভিউতে প্রায়ই আসে। উত্তর একটিই: Java সব সময় pass-by-value — ভাষার নির্দেশিকা (JLS) তা-ই বলে, আর James Gosling-ও একই কথা বলেছেন। বিভ্রান্তি আসে “value” বলতে কী পাঠানো হয়, তা না বোঝা থেকে।

Primitive (int, double) ভ্যারিয়েবলে মানটি নিজেই থাকে, তাই method সেই মানের একটি কপি পায়। Object-এর ক্ষেত্রে ভ্যারিয়েবলে object থাকে না — থাকে একটি reference, অর্থাৎ heap-এর object-এর দিকে একটি “ঠিকানা”। method ডাকলে সেই ঠিকানার একটি কপি যায়। ফলে দুটি ঘটনা ঘটে:

  • কপি-ঠিকানা দিয়ে object বদলানো: a[0] = 99 বা student.setName("Rina") — দুটি ঠিকানাই একই object দেখায়, তাই পরিবর্তন বাইরে দেখা যায়। এটিকেই লোকে ভুল করে “pass-by-reference” ভাবে।
  • কপি-ঠিকানায় নতুন object বসানো: a = new int[]{7} — শুধু method-এর নিজের কপি অন্য দিকে সরে যায়; caller-এর ভ্যারিয়েবল আগের object-ই দেখায়।

সত্যিকারের pass-by-reference হলে (যেমন C++-এর int& বা C#-এর ref) দ্বিতীয় কাজটিও caller-এর ভ্যারিয়েবল বদলে দিত। সবচেয়ে সহজ পরীক্ষা: একটি swap(Student a, Student b) method লিখুন, যা ভেতরে a আর b অদলবদল করে। Java-তে বাইরের দুটি ভ্যারিয়েবল একটুও বদলায় না — সত্যিকারের reference পাঠানো হলে বদলাত।

একটি উপমা: আপনি বন্ধুকে আপনার বাসার ঠিকানা একটি কাগজে লিখে দিলেন (কপি)। বন্ধু সেই ঠিকানায় গিয়ে দেয়াল রং করলে আপনার বাসা বদলায়। কিন্তু বন্ধু যদি কাগজটি কেটে অন্য ঠিকানা লেখেন, আপনার বাসা বা আপনার নিজের কাগজ — কোনোটিই বদলায় না।

String-এর ক্ষেত্রে বিভ্রান্তি আরও বাড়ে। void f(String s) { s = s + "!"; } বাইরের String বদলায় না — কারণ দুটোই: String immutable, আর s = ... শুধু কপি-reference সরায়।

MCQ-তে উত্তর বাছার নিয়ম: method-এর ভেতরে param.field = ... বা param[i] = ... → বাইরে দেখা যায়। param = new ... → বাইরে দেখা যায় না। আর primitive প্যারামিটার বদলালে কখনোই বাইরে দেখা যায় না।

মূল উপলব্ধি: Java reference-এর মান কপি করে পাঠায়। তাই object-এর ভেতরটা বদলানো যায়, কিন্তু caller-এর ভ্যারিয়েবলকে অন্য object-এ সরানো যায় না — এটিই pass-by-value-এর প্রমাণ।

প্র ০৫checked exception কি ভালো ধারণা ছিল? কেন অন্য অনেক ভাষা এটি নেয়নি?

Java প্রায় একমাত্র জনপ্রিয় ভাষা, যেখানে compiler exception নিয়ে জোর খাটায়। নিয়মটি সরল: checked exception (যেমন IOException, SQLException — Exception-এর subclass কিন্তু RuntimeException-এর নয়) যে method ছুড়তে পারে, তাকে হয় catch করতে হবে, নয়তো throws লিখে ঘোষণা করতে হবে। না করলে javac থামায়: unreported exception ...; must be caught or declared to be thrown. unchecked exception (RuntimeException আর তার subclass, আর Error) এই বাধ্যবাধকতার বাইরে।

১৯৯০-এর দশকে ভাবনাটি ছিল যুক্তিসঙ্গত: ফাইল না পাওয়া, নেটওয়ার্ক বিচ্ছিন্ন হওয়া — এগুলো প্রোগ্রামারের ভুল নয়, বাস্তব জগতের ঘটনা, যা ঘটবেই। compiler যদি বাধ্য করে, কেউ ভুলে যাবে না। আর NullPointerException, ArrayIndexOutOfBoundsException প্রোগ্রামারের ভুল — এগুলো ধরার বদলে কোড ঠিক করা উচিত, তাই unchecked.

বাস্তবে সমস্যা দেখা দিল কয়েকটি জায়গায়:

  • গিলে ফেলা exception: compiler-কে চুপ করাতে অনেকে লেখেন catch (Exception e) {} — ভুলটি চিরতরে হারিয়ে যায়। এটি exception না ধরার চেয়েও খারাপ।
  • স্তর ভেদ করে ছড়িয়ে পড়া: একদম নিচের স্তরে নতুন checked exception এলে উপরের প্রতিটি method-এর throws বদলাতে হয়।
  • lambda আর stream: Java 8-এর Function, Consumer-এর method কোনো checked exception ঘোষণা করে না। তাই stream.map(p -> Files.readString(p)) compile হয় না — ভেতরে try-catch লাগে। এ কারণে JDK নিজেই UncheckedIOException (Java 8) যোগ করেছে।

C# (২০০০) এর নকশাকারী Anders Hejlsberg প্রকাশ্যে ব্যাখ্যা করেছেন কেন তাঁরা checked exception নেননি — versioning আর scalability-র সমস্যার জন্য। Kotlin, Scala-ও নেয়নি; Kotlin-এ সব exception unchecked, যদিও সেটি একই JVM-এ চলে। Spring-ও SQLException-কে unchecked DataAccessException-এ মুড়ে দেয়।

তবু checked exception উঠে যায়নি, আর এর পক্ষেও যুক্তি আছে: method-এর signature দেখেই বোঝা যায় কী ব্যর্থ হতে পারে। আধুনিক রীতি মোটামুটি এমন — ডাকার জায়গা থেকে সত্যিই সামলানো যায় এমন অবস্থায় checked, প্রোগ্রামিং ভুল বা সামলানো যায় না এমন অবস্থায় unchecked; আর কখনো খালি catch নয়।

মূল উপলব্ধি: checked exception compiler দিয়ে ব্যর্থতা সামলাতে বাধ্য করে — ভাবনাটি ভালো, কিন্তু খালি catch, lambda আর স্তরের সমস্যায় বিতর্কিত। MCQ-তে মূল চাবি একটি: RuntimeException-এর বংশধর হলে unchecked, না হলে checked.

প্র ০৬for-each লুপে list থেকে remove করলে ConcurrentModificationException আসে — কিন্তু মাঝে মাঝে আসে না কেন?

for-each লুপ (for (Integer x : list)) আসলে একটি Iterator-এর ছদ্মবেশ: compiler এটিকে hasNext() আর next()-এর লুপে বদলে দেয়। ArrayList-এর ভেতরে একটি গণনা থাকে — modCount — যা প্রতিটি গঠনগত পরিবর্তনে (add, remove) এক বাড়ে। Iterator তৈরির সময় সে এই সংখ্যাটি মনে রাখে। প্রতিটি next()-এ মিলিয়ে দেখে; না মিললে বোঝে কেউ তার অজান্তে list বদলেছে, আর সাথে সাথে ConcurrentModificationException ছোড়ে। একে বলে fail-fast — ভুল ফল নিয়ে নীরবে চলার চেয়ে তাড়াতাড়ি থেমে যাওয়া ভালো।

নামের “Concurrent” শব্দটি বিভ্রান্তিকর: একটিমাত্র thread-এও এটি আসে। এখানে concurrent মানে “লুপ চলার সাথে সাথে বদলানো”।

এবার রহস্য। [1, 2, 3] list-এ if (x == 1) list.remove(x) → exception. কিন্তু if (x == 2) list.remove(x) → কোনো exception নেই, ফল [1, 3]! কেন? ArrayList-এর iterator-এর hasNext() শুধু দেখে cursor != size. ২ সরানোর পর size হয় ২, আর cursor-ও তখন ২ (দুটি উপাদান পড়া হয়ে গেছে)। তাই hasNext() false দেয়, লুপ শেষ — next() আর ডাকা হয় না, তাই যাচাইও হয় না। শেষের আগের উপাদান সরালে এই ফাঁক তৈরি হয়। কিন্তু খেয়াল করুন: ৩ আর কখনো পরীক্ষাই হয়নি — যুক্তির বাগ রয়ে গেছে। Javadoc নিজেই বলে, fail-fast আচরণ “best-effort”, এর ওপর ভরসা করে প্রোগ্রাম লেখা উচিত নয়।

নিরাপদ উপায় তিনটি:

  • list.removeIf(x -> x == 1); — Java 8 থেকে, সবচেয়ে পরিষ্কার।
  • স্পষ্ট Iterator নিয়ে it.remove() — iterator নিজে modCount হালনাগাদ করে।
  • নতুন list বানানো: list.stream().filter(x -> x != 1).toList().

একাধিক thread থাকলে আলাদা সমাধান: CopyOnWriteArrayList (iterator একটি স্থির কপি দেখে, কখনো exception দেয় না), বা ConcurrentHashMap-এর মতো concurrent collection, যাদের iterator “weakly consistent”.

আরেকটি ফাঁদ: List<Integer>-এ list.remove(x)-এ x যদি int হয়, তাহলে index ধরে সরায়; Integer হলে মান ধরে। for-each-এর Integer x-এ তাই মান ধরে সরানো হয়।

মূল উপলব্ধি: fail-fast iterator modCount মিলিয়ে লুকানো পরিবর্তন ধরে, কিন্তু শুধু পরের next()-এ — তাই শেষের আগের উপাদান সরালে exception না-ও আসতে পারে। লুপের ভেতরে সরাতে removeIf বা Iterator.remove.

শেষ ধাপ — ক্রম সাজান আর স্কোর দেখুন

উপরের সব MCQ শেষ করলে নিচে আপনার মোট স্কোর দেখাবে — প্রথম চেষ্টায় কয়টি ঠিক হয়েছে।

ক্রমMaven-এর default lifecycle-এর ছয়টি প্রধান phase সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. ✅ validate — প্রজেক্টের গঠন ঠিক আছে কি না
  2. ⚙️ compile — source থেকে bytecode
  3. 🧪 test — unit test চালানো
  4. 📦 package — jar বা war বানানো
  5. 💾 install — local repository-তে রাখা
  6. 🚀 deploy — remote repository-তে পাঠানো

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব শব্দ এখানে একসাথে:

মনে রাখুন

  1. আগে দুটি প্রশ্ন: কোড থাকলে আউটপুট খোঁজার আগে জিজ্ঞেস করুন — “এটি কি compile হবে?” আর “চলার সময় কি exception?” অনেক কঠিন প্রশ্নের উত্তর এখানেই মেলে।
  2. বাদ দিন, খুঁজবেন না: প্রতিটি অপশনের পেছনের নিয়ম যাচাই করুন; “সব সময়”, “কখনো না” ধরনের চরম শব্দে সতর্ক হোন; “কোনটি মিথ্যা” প্রশ্নে প্রতিটি বাক্যে দাগ দিন।
  3. ==-এর তিন ফাঁদ: String-এ শুধু compile-time constant-এ true; Integer-এ শুধু −১২৮ থেকে ১২৭-এ; equals override করলে hashCode-ও — নইলে HashMap খুঁজে পায় না।
  4. OOP-এর তিন ফাঁদ: শুধু instance method override হয় — field আর static method নয়; constructor থেকে override করা method ডাকলে subclass-এর field তখনো ডিফল্ট; override করে access কমানো যায় না।
  5. Collections ও stream: List.of বদলানো যায় না; for-each লুপে remove সাধারণত ConcurrentModificationException দেয়; HashSet-এর ক্রম নিশ্চিত নয়; terminal operation ছাড়া stream কিছুই করে না, আর একবারের বেশি চলে না।

পরের পর্বে: MCQ-তে চারটি অপশন থেকে বাছতে হয়। লিখিত আর মৌখিক (ভাইভা) পরীক্ষায় কোনো অপশন নেই — নিজের ভাষায় সংজ্ঞা, পার্থক্য আর উদাহরণ দিতে হয়। পর্ব ৫৮-এ সেই প্রশ্নগুলো আর উত্তর সাজানোর কৌশল।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান