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

প্রথম Java প্রোগ্রাম — class, main আর println

Your First Java Program — class, main, println and Reading Compiler Errors

Taught in Bangla, this lesson walks through a first Java program word by word: why all code lives in a class, the public static void main signature, file and class naming rules, print and println with concatenation and escape sequences, syntax rules and comments, and reading javac error messages to fix mistakes.

এই পর্বে যা শিখবেন

  • Hello World প্রোগ্রামের প্রতিটি শব্দ — class, public, static, void, main, String[] args — কেন আছে
  • প্রোগ্রাম চালু করলে JVM ঠিক কোন ক্রমে কাজ করে
  • print, println, লেখা জোড়া দেওয়া (+) আর escape sequence দিয়ে সুন্দর আউটপুট
  • Comment কীভাবে লিখবেন, আর কেন comment “কী” নয়, “কেন” ব্যাখ্যা করে
  • javac-এর আসল error মেসেজ পড়ে নিজেই ভুল খুঁজে ঠিক করা

১ · Java-তে সবকিছু একটি class-এর ভেতরে

পর্ব ০৩-এ আপনি JDK বসিয়েছেন, JShell-এ দু-এক লাইন লিখেও দেখেছেন। এবার আসল জিনিস — একটি পূর্ণ Java প্রোগ্রাম, যা ফাইলে লেখা হয়, compile হয়, আর যেকোনো কম্পিউটারে চলে। প্রায় সব Java বইয়ের প্রথম প্রোগ্রামটি দেখতে এমন:

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, Dhaka!");
    }
}

Python-এ একই কাজ এক লাইনে হয়: print("Hello, Dhaka!"). তাহলে Java-তে পাঁচ লাইন কেন? কারণ Java-র নকশার একটি মৌলিক সিদ্ধান্ত: প্রতিটি কোড কোনো না কোনো class-এর অংশ। পর্ব ০২-এ দেখেছেন, Java সমস্যাকে object আর তাদের দায়িত্বে ভাগ করে ভাবে। Class হলো সেই দায়িত্বের ঘর। একটি লাইন লিখতে চাইলেও সেটি কোনো ঘরের ভেতরেই লিখতে হয় — Java-তে “বাইরে পড়ে থাকা” কোড বলে কিছু নেই (Java 25-এর একটি নতুন সুবিধা বাদে, যা অংশ ৬-এ দেখবেন)।

একটি চায়ের দোকানের কথা ভাবুন। দোকানের একটি নাম আছে — “রফিক টি স্টল”। দোকানের ভেতরে কাজ হয়: চা বানানো, বিল করা। আর প্রতিদিন সকালে একটি নির্দিষ্ট কাজ দিয়ে দিন শুরু হয় — শাটার তোলা। Java প্রোগ্রামে class Main হলো দোকানের নাম আর চার দেয়াল, ভেতরের method-গুলো হলো কাজ, আর main হলো “সকালের শাটার তোলা” — যেখান থেকে দিনের সব কাজ শুরু হয়। খদ্দের (এখানে JVM) এসে প্রথমেই সেই দরজাটাই খোঁজে।

এই প্রোগ্রামে তিনটি স্তর আছে, একটির ভেতরে আরেকটি — ঠিক বাক্সের ভেতরে বাক্সের মতো:

📦 বাইরের বাক্স: class

public class Main { … } — প্রোগ্রামের নাম আর সীমানা। ভেতরের সবকিছু এই class-এর।

দোকানের নাম আর দেয়াল

🚪 মাঝের বাক্স: main method

public static void main(String[] args) { … } — প্রোগ্রাম শুরুর দরজা, যাকে বলে entry point.

সকালের শাটার তোলা

✍️ ভেতরের কাজ: statement

System.out.println("Hello, Dhaka!"); — একটি নির্দেশ: “স্ক্রিনে এই লেখাটি ছাপো, তারপর নতুন লাইনে যাও।”

আসল কাজ
মূল ধারণা

Java প্রোগ্রাম চালু করলে JVM তিনটি কাজ করে: (১) আপনার বলা class-টি খুঁজে মেমরিতে আনে, (২) তার ভেতরে ঠিক public static void main(String[] args) রূপের method খোঁজে, (৩) সেটিকে ডাকে। এরপর main-এর ভেতরের statement-গুলো একটার পর একটা, ওপর থেকে নিচে চলে। main শেষ হলে প্রোগ্রামও শেষ।

Java-র জন্ম ১৯৯০-এর দশকের শুরুতে Sun Microsystems-এ, James Gosling-এর নেতৃত্বে একটি ছোট দলের হাতে — প্রথম নাম ছিল Oak. ১৯৯৫ সালে “Java” নামে প্রকাশ্যে আসে। Gosling আর তাঁর দল ইচ্ছা করেই এর চেহারা C আর C++-এর মতো রেখেছিলেন: সেই একই { }, ;, main. লক্ষ্য ছিল, লাখ লাখ C/C++ প্রোগ্রামার যেন প্রথম দিনেই Java কোড পড়তে পারেন। “সব কিছু class-এর ভেতরে” নিয়মটি অবশ্য এসেছিল object-oriented চিন্তা থেকে — এখানে Java তার পূর্বসূরিদের চেয়ে কড়া।

২ · Hello World — শব্দ ধরে ধরে

অনেকে public static void main(String[] args) লাইনটিকে মন্ত্রের মতো মুখস্থ করেন। প্রথম দিনে সব শব্দের পূর্ণ অর্থ বোঝা সম্ভবও নয় — কিছু শব্দ পরের পর্বগুলোতে বিস্তারিত আসবে। কিন্তু প্রতিটি শব্দ মোটামুটি কী বলছে, সেটি আজই জেনে রাখা ভালো। তাহলে error এলে বুঝবেন কোন শব্দে সমস্যা। নিচের ডায়াগ্রামে “পরে” চাপুন — প্রতিটি টুকরো আলাদা করে আলো জ্বলবে:

public class Main { public static void main (String[] args) System.out.println ("Hello, Dhaka!"); } }
  1. public (class-এর আগে) — “এই class সবার জন্য খোলা, যেকোনো জায়গা থেকে ব্যবহার করা যাবে।” এটি একটি access modifier. এর একটি বড় শর্ত আছে, যা অংশ ৩-এ দেখবেন: public class-এর নাম আর ফাইলের নাম এক হতে হয়। বিস্তারিত পর্ব ১৭-এ।
  2. class — একটি keyword, অর্থাৎ Java-র নিজের সংরক্ষিত শব্দ। বলছে, “এখান থেকে একটি class-এর সংজ্ঞা শুরু।” Keyword দিয়ে নিজের কোনো জিনিসের নাম রাখা যায় না — class নামে ভ্যারিয়েবল হয় না।
  3. Main — class-টির নাম, যা আপনি বেছে নেন। প্রথা হলো class-এর নাম বড় হাতের অক্ষরে শুরু (Main, TeaStall, Receipt). এটি নিয়ম নয়, কিন্তু সারা দুনিয়ার Java প্রোগ্রামার এই প্রথা মানেন।
  4. { — class-এর শরীর শুরু। এর জোড়া } আছে একদম শেষে। দুই বন্ধনীর মাঝের অংশকে বলে block. প্রতিটি খোলা বন্ধনীর একটি বন্ধ বন্ধনী থাকতেই হবে।
  5. public (main-এর আগে) — main method-টিও সবার জন্য খোলা। কেন? কারণ যে একে ডাকবে, সেই JVM আপনার class-এর বাইরের কেউ। দরজা বন্ধ থাকলে সে ঢুকতে পারবে না।
  6. static — “এই method ডাকতে class-এর কোনো object বানাতে হবে না।” প্রোগ্রাম শুরুর মুহূর্তে কোনো object থাকে না — তাই JVM সরাসরি Main.main(…) ডাকতে পারে। static-এর পুরো গল্প পর্ব ১৮-এ।
  7. void — “এই method কাজ শেষে কোনো মান ফেরত দেয় না।” void মানে শূন্য বা ফাঁকা। C-র int main যেখানে একটি সংখ্যা ফেরত দেয়, Java-র main কিছুই ফেরত দেয় না। Method কীভাবে মান ফেরত দেয়, তা পর্ব ১২-এ।
  8. main — method-টির নাম। এটি বাছাই করা নাম নয় — JVM ঠিক এই বানানটিই খোঁজে, ছোট হাতের অক্ষরে। Main বা mian লিখলে compile হবে, কিন্তু চালাতে গেলে JVM বলবে main method পাওয়া যায়নি।
  9. (String[] args) — main-এর parameter. String[] মানে “অনেকগুলো লেখার একটি তালিকা” (array), আর args তার নাম। প্রোগ্রাম চালানোর সময় কমান্ডের সাথে কিছু শব্দ দিলে (যেমন java Main Rafi) সেগুলো এখানে আসে। আজ আমরা এটি ব্যবহার করব না, তবু লিখতে হবে — কারণ JVM ঠিক এই রূপটিই খোঁজে। Array শিখবেন পর্ব ১৩-এ।
  10. System.out.println — তিন টুকরো। System হলো Java-র তৈরি একটি class (বড় হাতের S), যার কাছে কম্পিউটারের সাথে যোগাযোগের জিনিসপত্র থাকে। out হলো তার ভেতরের standard output — সাধারণত আপনার স্ক্রিন। আর println হলো সেই out-এর একটি method: “print line” — লেখাটি ছাপো, তারপর নতুন লাইনে যাও। মাঝের ডট (.) মানে “এর ভেতরের”।
  11. ("Hello, Dhaka!"); — বন্ধনীর ভেতরে যা দেওয়া হয়, println তা-ই ছাপে। ডাবল কোটের ভেতরের লেখাকে বলে String. আর শেষের ; বলছে “এই statement এখানে শেষ।” Java-তে লাইন ভাঙা দিয়ে statement শেষ হয় না — শেষ হয় semicolon দিয়ে।
  12. } } — প্রথমটি main-এর block বন্ধ করে, দ্বিতীয়টি class-এর। বাক্স বন্ধ করার ক্রম উল্টো: আগে ভেতরের, পরে বাইরের। একটিও বাদ পড়লে compile হবে না — অংশ ৭-এ সেই error-টি দেখবেন।

এখন আপনি জানেন যে, এই লম্বা লাইনের প্রতিটি শব্দ একটি নির্দিষ্ট প্রশ্নের উত্তর দিচ্ছে: কে ডাকতে পারবে (public), object লাগবে কি না (static), কী ফেরত দেবে (void), নাম কী (main), আর কী নেবে (String[] args). এই পাঁচটি প্রশ্ন Java-র প্রতিটি method-এর জন্যই আসে — main শুধু প্রথম উদাহরণ।

আরেকটি কথা: String[] args-এর জায়গায় String... args বা String args[] লিখলেও JVM মেনে নেয়, আর args-এর বদলে যেকোনো নাম দেওয়া যায়। কিন্তু পেশাদার কোডে প্রায় সবাই String[] args লেখেন — সেটাই অভ্যাস করুন।

৩ · ফাইলের নাম আর class-এর নাম — একটি জরুরি নিয়ম

Java-র একটি নিয়ম নতুনদের সবচেয়ে বেশি অবাক করে: একটি public class-এর নাম যা, ফাইলের নামও হুবহু তা-ই হতে হবে, শেষে .java. public class Main থাকবে Main.java ফাইলে; public class TeaStall থাকবে TeaStall.java-তে। বড়-ছোট হাতের অক্ষরও মিলতে হবে। আর একটি ফাইলে public class থাকতে পারে বড়জোর একটি।

নিজের কম্পিউটারে কাজটি দুই ধাপে হয় (পর্ব ০৩-এ দেখেছেন):

javac Main.java     # compile: তৈরি হয় Main.class
java Main           # চালানো: JVM-কে বলা হলো "Main class-টি চালাও"

খেয়াল করুন, java কমান্ডে ফাইলের নাম নয়, class-এর নাম দেওয়া হয় (.class ছাড়া)। javac প্রতিটি class থেকে একটি আলাদা .class ফাইল বানায়, যার ভেতরে থাকে bytecode. এর ভেতরের গল্প পরের পর্বে। ছোট প্রোগ্রামের জন্য Java 11 থেকে একটি শর্টকাটও আছে — java Main.java লিখলে compile আর চালানো একসাথে হয়।

এই কোর্সের “চালান” বোতাম সম্পর্কে একটি কথা। পাতার ভেতরের কোড চালানো হয় একটি অনলাইন সার্ভারে (Wandbox, OpenJDK 21). সেই সার্ভার আপনার কোডকে সবসময় prog.java নামের ফাইলে রেখে compile করে। ফাইলের নাম prog.java হলে public class Main নিয়ম ভাঙে! তাই এই কোর্সের চালানো যায় এমন সব কোডে লেখা থাকবে শুধু class Main — সামনে public ছাড়া। Public না হলে ফাইলের নামের শর্ত খাটে না, আর JVM-ও main ঠিকই খুঁজে পায়। নিজের প্রজেক্টে কিন্তু প্রথাটাই মানুন: public class Main, ফাইলের নাম Main.java. IntelliJ IDEA বা VS Code নতুন class বানালে নিজেই এভাবে ফাইল তৈরি করে দেয়।

নিয়মটি ভাঙলে javac ঠিক কী বলে? অনলাইন সার্ভারে public class Hello লিখে দেখা গেল (ফাইলের নাম prog.java):

prog.java:1: error: class Hello is public, should be declared in a file named Hello.java
public class Hello {
       ^
1 error

মেসেজটি নিজেই সমাধান বলে দিচ্ছে: “class Hello public, তাই একে Hello.java নামের ফাইলে রাখুন।” দুটি সমাধান — ফাইলের নাম বদলান, অথবা (অনলাইন runner-এ) public শব্দটি সরিয়ে দিন।

কেন এই নিয়ম? বড় প্রজেক্টে হাজার হাজার class থাকে। কোনো class দরকার হলে compiler আর মানুষ — দুজনেই জানে কোথায় খুঁজতে হবে: TeaStall আছে TeaStall.java-তে। কোনো সূচিপত্র লাগে না। পরে package নিয়ে কাজ করার সময় দেখবেন, ফোল্ডারের নামও একইভাবে package-এর নামের সাথে মেলে।

৪ · প্রোগ্রাম চালু হলে JVM যা করে

আপনি java Main লিখে Enter চাপলেন। তারপর ঠিক কী ঘটে? নিচের ডায়াগ্রামটি একটি ছোট প্রোগ্রাম ধাপে ধাপে চালাচ্ছে — দোকান খোলা থেকে বন্ধ হওয়া পর্যন্ত। ডান দিকে খেয়াল করুন, JVM প্রতিটি মুহূর্তে কী করছে আর স্ক্রিনে কী আসছে:

1class Main {2    public static void main(String[] args) {3        System.out.println("Dokan khola");4        System.out.println("Cha ready");5        System.out.println("Dokan bondho");6    }7}
এই মুহূর্তে
JVM কী করছে
object আছে?
  1. কমান্ড দেওয়া হলো। আগেই javac Main.java দিয়ে Main.class তৈরি হয়েছে। এখন java Main লেখায় অপারেটিং সিস্টেম JVM নামের প্রোগ্রামটি চালু করল, আর তাকে বলল: “Main নামের class চালাও।” স্ক্রিনে এখনো কিছু ছাপা হয়নি।
  2. Class খুঁজে আনা। JVM Main.class ফাইলটি খুঁজে মেমরিতে আনে (একে বলে class loading). ফাইল না পেলে এখানেই থেমে যায়: Could not find or load main class Main. সাধারণত ভুল ফোল্ডারে থাকলে বা নামের বানান ভুল হলে এমন হয়।
  3. দরজা খোঁজা — main. JVM class-টির ভেতরে ঠিক public static void main(String[] args) খোঁজে। খেয়াল করুন, “object আছে?” ঘরে লেখা “না”। কোনো object বানানো হয়নি, তবু main ডাকা গেল — কারণ এটি static. এটাই static-এর প্রথম ব্যবহারিক মানে।
  4. প্রথম statement. এবার main-এর ভেতরের লাইনগুলো চলছে, ওপর থেকে নিচে। লাইন ৩ স্ক্রিনে ছাপল Dokan khola, তারপর নতুন লাইনে গেল (println-এর “ln”).
  5. দ্বিতীয় statement. লাইন ৪ — একই কাজ, নতুন লেখা। আগের লাইন শেষ না হওয়া পর্যন্ত পরের লাইন শুরু হয় না। এই সরল ক্রমই সব প্রোগ্রামের ভিত্তি; পর্ব ১০ আর ১১-এ দেখবেন if আর loop দিয়ে এই ক্রম কীভাবে বদলানো যায়।
  6. শেষ statement. লাইন ৫ ছাপল Dokan bondho. এবার main-এর block-এর শেষ বন্ধনী।
  7. main শেষ, প্রোগ্রাম শেষ। main ফেরত গেলে (এবং অন্য কোনো কাজ চলতে না থাকলে) JVM বন্ধ হয়ে যায়, আর terminal আবার আপনার কমান্ডের অপেক্ষায় ($)। স্বাভাবিকভাবে শেষ হলে অপারেটিং সিস্টেম পায় exit code 0, মানে “সব ঠিক”. পুরো যাত্রায় একটি object-ও তৈরি হয়নি।
C/C++/Python জানলে

C/C++-এর মতোই Java শুরু হয় main থেকে, statement শেষ হয় ; দিয়ে, block থাকে { }-এ। পার্থক্য: Java-তে main অবশ্যই একটি class-এর ভেতরে থাকে, কিছু ফেরত দেয় না (void), আর কোনো #include নেই — System-এর মতো মৌলিক class সবসময় হাতের কাছে। Python-এর তুলনায় Java-তে indentation ব্যাকরণের অংশ নয়, কিন্তু টাইপ আর কাঠামো অনেক কড়া। তুলনার জন্য দেখুন C++-এর প্রথম প্রোগ্রাম আর Python-এর প্রথম প্রোগ্রাম।

৫ · আউটপুট — print, println, + আর escape sequence

স্ক্রিনে লেখা ছাপার জন্য প্রতিদিন তিনটি method লাগবে। তিনটিই থাকে System.out-এর ভেতরে:

Methodকী করেকখন
print(…)লেখা ছাপে, কার্সর একই লাইনে থাকেএক লাইনে কয়েক টুকরো জোড়া দিতে
println(…)লেখা ছাপে, তারপর নতুন লাইনে যায়প্রায় সব সময়
printf(…)নির্দিষ্ট ছাঁচে (format) সাজিয়ে ছাপেটাকার অঙ্ক, টেবিল, দশমিক — পর্ব ০৯-এ বিস্তারিত

print আর println-এর পার্থক্য চোখে দেখা সবচেয়ে সহজ। নিচের ডায়াগ্রামে প্রতিটি লাইনের পর কার্সর (▌) কোথায় থাকে, খেয়াল করুন:

3System.out.print("Cha ");4System.out.print("15 tk");5System.out.println();6System.out.println("Singara 20 tk");7System.out.print("Dhonnobad!");
কার্সর
কোথায়
  1. print("Cha ") — লেখাটি ছাপা হলো, কার্সর ঠিক তার পরেই দাঁড়িয়ে রইল। শেষের ফাঁকা জায়গাটিও (space) লেখার অংশ, তাই ছাপা হয়েছে।
  2. print("15 tk") — একই লাইনে জুড়ে গেল। দুটি print মিলে একটি লাইন: Cha 15 tk. Space না রাখলে আসত Cha15 tk.
  3. println() — খালি বন্ধনী: কিছু ছাপল না, শুধু লাইন ভাঙল। কার্সর এখন নতুন লাইনের শুরুতে।
  4. println("Singara 20 tk") — লেখা ছাপল এবং লাইন ভাঙল — এক ধাপে দুই কাজ। তাই সাধারণত println-ই বেশি ব্যবহার হয়।
  5. print("Dhonnobad!") — শেষ লাইনটি print, তাই কার্সর লাইনের শেষেই থেকে গেল। Terminal-এ পরের $ চিহ্নটি এসে বসবে এই লেখার ঠিক পাশে — অনেক সময় নতুনরা ভাবেন আউটপুট “ভেঙে গেছে”। শেষ লাইনে println ব্যবহার করাই নিরাপদ অভ্যাস।

লেখা জোড়া দেওয়া — + চিহ্নের দুই রূপ

Java-তে দুটি String-এর মাঝে + দিলে সেগুলো জুড়ে যায়: "Cha " + "15 tk" হয় "Cha 15 tk". একে বলে string concatenation. String-এর সাথে সংখ্যা জুড়লে সংখ্যাটিও লেখায় রূপ নেয়: "Dam: " + 15 হয় "Dam: 15".

কিন্তু এখানে একটি ফাঁদ আছে। + চিহ্ন বাঁ থেকে ডানে কাজ করে, আর যেই মুহূর্তে একদিকে একটি String পায়, তখন থেকে সে যোগ নয়, জোড়া দেয়। চায়ের দোকানের রসিদ দিয়ে দেখুন — শেষ দুই লাইনে কী ঘটে:

class Main {
    public static void main(String[] args) {
        // রফিক মামার দোকানের আজকের রসিদ
        System.out.println("=== Rafiq Tea Stall ===");
        System.out.println("Item\t\tPrice");
        System.out.println("Cha (milk)\t" + 15 + " tk");
        System.out.println("Singara x2\t" + 2 * 10 + " tk");
        System.out.println("Biscuit\t\t" + 5 + " tk");
        System.out.println("-----------------------");

        // মোট: আগে সংখ্যাগুলো যোগ, তারপর " tk" জোড়া
        System.out.print("Total:\t\t");
        System.out.println(15 + 2 * 10 + 5 + " tk");

        // ফাঁদ: String আগে থাকলে + আর যোগ করে না, জোড়া দেয়
        System.out.println("Wrong total: " + 15 + 20 + 5);
        System.out.println("Right total: " + (15 + 20 + 5));
    }
}

রসিদের সারিগুলো সোজা দাঁড়িয়েছে \t-এর জন্য — এটি একটি tab, যা কার্সরকে পরের নির্দিষ্ট ঘর পর্যন্ত সরিয়ে দেয় (সাধারণত প্রতি ৮ অক্ষরে একটি ঘর)। ছোট নামের পরে (Item, Biscuit) দুটি tab, লম্বা নামের পরে একটি — তাই দাম একই কলামে এসেছে। 2 * 10 আগে গুণ হয়ে 20 হয়েছে, কারণ গুণের অগ্রাধিকার +-এর চেয়ে বেশি।

মোটের লাইনে 15 + 2 * 10 + 5 সব সংখ্যা, তাই আগে যোগ হয়ে 40, তারপর " tk" জুড়ে 40 tk. কিন্তু “Wrong total” লাইনে বাঁ দিকে প্রথমেই String, তাই "Wrong total: " + 15 হয়ে গেল "Wrong total: 15", তারপর তার সাথে "20", তারপর "5" — ফল 15205! বন্ধনী দিলে ((15 + 20 + 5)) আগে যোগ হয়, ফল ঠিক 40. দোকানের হিসাবে এই ভুল হলে খদ্দের ১৫ হাজার টাকার বিল পাবেন — তাই অভ্যাস করুন: String-এর সাথে হিসাব মেশালে হিসাবটি বন্ধনীতে রাখুন। অপারেটরের অগ্রাধিকার পর্ব ০৭-এ বিস্তারিত।

Escape sequence — যে অক্ষর সরাসরি লেখা যায় না

String শুরু আর শেষ হয় " দিয়ে। তাহলে লেখার ভেতরে একটি কোট চিহ্ন দেবেন কীভাবে? বা নতুন লাইন? এর জন্য আছে escape sequence — একটি backslash (\) আর তার পরের একটি অক্ষর মিলে একটি বিশেষ অক্ষর বোঝায়:

লিখবেনমানেউদাহরণ
\nনতুন লাইন (newline)"Line 1\nLine 2" → দুই লাইনে ছাপা
\tTab — পরের কলাম পর্যন্ত ফাঁকারসিদের সারি সাজাতে
\"লেখার ভেতরে কোট চিহ্ন"He said \"Hi\"" → He said "Hi"
\\একটি backslash"C:\\Users" → C:\Users

এবার এসব একসাথে — বাংলায় একটি নববর্ষের শুভেচ্ছা-কার্ড। Java শুরু থেকেই Unicode সমর্থন করে, তাই বাংলা লেখা সরাসরি String-এ রাখা যায়:

/**
 * নববর্ষের শুভেচ্ছা-কার্ড ছাপে।
 * কার্ডের ওপরে-নিচে একই মাপের দাগ রাখা হয়েছে, যাতে ফ্রেমের মতো দেখায়।
 */
class Main {
    public static void main(String[] args) {
        String name = "নুসরাত"; // প্রতি বছর শুধু এই নামটি বদলাই

        System.out.println("*************************");
        System.out.println("  প্রিয় " + name + ",");
        System.out.println("  শুভ নববর্ষ!\n  নতুন বছর ভালো কাটুক।");
        System.out.println("  দাদু বলেন: \"রোজ একটু একটু শেখা চাই।\"");
        System.out.println("\t— ভালোবাসাসহ, রাফি");
        System.out.println("*************************");
        /* পরের বছর যোগ করব:
           ছবি আর রঙিন লেখা */
    }
}

প্রথমে চোখে পড়ে /** … */ — এটি Javadoc comment, যা দিয়ে class বা method-এর পরিচয় লেখা হয় (পরের অংশে বিস্তারিত)। String name = "নুসরাত"; একটি variable — একটি নাম দেওয়া বাক্স, যার ভেতরে লেখাটি রাখা হলো; পর্ব ০৬-এ variable বিস্তারিত শিখবেন। আজ শুধু দেখুন, " প্রিয় " + name + "," তিনটি টুকরো জুড়ে একটি লাইন বানিয়েছে।

তৃতীয় println-এ একটি \n আছে, তাই একটি statement থেকেই দুটি লাইন ছাপা হয়েছে। দাদুর কথাটি কোটের ভেতরে এসেছে \"-এর জন্য — এটি ছাড়া compiler ভাবত String ওখানেই শেষ, আর error দিত। \t “ভালোবাসাসহ” লাইনটিকে একটু ডানে সরিয়েছে। আর শেষের /* … */ comment-টি প্রোগ্রামের কোনো আউটপুটে আসেনি — compiler comment পুরোপুরি বাদ দেয়।

নিজের কম্পিউটারে বাংলা ভাঙা দেখালে (যেমন ??? বা অদ্ভুত চিহ্ন), সমস্যা সাধারণত Java-র নয়, terminal-এর font বা encoding-এর। Java 18 থেকে source ফাইলের ডিফল্ট encoding UTF-8, তাই ফাইল UTF-8-এ সেভ করলেই চলে। পুরোনো Windows Command Prompt-এ বাংলা ঠিকমতো দেখাতে সমস্যা হতে পারে; Windows Terminal বা IDE-র ভেতরের console সাধারণত ঠিকঠাক দেখায়।

printf — এক ঝলক

Tab দিয়ে সাজানো সহজ, কিন্তু নাম খুব লম্বা হলে সারি এলোমেলো হয়ে যায়। পেশাদার উপায় হলো printf — যেখানে আপনি “ছাঁচ” বলে দেন: কত ঘর জায়গা, বাঁয়ে না ডানে। নিচের দুই লাইন অনলাইন runner-এ যাচাই করা:

System.out.printf("%-12s%5d tk%n", "Cha", 15);
System.out.printf("%-12s%5d tk%n", "Singara", 20);
Cha            15 tk
Singara        20 tk

%-12s মানে “একটি লেখা, ১২ ঘর জায়গায়, বাঁ দিক ঘেঁষে”; %5d মানে “একটি পূর্ণসংখ্যা, ৫ ঘরে, ডান দিক ঘেঁষে”; %n মানে নতুন লাইন। এই ছাঁচের পুরো ভাষা পর্ব ০৯-এ শিখবেন — আজ শুধু জেনে রাখুন যে এটি আছে।

৬ · ব্যাকরণ — statement, বন্ধনী, indentation আর comment

প্রতিটি ভাষার যেমন ব্যাকরণ আছে, Java-রও আছে — একে বলে syntax. বাংলায় দাঁড়ি ভুল হলে পাঠক তবু বুঝে নেন; কিন্তু compiler একটুও ছাড় দেয় না। প্রথম দিনেই চারটি নিয়ম জেনে নিন।

১. প্রতিটি statement শেষ হয় semicolon দিয়ে

Java লাইন দেখে না, ; দেখে। চাইলে দুটি statement এক লাইনে লেখা যায় (System.out.print("A"); System.out.print("B");), আবার একটি লম্বা statement কয়েক লাইনে ভাঙা যায় — compiler-এর কাছে সব সমান। তবে মানুষের জন্য নিয়ম: এক লাইনে একটি statement. মনে রাখবেন, class বা method-এর শিরোনামের পরে (class Main {) semicolon বসে না — সেখানে block শুরু হয়।

২. Block থাকে বন্ধনীর ভেতরে, আর বন্ধনী জোড়ায় জোড়ায়

প্রতিটি {-এর একটি } চাই। class-এর block-এর ভেতরে method-এর block, পরে তার ভেতরে if বা loop-এর block — বাক্সের ভেতরে বাক্স। একটি বন্ধনী হারালে compiler ফাইলের শেষে গিয়ে অভিযোগ করে, কারণ সে শেষ পর্যন্ত বন্ধ বন্ধনীটি খুঁজতেই থাকে।

৩. Indentation — compiler-এর জন্য নয়, মানুষের জন্য

Python-এ indentation (লাইনের শুরুর ফাঁকা জায়গা) ব্যাকরণের অংশ। Java-তে নয় — পুরো প্রোগ্রাম এক লাইনে লিখলেও compile হবে। তাহলে ফাঁকা জায়গা কেন? কারণ কোড লেখা হয় একবার, কিন্তু পড়া হয় শতবার। নিচের দুটি কোড compiler-এর কাছে হুবহু এক:

// পড়া কঠিন — কিন্তু compile হয়
class Main{public static void main(String[] args){System.out.println("Hi");}}

// পড়া সহজ — প্রতিটি block ৪ ঘর ভেতরে
class Main {
    public static void main(String[] args) {
        System.out.println("Hi");
    }
}

প্রচলিত প্রথা: প্রতি স্তরে ৪টি space, খোলা বন্ধনী একই লাইনের শেষে, বন্ধ বন্ধনী নিজের লাইনে। IntelliJ IDEA-তে Ctrl+Alt+L (Mac-এ Cmd+Option+L) চাপলে IDE নিজেই সাজিয়ে দেয়। ভালো indentation-এর আরেকটি লাভ: কোন } কোন {-এর জোড়া, তা এক নজরে দেখা যায় — ফলে হারানো বন্ধনী খুঁজে পাওয়া সহজ।

৪. বড় হাত আর ছোট হাত আলাদা

Java case-sensitive: System আর system দুটি সম্পূর্ণ আলাদা নাম। Main আর main-ও আলাদা। ছোট হাতে system.out.println(…) লিখলে javac যা বলে, সেটি নতুনদের প্রায়ই বিভ্রান্ত করে:

prog.java:3: error: package system does not exist
        system.out.println("Hello, Dhaka!");
              ^
1 error

“package” কোথা থেকে এলো? compiler system নামে কোনো class চেনে না, তাই ধরে নিয়েছে এটি হয়তো কোনো package-এর নাম (package হলো class রাখার ফোল্ডারের মতো, পরের পর্বগুলোতে আসবে) — আর সেটিও খুঁজে পায়নি। মেসেজের শব্দ অদ্ভুত হলেও ^ চিহ্নটি ঠিক জায়গাটিই দেখাচ্ছে। শিক্ষা: মেসেজ পুরো না বুঝলেও লাইন নম্বর আর ^-এর জায়গাটি দেখুন।

Comment — কোডের পাশে মানুষের জন্য নোট

Comment হলো এমন লেখা, যা compiler পুরোপুরি বাদ দেয়। Java-তে তিন রকম:

রূপকতটুকুকখন ব্যবহার
// …লাইনের শেষ পর্যন্তছোট ব্যাখ্যা — সবচেয়ে বেশি ব্যবহার হয়
/* … */যত লাইন খুশিলম্বা ব্যাখ্যা, বা সাময়িকভাবে কিছু কোড বন্ধ রাখা
/** … */যত লাইন খুশিJavadoc — class/method-এর আনুষ্ঠানিক পরিচয়, যা থেকে javadoc টুল HTML ডকুমেন্টেশন বানায়

Java-র নিজের ডকুমেন্টেশন — যেখানে String বা System-এর প্রতিটি method-এর ব্যাখ্যা আছে — সেটি এই Javadoc comment থেকেই তৈরি। অর্থাৎ JDK-এর source code-এর ভেতরের /** … */ লেখাগুলোই আপনি ওয়েবসাইটে পড়েন।

ভালো comment কেমন

খারাপ comment কোড যা বলছে তা-ই আবার বলে: // 15 প্রিন্ট করো — এটি তো কোড দেখেই বোঝা যায়। ভালো comment বলে কেন: // দুধ-চা ১৫ টাকা: গত মাস থেকে নতুন দাম. ছয় মাস পরে কোড খুললে “কী হচ্ছে” আপনি পড়ে বুঝবেন; কিন্তু “কেন এমন করা হয়েছিল” — সেটি comment না থাকলে হারিয়ে যায়।

নতুন Java-র একটি সুবিধা — ছোট main (এই কোর্সে ব্যবহার হবে না)

নতুনদের জন্য পাঁচ লাইনের Hello World একটু ভারী — এই অভিযোগ বহু বছরের। তাই Java ধাপে ধাপে একটি সহজ রূপ এনেছে। Java 21-এ এটি প্রথম আসে preview feature হিসেবে (JEP 445) — অর্থাৎ পরীক্ষামূলক, বিশেষ flag ছাড়া চলে না। কয়েকটি সংস্করণে বদল আর উন্নতির পর Java 25-এ এটি স্থায়ী হয় (JEP 512, নাম “compact source files and instance main methods”). Java 25-এ পুরো প্রোগ্রাম এমন হতে পারে:

// শুধু Java 25 বা তার পরের সংস্করণে
void main() {
    IO.println("Hello, Dhaka!");
}

এখানে class লেখা নেই (compiler নিজেই একটি class বানিয়ে নেয়), main static নয়, public নয়, String[] args-ও নেই। এই কোর্সের runner-এ আছে Java 21, যেখানে এটি এখনো preview. অনলাইন runner-এ চালিয়ে দেখা গেছে, Java 21 এমন কোড পেলে বলে:

prog.java:1: error: unnamed classes are a preview feature and are disabled by default.
void main() {
^
  (use --enable-preview to enable unnamed classes)
1 error

তাই এই কোর্সে আমরা প্রচলিত public static void main(String[] args)-ই ব্যবহার করব। কারণ শুধু runner নয় — আজকের বেশিরভাগ চাকরির কোডবেস, বই, ইন্টারভিউ প্রশ্ন আর Android/Spring প্রজেক্ট এই রূপেই লেখা। নতুন রূপটি চিনে রাখুন, কোথাও দেখলে যেন অবাক না হন।

৭ · javac-এর error পড়তে শিখুন

প্রথম সপ্তাহে আপনি সম্ভবত যত কোড চালাবেন, তার চেয়ে বেশি error দেখবেন। এতে লজ্জার কিছু নেই — অভিজ্ঞ প্রোগ্রামাররাও প্রতিদিন error দেখেন। পার্থক্য হলো, তাঁরা মেসেজটি পড়েন। একটি javac compile error-এর চারটি অংশ:

prog.java:3: error: ';' expected
        System.out.println("Hello, Dhaka!")
                                           ^
1 error
  • prog.java:3 — কোন ফাইল, কোন লাইন। নিজের কম্পিউটারে এখানে দেখবেন আপনার ফাইলের নাম, যেমন Main.java:3.
  • error: ';' expected — সমস্যার বর্ণনা: এখানে একটি semicolon আশা করা হয়েছিল।
  • সেই লাইনের কপি আর ^ — ঠিক কোন অক্ষরে compiler আটকেছে। এখানে বন্ধনী শেষ হওয়ার ঠিক পরে।
  • 1 error — মোট কতটি error. সংখ্যা বেশি হলেও ঘাবড়াবেন না; প্রায়ই একটি মূল ভুল থেকে বাকিগুলো জন্মায়।

নতুনদের সবচেয়ে সাধারণ ভুলগুলো, আর javac সেগুলো দেখে কী বলে — সবগুলো মেসেজ অনলাইন runner-এ (OpenJDK 21) যাচাই করা:

ভুলjavac যা বলেসমাধান
Statement-এর শেষে ; নেইerror: ';' expected^-এর জায়গায় ; দিন
println-এর বানান ভুল (printline)error: cannot find symbol, সাথে symbol: method printline(String)বানান ঠিক করুন
শেষের } নেইerror: reached end of file while parsingবন্ধনী গুনে হারানোটি যোগ করুন
public class-এর নাম ≠ ফাইলের নামerror: class Hello is public, should be declared in a file named Hello.javaফাইলের নাম বদলান
System-কে ছোট হাতে লেখাerror: package system does not existবড় হাতের S

cannot find symbol মেসেজটি পুরো দেখতে এমন:

prog.java:4: error: cannot find symbol
        System.out.printline("Bye");
                  ^
  symbol:   method printline(String)
  location: variable out of type PrintStream
1 error

এটি Java-র সবচেয়ে পরিচিত error. symbol মানে কোনো নাম — class, method বা variable-এর। মেসেজ বলছে: “printline নামে, একটি String নেয় এমন কোনো method আমি খুঁজে পাইনি।” কোথায় খুঁজেছে? out-এর ভেতরে, যার টাইপ PrintStream (out আসলে PrintStream class-এর একটি object). এই symbol: আর location: লাইন দুটি পড়লে প্রায় সবসময় বানান ভুলটি ধরা পড়ে।

এবার একটি বাস্তব দৃশ্য — একটি প্রোগ্রামে তিনটি ভুল একসাথে। দেখুন javac কোন ক্রমে সেগুলো দেখায়। প্রতিটি মেসেজ অনলাইন runner থেকে হুবহু নেওয়া:

prog.java → javacপ্রথম চেষ্টা
class Main {
    public static void main(String[] args) {
        System.out.println("Hello, Dhaka!")_
        System.out.printline("Bye");
    }
_

prog.java:3: error: ';' expected
        System.out.println("Hello, Dhaka!")
                                           ^
prog.java:5: error: reached end of file while parsing
    }
     ^
2 errors
prog.java → javacদ্বিতীয় চেষ্টা — ; যোগ করা হলো
class Main {
    public static void main(String[] args) {
        System.out.println("Hello, Dhaka!");
        System.out.printline("Bye");
    }
_

prog.java:5: error: reached end of file while parsing
    }
     ^
1 error
prog.java → javacতৃতীয় চেষ্টা — } যোগ করা হলো
class Main {
    public static void main(String[] args) {
        System.out.println("Hello, Dhaka!");
        System.out.printline("Bye");
    }
}

prog.java:4: error: cannot find symbol
        System.out.printline("Bye");
                  ^
  symbol:   method printline(String)
  location: variable out of type PrintStream
1 error
prog.java → javac → javaশেষ সংশোধন — এবার চলল
class Main {
    public static void main(String[] args) {
        System.out.println("Hello, Dhaka!");
        System.out.println("Bye");
    }
}

Hello, Dhaka!
Bye
  1. প্রথম চেষ্টা: দুটি error. কোডে আসলে তিনটি ভুল — লাইন ৩-এ ; নেই, লাইন ৪-এ printline, আর শেষে class-এর } নেই (লাল দাগ)। কিন্তু javac দেখাল দুটি: ';' expected আর reached end of file while parsing. বানানের ভুলটির কথা কিছুই বলেনি! কারণ javac কাজ করে ধাপে ধাপে — আগে parsing (ব্যাকরণ ঠিক আছে কি না), সেটি পার হলে তবেই নাম যাচাই। ব্যাকরণে ভুল থাকলে নাম যাচাইয়ের ধাপে পৌঁছায়ই না। নিয়ম: সবসময় ওপরের প্রথম error আগে ঠিক করুন, তারপর আবার compile.
  2. দ্বিতীয় চেষ্টা: হারানো বন্ধনী। ; বসাতেই প্রথম error চলে গেল। বাকি রইল reached end of file while parsing — “ফাইল শেষ হয়ে গেল, অথচ আমি তখনো একটি } খুঁজছিলাম।” খেয়াল করুন, লাইন নম্বর ৫ দেখাচ্ছে — ফাইলের শেষ লাইন — কিন্তু ভুলটি আসলে “কোথাও একটি বন্ধনী কম”. এখানে indentation কাজে আসে: class Main {-এর বন্ধনীর জোড়া নেই।
  3. তৃতীয় চেষ্টা: এবার লুকানো ভুলটি বেরোল। ব্যাকরণ এখন ঠিক, তাই javac নাম যাচাই করল — আর পেল printline. এতক্ষণ এই ভুলটি লুকিয়ে ছিল। নতুনরা এখানে প্রায়ই হতাশ হন: “একটা ঠিক করলাম, আরেকটা এলো!” আসলে এটাই অগ্রগতি — compiler এক ধাপ এগিয়েছে।
  4. শেষ সংশোধন: চলল। printline → println. কোনো error নেই, প্রোগ্রাম চলল, দুই লাইন ছাপা হলো। তিনটি ভুল, তিনটি ধরন: বিরামচিহ্ন (;), কাঠামো (}), নাম (printline). প্রতিবার শুধু প্রথম error পড়ে ঠিক করে আবার চালানো — এই সরল অভ্যাসই সবচেয়ে দ্রুত পথ।

চলার সময়ের ভুল — exception-এর এক ঝলক

সব ভুল compile-এর সময় ধরা পড়ে না। কিছু ভুল ঘটে চালানোর সময় — যেমন শূন্য দিয়ে ভাগ। তখন Java একটি exception ছোড়ে, আর কেউ সেটি না সামলালে প্রোগ্রাম থেমে যায়। লাইন ৫-এ 100 / cups (যেখানে cups শূন্য) রাখা একটি প্রোগ্রাম চালালে আউটপুট আসে এমন:

Start
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at Main.main(prog.java:5)

একে বলে stack trace. পড়ার নিয়ম: "main" — কোন thread-এ ঘটেছে (আপাতত সবসময় main); java.lang.ArithmeticException — কী ধরনের সমস্যা; / by zero — বিস্তারিত; আর at Main.main(prog.java:5) — কোন class, কোন method, কোন ফাইলের কোন লাইনে। খেয়াল করুন, Start ঠিকই ছাপা হয়েছিল — সমস্যার আগের লাইনগুলো চলেছে, পরেরগুলো চলেনি। Exception কীভাবে ধরতে ও সামলাতে হয়, তা পর্ব ২৯-এ শিখবেন।

পরীক্ষা ও ইন্টারভিউতে
  • main method কেন static? — প্রোগ্রাম শুরুর সময় কোনো object থাকে না; static হলে JVM object না বানিয়েই class-এর নাম দিয়ে main ডাকতে পারে।
  • main public না হলে কী হয়? — compile হয়, কিন্তু (Java 21 পর্যন্ত প্রচলিত নিয়মে) JVM একে প্রবেশপথ হিসেবে মানে না এবং main খুঁজে না পাওয়ার error দেয়।
  • একটি .java ফাইলে কয়টি public class থাকতে পারে? — বড়জোর একটি, আর তার নাম ফাইলের নামের সাথে হুবহু মিলতে হয়।
  • print আর println-এর পার্থক্য? — দুটোই ছাপে; println শেষে নতুন লাইনে যায়, print একই লাইনে থাকে।
  • "Sum: " + 2 + 3-এর আউটপুট কী? — Sum: 23, কারণ বাঁ দিকে String থাকায় প্রতিটি + জোড়া দেয়; "Sum: " + (2 + 3) দিলে Sum: 5.

৮ · AI-এর যুগে — error নিয়ে AI-এর সাথে কাজ

Compile error পেলে AI-কে জিজ্ঞেস করা এখন খুব স্বাভাবিক — আর এটা ভালো অভ্যাসও, যদি ঠিকভাবে করেন। সমস্যা হলো, বেশিরভাগ মানুষ লেখেন “আমার Java কোড চলছে না, ঠিক করে দাও” — কোনো error ছাড়া, কোনো লাইন নম্বর ছাড়া। তখন AI অনুমান করে, আর অনুমান প্রায়ই ভুল হয়।

Error মেসেজ হলো compiler-এর লেখা চিঠি।
AI-কে চিঠির সারাংশ নয়, পুরো চিঠিটাই দিন।

AI সাধারণত যে ভুলগুলো করে

AI যা করেকেন বিপজ্জনকআপনি যা করবেন
Error-এর লাইনটি মুছে দিয়ে বলে “এখন চলবে”Error গেল, কিন্তু সেই লাইনের কাজটিও গেলআগের আর নতুন কোড পাশাপাশি মিলিয়ে দেখুন — কোনো লাইন হারাল কি না
পুরো কোড নতুন করে লিখে দেয়আপনার নাম, হিসাব, যুক্তি বদলে যেতে পারে; কী বদলাল বোঝা যায় নাবলুন: “শুধু যে লাইন বদলাতে হবে, সেটুকু দেখাও”
public class Main দেয়, আপনার ফাইলের নাম অন্য“should be declared in a file named…” errorফাইলের নাম আর class-এর নাম মিলিয়ে নিন
নতুন Java-র রূপ দেয় (void main(), IO.println)Java 21 বা পুরোনো JDK-তে compile হয় নাপ্রশ্নে আপনার Java version লিখে দিন

নিচের কাঠামোয় প্রশ্ন করুন। তিনটি জিনিস অবশ্যই থাকবে — Java version, পুরো কোড, আর পুরো error, লাইন নম্বরসহ। শেষ দুটি নির্দেশ AI-কে কোড মুছে ফেলা থেকে আটকায়:

আমি Java 21 (OpenJDK) দিয়ে নিচের প্রোগ্রাম compile করছি। কমান্ড: javac Main.java [এখানে পুরো কোড পেস্ট করো] javac এই error দিচ্ছে (হুবহু কপি করা): [এখানে পুরো error মেসেজ, ফাইলের নাম আর লাইন নম্বরসহ] ১. শুধু প্রথম error-টি নিয়ে বলো — সহজ বাংলায়, এটি কেন হলো? ২. পুরো কোড আবার লিখো না। শুধু যে লাইন বদলাতে হবে, আগের আর পরের রূপ পাশাপাশি দেখাও। ৩. কোনো লাইন মুছে ফেলবে না, আর আমার লেখা String বা হিসাব বদলাবে না। মুছতেই হলে আগে কারণ বলো।

AI-এর দেওয়া সমাধান হাতে পেলে — যাচাইয়ের চেকলিস্ট

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন। এগুলোই আপনাকে কোড-লেখক থেকে সিস্টেম-চিন্তক বানাবে।

প্র ০১main method কেন static হতে হয়? JVM কি একটি object বানিয়ে তার main ডাকতে পারত না?

প্রশ্নটি আসলে একটি “ডিম আগে না মুরগি আগে” সমস্যা। একটি সাধারণ (non-static) method ডাকতে হলে আগে সেই class-এর একটি object লাগে — যেমন একটি নির্দিষ্ট দোকানের হিসাবের খাতা খুলতে হলে আগে দোকানটি থাকতে হয়। কিন্তু প্রোগ্রাম শুরুর মুহূর্তে মেমরিতে আপনার কোনো object নেই। Object বানানো হবে main-এর ভেতরের কোড দিয়ে — অথচ main-ই এখনো চলেনি।

static এই চক্র ভাঙে। static method class-এর, কোনো নির্দিষ্ট object-এর নয়। তাই JVM শুধু class-টি load করেই Main.main(args) ডাকতে পারে, কোনো object ছাড়া। এটাই সবচেয়ে সরল আর অনুমানযোগ্য নিয়ম।

তাহলে JVM নিজে একটি object বানাল না কেন? প্রযুক্তিগতভাবে সম্ভব, কিন্তু প্রশ্ন ওঠে: কোন constructor ডাকবে? Constructor যদি parameter চায়, তখন কী দেবে? Constructor-এর ভেতরে কোনো কাজ (যেমন ফাইল খোলা) থাকলে সেটি main-এর আগেই ঘটবে — বিভ্রান্তিকর। ১৯৯০-এর দশকে Java-র নকশাকারেরা C-র পরিচিত ধারা মেনে “একটি স্থির প্রবেশপথ, কোনো object ছাড়া” বেছে নেন।

মজার ব্যাপার: প্রায় তিন দশক পরে Java ঠিক সেই বিকল্প পথটিই খুলেছে। Java 25-এর instance main method-এ (অংশ ৬) main static না হলে launcher class-টির parameter ছাড়া constructor দিয়ে একটি object বানায়, তারপর তার main ডাকে। তবে সেখানেও নিয়ম আছে: পুরোনো static main থাকলে সেটিই আগে বেছে নেওয়া হয়। অর্থাৎ শুরুর সিদ্ধান্তটি ভুল ছিল না — শুধু নতুনদের জন্য একটি সহজ দরজা যোগ হয়েছে।

এই প্রশ্ন ইন্টারভিউতে প্রায়ই আসে, কারণ উত্তর থেকে বোঝা যায় আপনি static আর object-এর সম্পর্ক বোঝেন কি না। পর্ব ১৮-এ static নিয়ে বিস্তারিত দেখবেন — তখন এই উত্তরটি আরও পরিষ্কার হবে।

মূল উপলব্ধি: প্রবেশপথ এমন হতে হয়, যা কোনো পূর্বশর্ত ছাড়াই খোলা যায়। static main সেই শর্তহীন দরজা — object-এর জগৎ শুরু হয় তার পরে।

প্র ০২প্রায় সব ভাষার প্রথম প্রোগ্রাম কেন “Hello, World”? এই প্রথা কোথা থেকে এলো, আর এর আসল কাজ কী?

প্রথাটির শুরু Bell Labs-এ, Brian Kernighan-এর হাতে। ১৯৭০-এর দশকের শুরুতে B ভাষার একটি টিউটোরিয়ালে তিনি একটি উদাহরণে “hello, world” ছাপার কোড লেখেন। পরে C ভাষার টিউটোরিয়ালেও এটি আসে, আর ১৯৭৮ সালে Kernighan ও Dennis Ritchie-র বই The C Programming Language-এর প্রথম উদাহরণ হয়ে এটি বিশ্বজুড়ে ছড়িয়ে পড়ে। সেই বই এত প্রভাবশালী ছিল যে পরের প্রায় প্রতিটি ভাষার বই — C++, Java, Python — একই প্রথা মেনে চলে।

কিন্তু এর আসল কাজ প্রথা রক্ষা নয় — পুরো যন্ত্রপাতি পরীক্ষা। Hello World সফলভাবে চলা মানে একসাথে অনেক কিছু ঠিক আছে: compiler ইনস্টল হয়েছে, PATH ঠিক আছে, ফাইল সঠিক নামে সঠিক জায়গায় আছে, compile হচ্ছে, JVM চলছে, আর আউটপুট স্ক্রিনে আসছে। প্রকৌশলের ভাষায় একে বলা যায় “smoke test” — যন্ত্র চালু করে দেখা ধোঁয়া বেরোয় কি না। জটিল কিছু লেখার আগে এই ছোট পরীক্ষাটি পাস করা জরুরি; নইলে পরে একটি বড় প্রোগ্রামে error এলে বুঝবেন না দোষ কোডের, না সেটআপের।

পেশাদার জগতেও এই চিন্তা আছে। নতুন সার্ভার, নতুন framework বা নতুন cloud সার্ভিস নিয়ে কাজ শুরুর সময় প্রকৌশলীরা প্রথমে সবচেয়ে ছোট “Hello World” সংস্করণটি চালান — একটি পাতা যা শুধু “OK” দেখায়, বা একটি API যা শুধু একটি লেখা ফেরত দেয়। পর্ব ৫০-এ Spring Boot শুরুর সময় আপনিও ঠিক এটাই করবেন।

Java-র Hello World আরেকটি জিনিস দেখায়: ভাষার দর্শন। C-তে এটি একটি ফাংশন, Python-এ এক লাইন, আর Java-তে একটি class-এর ভেতরে static method. একটি ভাষার Hello World দেখেই বোঝা যায় তার নকশাকারেরা কোন জিনিসকে সবচেয়ে গুরুত্ব দিয়েছেন।

মূল উপলব্ধি: যেকোনো নতুন সিস্টেমে প্রথমে সবচেয়ে ছোট কাজটি পুরো পথ ঘুরিয়ে চালান। পথ পরিষ্কার হলে তবেই বোঝা চাপান।

প্র ০৩Java কেন C/C++-এর মতো দেখতে? নতুন ভাষা তো সম্পূর্ণ নতুন চেহারায়ও বানানো যেত।

এটি ছিল একটি সচেতন ব্যবসায়িক ও প্রকৌশল সিদ্ধান্ত। ১৯৯০-এর দশকের শুরুতে Sun Microsystems-এ James Gosling-এর দল যখন ভাষাটি বানাচ্ছিল, তখন পেশাদার সফটওয়্যার জগতে C আর C++-এর দাপট। লাখো প্রোগ্রামার প্রতিদিন { }, ;, if (…), for (…;…;…) লিখতেন। একটি নতুন ভাষার সবচেয়ে বড় বাধা হলো শেখার খরচ — মানুষ সহজে নতুন অভ্যাস নেয় না।

১৯৯০-এর দশকের মাঝামাঝি Gosling ও Henry McGilton-এর লেখা Java-র শ্বেতপত্রে (white paper) ভাষার প্রথম তিন বৈশিষ্ট্য বলা হয়েছিল: simple, object-oriented, আর familiar. “Familiar” মানে ঠিক এটাই — C++ প্রোগ্রামার যেন Java কোড দেখে প্রথম দিনেই মোটামুটি পড়তে পারেন। তাই চেহারা রাখা হলো পরিচিত।

কিন্তু ভেতরে অনেক কিছু ইচ্ছা করে বাদ দেওয়া হয়েছিল — যেগুলো C++-এ বাগের বড় উৎস ছিল: pointer arithmetic (মেমরির ঠিকানা নিয়ে সরাসরি অঙ্ক), নিজে হাতে মেমরি মুক্ত করা (Java-তে garbage collector করে, পরের পর্বে দেখবেন), একাধিক class থেকে inheritance, preprocessor আর header ফাইল। ফলে Java দেখতে C++-এর মতো, কিন্তু আচরণে অনেক নিরাপদ। একে বলা যায় “পরিচিত পোশাকে নতুন মানুষ”।

কৌশলটি কাজ করেছিল। C/C++ থেকে বিপুল সংখ্যক প্রোগ্রামার দ্রুত Java-তে এলেন। পরে C# (Microsoft, ২০০০) একই পথ ধরে, আর আজ JavaScript, Kotlin, Swift, Go, Rust — প্রায় সবার চেহারায় C পরিবারের ছাপ। অন্যদিকে ঝুঁকিও ছিল: C-র কিছু অদ্ভুত অভ্যাসও Java উত্তরাধিকারসূত্রে পেয়েছে — যেমন switch-এ break ভুলে গেলে পরের case-এ গড়িয়ে যাওয়া। নতুন Java সেটি ঠিক করতে switch expression এনেছে (পর্ব ১০)।

মূল উপলব্ধি: একটি প্রযুক্তি কেবল ভালো হলেই চলে না, মানুষকে তার কাছে আসতে হয়। পরিচিত চেহারা দিয়ে শেখার খরচ কমানো, আর ভেতরে নিরাপত্তা বাড়ানো — এটাই ছিল Java-র সাফল্যের বড় কারণগুলোর একটি।

প্র ০৪Java ২৫ বছরেরও বেশি সময় পাঁচ লাইনের Hello World রেখেছিল। Java 21 থেকে 25-এর মধ্যে এটি কীভাবে সহজ হলো, আর এত সময় লাগল কেন?

শিক্ষকদের বহু পুরোনো অভিযোগ ছিল: প্রথম দিনেই শিক্ষার্থীকে public, static, void, String[] — চারটি অবোধ্য শব্দ দেখাতে হয়, আর বলতে হয় “পরে বুঝবেন”। ২০২২ সালে Java ভাষার স্থপতি Brian Goetz “Paving the on-ramp” নামে একটি লেখায় এই সমস্যার সমাধানের দিক তুলে ধরেন। এরপর পরিবর্তনটি এলো কয়েকটি JEP (JDK Enhancement Proposal)-এর মধ্য দিয়ে, ধাপে ধাপে:

  • Java 21 — JEP 445 (প্রথম preview): নাম ছিল “unnamed classes and instance main methods”. class ছাড়া void main() লেখা যায়, তবে শুধু --enable-preview দিলে।
  • Java 22 — JEP 463 (দ্বিতীয় preview): ধারণাটির নাম বদলে হলো “implicitly declared classes”, আর main খোঁজার নিয়ম সরল করা হলো।
  • Java 23 — JEP 477 (তৃতীয় preview): সহজে ইনপুট-আউটপুটের জন্য একটি ছোট helper class যোগ হলো, আর এমন ফাইলে কিছু প্রচলিত class আলাদা import ছাড়াই পাওয়ার ব্যবস্থা।
  • Java 24 — JEP 495 (চতুর্থ preview): নাম হলো “simple source files”, আরও কিছু খুঁটিনাটি পরিমার্জন।
  • Java 25 — JEP 512 (স্থায়ী): “compact source files and instance main methods” — preview থেকে বেরিয়ে আসা স্থায়ী বৈশিষ্ট্য, সাথে IO.println-এর মতো সহজ method.

এত সময় কেন? কারণ Java-র সবচেয়ে বড় প্রতিশ্রুতি হলো backward compatibility — বিশ বছর আগের কোডও আজকের JVM-এ চলতে হবে। ভাষায় যা একবার স্থায়ী হয়, তা আর ফেরানো যায় না। তাই Java এখন নতুন বৈশিষ্ট্য আগে “preview” হিসেবে দেয়, মানুষ ব্যবহার করে মতামত দেয়, নকশা বদলায় — নাম পর্যন্ত বদলেছে তিনবার। প্রতি ছয় মাসে নতুন Java সংস্করণ আসে বলে এই চক্র দ্রুত ঘোরে।

আরেকটি গুরুত্বপূর্ণ নকশা-নীতি: সহজ রূপটি কোনো আলাদা “শিশুদের Java” নয়। Compiler পেছনে একটি সাধারণ class-ই বানায়। প্রোগ্রাম বড় হলে শিক্ষার্থী শুধু চারপাশে class লিখে দেন — কিছু ফেলে দিতে হয় না।

মূল উপলব্ধি: লাখো প্রজেক্ট যে ভাষার ওপর দাঁড়িয়ে, সেখানে একটি ছোট পরিবর্তনও পরীক্ষা, মতামত আর ধৈর্যের মধ্য দিয়ে আসে। Preview ব্যবস্থা হলো “আগে চেখে দেখুন, পরে কিনুন” — ভাষার বিবর্তনের নিরাপদ পথ।

প্র ০৫javac-এর error মেসেজ কেন সময়ের সাথে আরও সহায়ক হয়েছে? একটি ভালো error মেসেজের বৈশিষ্ট্য কী?

Compiler-এর error মেসেজ আসলে একটি ইউজার ইন্টারফেস — আর এর ব্যবহারকারী প্রোগ্রামার। পুরোনো দিনের অনেক compiler শুধু জানাত “syntax error at line 12” — কী ভুল, কোথায় ঠিক, কিছুই না। ধারণা ছিল, প্রোগ্রামার নিজেই বুঝে নেবেন। কিন্তু প্রোগ্রামিং যত মানুষের কাছে ছড়াল, তত স্পষ্ট হলো যে অস্পষ্ট মেসেজ শেখার পথে সবচেয়ে বড় বাধাগুলোর একটি।

javac-এর মেসেজ বছরের পর বছর ধাপে ধাপে উন্নত হয়েছে। এই পর্বেই দেখেছেন আজকের মেসেজে কী কী থাকে: ফাইল আর লাইন নম্বর, লাইনের কপি, ^ দিয়ে নির্দিষ্ট অক্ষর, আর cannot find symbol-এর সাথে symbol: ও location: — কী খোঁজা হচ্ছিল, কোথায়। JDK 7-এর সময় javac-এ মেসেজ সাজানোর একটি উন্নত ব্যবস্থা যোগ হয়, যা জটিল generic টাইপের error-কেও পড়ার উপযোগী করে। চলার সময়ের দিকেও উন্নতি হয়েছে: Java 14-এ এসেছে “helpful NullPointerException” (JEP 358), যা Java 15 থেকে ডিফল্টভাবে চালু — আগে শুধু বলত NullPointerException, এখন বলে ঠিক কোন variable null ছিল আর কোন কাজটি করা যায়নি।

এই উন্নতির পেছনে প্রতিযোগিতাও কাজ করেছে। C/C++ জগতে Clang-এর পরিষ্কার মেসেজ GCC-কে উন্নত হতে বাধ্য করে; Elm আর Rust-এর মতো নতুন ভাষা “বন্ধুসুলভ error” দিয়ে সুনাম কুড়ায়। প্রোগ্রামাররা এখন ভালো মেসেজ আশা করেন।

ভালো error মেসেজের বৈশিষ্ট্য: (১) কোথায় — নির্দিষ্ট লাইন ও কলাম; (২) কী — সমস্যার স্পষ্ট নাম; (৩) কেন — প্রেক্ষাপট, যেমন “কোথায় খুঁজেছি”; (৪) সম্ভব হলে সমাধানের ইঙ্গিত — যেমন “should be declared in a file named Hello.java”. তবু মনে রাখুন, compiler আপনার উদ্দেশ্য জানে না — সে শুধু জানে কোথায় নিয়ম ভেঙেছে। তাই কখনো কখনো মেসেজ আসল ভুলের পরের জায়গা দেখায় (যেমন হারানো বন্ধনীর জন্য ফাইলের শেষ)।

মূল উপলব্ধি: Error মেসেজ শত্রু নয়, আপনার জন্য লেখা একটি নির্দেশিকা। আপনি নিজে যখন সফটওয়্যার বানাবেন, ব্যবহারকারীকে ঠিক এমন মেসেজ দিন — কোথায়, কী, কেন, আর এখন কী করবেন।

অনুশীলন

বেশিরভাগ কাজে নতুন কোড লিখতে হবে না — ওপরের কোড বদলে দেখা আর ভাবাই আসল কাজ।

  1. Error ইচ্ছা করে ঘটান: রসিদের কোডে (অংশ ৫) একে একে তিনটি কাজ করুন, প্রতিবার চালান, তারপর আগের অবস্থায় ফেরান — (ক) কোনো একটি ; মুছুন, (খ) println-কে Println লিখুন, (গ) শেষের } মুছুন। প্রতিবার কোন মেসেজ এলো?

    (ক) error: ';' expected, সেই লাইনের নম্বরসহ, আর ^ ঠিক যেখানে ; থাকার কথা। (খ) error: cannot find symbol, সাথে symbol: method Println(String) — Java case-sensitive, তাই Println আর println আলাদা নাম। (গ) error: reached end of file while parsing, লাইন নম্বর হিসেবে ফাইলের শেষ লাইন। ইচ্ছা করে error ঘটানো একটি দারুণ অভ্যাস — আসল কাজের সময় মেসেজটি দেখেই চিনে ফেলবেন।

  2. আউটপুট অনুমান করুন: না চালিয়ে বলুন, এই চারটি লাইন কী ছাপবে — System.out.println(1 + 2 + "3");, System.out.println("1" + 2 + 3);, System.out.println("1" + (2 + 3));, System.out.println(1 + 2 + "3" + 4 + 5);

    প্রথম: 33 — বাঁ থেকে শুরু, 1 + 2 দুটোই সংখ্যা, তাই 3; তারপর "3" জোড়া লেগে 33. দ্বিতীয়: 123 — শুরুতেই String, তাই সব জোড়া। তৃতীয়: 15 — বন্ধনীর ভেতরে আগে 2 + 3 = 5, তারপর "1"-এর সাথে জোড়া। চতুর্থ: 3345 — 1 + 2 = 3, তারপর "3" এসে String হয়ে গেল, তার পরের 4 আর 5 শুধু জোড়া লাগল। নিয়ম একটাই: বাঁ থেকে ডানে, আর String দেখা দেওয়ার পর থেকে সব + জোড়া দেয়।

  3. নিজের কার্ড বানান: শুভেচ্ছা-কার্ডের কোড বদলে আপনার পরিবারের কারও জন্য একটি জন্মদিনের কার্ড বানান। শর্ত: অন্তত একবার \n, একবার \" আর একবার \t ব্যবহার করবেন, আর একটি comment লিখবেন যা “কী” নয়, “কেন” বলে।

    একটি সম্ভাব্য রূপ (main-এর ভেতরের অংশ):

    // আম্মুর প্রিয় কথাটি রাখলাম, যাতে কার্ডটি তাঁর নিজের মনে হয়
    System.out.println("প্রিয় আম্মু,\nশুভ জন্মদিন!");
    System.out.println("আম্মুর কথা: \"আগে পড়া, পরে খেলা।\"");
    System.out.println("\t— ভালোবাসাসহ, রাফি");

    খেয়াল করুন comment-টি কেন সেই লাইনটি রাখা হয়েছে তা বলছে — কোড পড়ে যা বোঝা যায় না। যাচাই করুন: কোট চিহ্ন ঠিকমতো ছাপা হচ্ছে কি না, আর প্রথম println থেকে দুটি লাইন আসছে কি না।

  4. Stack trace পড়ুন: একজন বন্ধু নিচের আউটপুট পাঠিয়ে বলল “আমার প্রোগ্রাম কিছুই করে না।” তিনটি প্রশ্নের উত্তর দিন — প্রোগ্রাম কি compile হয়েছিল? কোন লাইনে থেমেছে? সমস্যার আগের লাইনগুলো কি চলেছিল? Bill shuru / Exception in thread "main" java.lang.ArithmeticException: / by zero / at Main.main(Main.java:7)

    হ্যাঁ, compile হয়েছিল — exception আসে শুধু চালানোর সময়; compile না হলে প্রোগ্রাম চলতই না, আর error: দিয়ে শুরু মেসেজ আসত। থেমেছে Main.java-এর লাইন ৭-এ, Main class-এর main method-এ — সেখানে কোনো সংখ্যাকে শূন্য দিয়ে ভাগ করা হয়েছে। আগের লাইনগুলো চলেছিল — প্রমাণ, Bill shuru ছাপা হয়েছে। তাই “কিছুই করে না” কথাটি ঠিক নয়; প্রোগ্রাম কাজ শুরু করেছিল, লাইন ৭-এ এসে থেমেছে। বন্ধুকে বলুন লাইন ৭-এর ভাজক (যে সংখ্যা দিয়ে ভাগ হচ্ছে) কোথা থেকে শূন্য পাচ্ছে, সেটি খুঁজতে।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমএকটি Java প্রোগ্রাম লেখা থেকে চলা শেষ পর্যন্ত ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. ✍️ Main.java ফাইলে public class Main লেখা
  2. ⚙️ javac Main.java — compile করে Main.class তৈরি
  3. ▶️ java Main — JVM চালু হয়ে class load করে
  4. 🚪 JVM main method খুঁজে ডাকে
  5. 📄 main-এর statement-গুলো ওপর থেকে নিচে চলে, তারপর প্রোগ্রাম শেষ

Java প্রোগ্রামের entry point হিসেবে প্রচলিত main method-এর সঠিক রূপ কোনটি?

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

একটি ফাইলের নাম Shop.java, আর তার ভেতরে লেখা public class Main. compile করলে কী হবে?

  • ঠিকঠাক compile হবে, তৈরি হবে Shop.class
  • javac নিজেই class-এর নাম বদলে Shop করে দেবে
  • compile error: public class Main থাকতে হবে Main.java ফাইলে
  • compile হবে, কিন্তু চালানোর সময় exception আসবে

System.out.println("Total: " + 10 + 5); — এই লাইনটি কী ছাপবে?

  • Total: 15
  • Total: 10 + 5
  • compile error
  • Total: 105

javac দেখাল: error: reached end of file while parsing. সবচেয়ে সম্ভাব্য কারণ কোনটি?

  • কোনো একটি খোলা { বন্ধনীর জোড়া } নেই
  • println-এর বানান ভুল
  • ফাইলের নাম আর class-এর নাম মেলেনি
  • কোথাও শূন্য দিয়ে ভাগ করা হয়েছে

Java-তে indentation (লাইনের শুরুর ফাঁকা জায়গা) সম্পর্কে কোন কথাটি সঠিক?

  • Indentation ভুল হলে Java compile হয় না
  • compiler একে উপেক্ষা করে, তবু কোড পড়া আর ভুল খোঁজার জন্য এটি জরুরি
  • বেশি indentation দিলে প্রোগ্রাম ধীরে চলে
  • Java-তে শুধু tab দিয়ে indentation করা যায়

AI-কে একটি Java compile error ঠিক করতে বলার সময় সবচেয়ে কার্যকর তথ্য কোনটি?

  • শুধু বলা: “আমার কোড চলছে না, ঠিক করে দাও”
  • error-টি নিজের ভাষায় সংক্ষেপে বলা
  • Java version, পুরো কোড আর লাইন নম্বরসহ হুবহু error মেসেজ
  • শুধু যে লাইনে error, সেই একটি লাইন

শব্দকোষ

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

মনে রাখুন

  1. Java-তে সব কোড একটি class-এর ভেতরে; JVM শুরু করে public static void main(String[] args) থেকে।
  2. static মানে object ছাড়াই ডাকা যায় — প্রোগ্রাম শুরুর সময় কোনো object থাকে না বলেই main static.
  3. public class Main থাকবে Main.java-তে; এই কোর্সের অনলাইন runner-এ শুধু class Main লিখি।
  4. print একই লাইনে, println নতুন লাইনে; String-এর সাথে + জোড়া দেয়, হিসাব রাখুন বন্ধনীতে; \n, \t, \" বিশেষ অক্ষর।
  5. Error এলে প্রথম error আগে পড়ুন — ফাইল, লাইন, ^; AI-কে দিন পুরো মেসেজ, আর খেয়াল রাখুন সে যেন কোড মুছে না দেয়।

পরের পর্বে: আজ javac আর java দুটি কমান্ড চালালেন। কিন্তু Main.class-এর ভেতরে আসলে কী আছে? একই ফাইল কীভাবে Windows, Linux আর Mac-এ চলে? JVM, bytecode, JIT আর garbage collector — Java-র ইঞ্জিনঘরে ঢুকব।

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

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