📘 موضوع: Dependency Injection در جاوا — مفهوم و اهمیت آن در طراحی شیءگرا
در برنامهنویسی شیءگرا، کلاسها معمولاً برای انجام کارهای خود به اشیای دیگر نیاز دارند.
به این اشیای وابسته، Dependency (وابستگی) گفته میشود.
اما نحوهی ایجاد و مدیریت این وابستگیهاست که تفاوت بین کد ضعیف و کد قابلتوسعه و تستپذیر را مشخص میکند.
🔹 ۱. مشکل: وابستگی مستقیم بین کلاسها
فرض کنید کلاس Car برای کار کردن به یک Engine نیاز دارد 👇
در نگاه اول ساده است، اما یک مشکل بزرگ دارد:
کلاس Car خودش تصمیم گرفته که چطور Engine را بسازد.
اگر روزی بخواهید نوع موتور را تغییر دهید (مثلاً از Engine به ElectricEngine)، باید کد Car را تغییر دهید ❌
یعنی Car به Engine وابسته شده و این برخلاف اصل Open/Closed Principle از SOLID است.
🔹 ۲. راهحل: تزریق وابستگی (Dependency Injection)
در روش Dependency Injection، به جای اینکه کلاس خودش وابستگی را بسازد،
ما آن را از بیرون تزریق میکنیم (از طریق سازنده، Setter یا Interface).
📘 مثال با Constructor Injection:
در اینجا، Car دیگر مسئول ساخت Engine نیست — فقط از آن استفاده میکند.
در نتیجه میتوانیم نوع موتور را در آینده بهراحتی تغییر دهیم، بدون دست زدن به کد Car ✅
🔹 ۳. انواع Dependency Injection
1. Constructor Injection → تزریق از طریق سازنده (مثل مثال بالا)
2. Setter Injection → تزریق از طریق متد Setter
3. Interface Injection → وابستگی از طریق متدی در Interface تزریق میشود
📘 مثال Setter Injection:
🔹 ۴. مزایای استفاده از Dependency Injection
✅ کاهش Coupling (وابستگی مستقیم) بین کلاسها
✅ افزایش Testability (قابل تست شدن راحتتر)
✅ افزایش Reusability (قابل استفاده مجدد بودن کلاسها)
✅ رعایت اصول SOLID مخصوصاً Open/Closed و Single Responsibility
📘 مثال تست راحتتر با DI:
در اینجا، بدون تغییر در کلاس Car`، یک `MockEngine تزریق کردیم تا تست انجام شود.
🔹 ۵. Dependency Injection در فریمورکها (مثل Spring)
فریمورکهایی مانند Spring این فرایند را بهصورت خودکار انجام میدهند.
یعنی فقط با استفاده از Annotationهایی مانند @Component و `@Autowired`،
Spring خودش وابستگیها را میسازد و تزریق میکند.
📘 مثال:
در این حالت، Spring Container خودش متوجه میشود که Car به Engine نیاز دارد و آن را تزریق میکند.
در برنامهنویسی شیءگرا، کلاسها معمولاً برای انجام کارهای خود به اشیای دیگر نیاز دارند.
به این اشیای وابسته، Dependency (وابستگی) گفته میشود.
اما نحوهی ایجاد و مدیریت این وابستگیهاست که تفاوت بین کد ضعیف و کد قابلتوسعه و تستپذیر را مشخص میکند.
🔹 ۱. مشکل: وابستگی مستقیم بین کلاسها
فرض کنید کلاس Car برای کار کردن به یک Engine نیاز دارد 👇
class Engine {
void start() {
System.out.println("Engine started!");
}
}
class Car {
private Engine engine = new Engine(); // وابستگی مستقیم!
void drive() {
engine.start();
System.out.println("Car is moving!");
}
}
در نگاه اول ساده است، اما یک مشکل بزرگ دارد:
کلاس Car خودش تصمیم گرفته که چطور Engine را بسازد.
اگر روزی بخواهید نوع موتور را تغییر دهید (مثلاً از Engine به ElectricEngine)، باید کد Car را تغییر دهید ❌
یعنی Car به Engine وابسته شده و این برخلاف اصل Open/Closed Principle از SOLID است.
🔹 ۲. راهحل: تزریق وابستگی (Dependency Injection)
در روش Dependency Injection، به جای اینکه کلاس خودش وابستگی را بسازد،
ما آن را از بیرون تزریق میکنیم (از طریق سازنده، Setter یا Interface).
📘 مثال با Constructor Injection:
class Engine {
void start() {
System.out.println("Engine started!");
}
}
class Car {
private Engine engine;
// وابستگی از بیرون تزریق میشود
public Car(Engine engine) {
this.engine = engine;
}
void drive() {
engine.start();
System.out.println("Car is moving!");
}
}
public class Main {
public static void main(String[] args) {
Engine engine = new Engine();
Car car = new Car(engine); // تزریق وابستگی
car.drive();
}
}
در اینجا، Car دیگر مسئول ساخت Engine نیست — فقط از آن استفاده میکند.
در نتیجه میتوانیم نوع موتور را در آینده بهراحتی تغییر دهیم، بدون دست زدن به کد Car ✅
🔹 ۳. انواع Dependency Injection
1. Constructor Injection → تزریق از طریق سازنده (مثل مثال بالا)
2. Setter Injection → تزریق از طریق متد Setter
3. Interface Injection → وابستگی از طریق متدی در Interface تزریق میشود
📘 مثال Setter Injection:
class Car {
private Engine engine;
public void setEngine(Engine engine) {
this.engine = engine;
}
void drive() {
engine.start();
System.out.println("Car is moving!");
}
}
🔹 ۴. مزایای استفاده از Dependency Injection
✅ کاهش Coupling (وابستگی مستقیم) بین کلاسها
✅ افزایش Testability (قابل تست شدن راحتتر)
✅ افزایش Reusability (قابل استفاده مجدد بودن کلاسها)
✅ رعایت اصول SOLID مخصوصاً Open/Closed و Single Responsibility
📘 مثال تست راحتتر با DI:
class MockEngine extends Engine {
void start() {
System.out.println("Mock engine started (for testing)");
}
}
public class Test {
public static void main(String[] args) {
Car car = new Car(new MockEngine());
car.drive(); // تست بدون اجرای موتور واقعی
}
}
در اینجا، بدون تغییر در کلاس Car`، یک `MockEngine تزریق کردیم تا تست انجام شود.
🔹 ۵. Dependency Injection در فریمورکها (مثل Spring)
فریمورکهایی مانند Spring این فرایند را بهصورت خودکار انجام میدهند.
یعنی فقط با استفاده از Annotationهایی مانند @Component و `@Autowired`،
Spring خودش وابستگیها را میسازد و تزریق میکند.
📘 مثال:
@Component
class Engine {
void start() {
System.out.println("Engine started!");
}
}
@Component
class Car {
private final Engine engine;
@Autowired
public Car(Engine engine) {
this.engine = engine;
}
void drive() {
engine.start();
System.out.println("Car is moving!");
}
}
در این حالت، Spring Container خودش متوجه میشود که Car به Engine نیاز دارد و آن را تزریق میکند.
👍7❤1
✅ جمعبندی نهایی:
* در واقع Dependency Injection یعنی واگذاری کنترل ساخت وابستگیها به بیرون از کلاس.
* این کار باعث میشود کد ما منعطفتر، تستپذیرتر و تمیزتر شود.
* این مفهوم پایهی اصلی فریمورکهایی مانند Spring است و یکی از اصول مهم طراحی شیءگرا مدرن به شمار میرود.
* در واقع Dependency Injection یعنی واگذاری کنترل ساخت وابستگیها به بیرون از کلاس.
* این کار باعث میشود کد ما منعطفتر، تستپذیرتر و تمیزتر شود.
* این مفهوم پایهی اصلی فریمورکهایی مانند Spring است و یکی از اصول مهم طراحی شیءگرا مدرن به شمار میرود.
#کاربرـپیشرفته
🆔 @javapro_ir
🆔 @group_javapro
❤8👍1
✳️ کار با JSON در جاوا — آشنایی با Jackson و Gson
در برنامهنویسی مدرن، JSON یکی از پرکاربردترین فرمتها برای ذخیره و تبادل دادهها است. در جاوا، دو کتابخانهی بسیار محبوب برای کار با JSON وجود دارد: Jackson و Gson. هر دو امکان تبدیل (Serialization) و برعکستبدیل (Deserialization) اشیاء جاوا به JSON را فراهم میکنند.
🔹 ۱. کتابخانهی Jackson
درواقع Jackson یکی از قدرتمندترین ابزارهای کار با JSON در جاواست که توسط FasterXML توسعه داده شده و در بسیاری از فریمورکها (مثل Spring Boot) بهصورت پیشفرض استفاده میشود.
📘 نمونهی کد:
📍 خروجی:
📘 ویژگیهای مهم Jackson:
* پشتیبانی از Annotationها مثل @JsonProperty و @JsonIgnore
* پشتیبانی از Map، List، و Genericها
* کارایی بالا در پردازش دادههای حجیم
🔹 ۲. کتابخانهی Gson
کتابخانهی Gson محصول شرکت Google است و بهدلیل سادگی و حجم کم، در پروژههای سبکتر بسیار محبوب است.
📘 نمونهی کد:
📍 خروجی مشابه Jackson است:
📘 ویژگیهای مهم Gson:
* پشتیبانی از انواع Collectionها
* امکان کنترل دقیق Serialization با Annotationهایی مانند @Expose
* سادگی در استفاده و پیادهسازی
🧠 جمعبندی:
اگر در پروژههای بزرگ و سازمانی کار میکنید یا از فریمورکهایی مثل Spring Boot استفاده میکنید، کتابخانهی Jackson انتخاب بهتری است چون سریعتر، انعطافپذیرتر و سازگارتر با سیستمهای بزرگ است.
اما اگر پروژهی شما سبکتر است یا در محیطهایی مثل اندروید کار میکنید، کتابخانهی Gson بهدلیل سادگی و سبک بودن، گزینهی ایدهآلی محسوب میشود.
در برنامهنویسی مدرن، JSON یکی از پرکاربردترین فرمتها برای ذخیره و تبادل دادهها است. در جاوا، دو کتابخانهی بسیار محبوب برای کار با JSON وجود دارد: Jackson و Gson. هر دو امکان تبدیل (Serialization) و برعکستبدیل (Deserialization) اشیاء جاوا به JSON را فراهم میکنند.
🔹 ۱. کتابخانهی Jackson
درواقع Jackson یکی از قدرتمندترین ابزارهای کار با JSON در جاواست که توسط FasterXML توسعه داده شده و در بسیاری از فریمورکها (مثل Spring Boot) بهصورت پیشفرض استفاده میشود.
📘 نمونهی کد:
import com.fasterxml.jackson.databind.ObjectMapper;
class User {
public String name;
public int age;
}
public class JacksonExample {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
// شیء جاوا به JSON
User user = new User();
user.name = "Saleh";
user.age = 25;
String json = mapper.writeValueAsString(user);
System.out.println("JSON: " + json);
// JSON به شیء جاوا
User newUser = mapper.readValue(json, User.class);
System.out.println("Name: " + newUser.name);
}
}
📍 خروجی:
JSON: {"name":"Saleh","age":25}
Name: Saleh
📘 ویژگیهای مهم Jackson:
* پشتیبانی از Annotationها مثل @JsonProperty و @JsonIgnore
* پشتیبانی از Map، List، و Genericها
* کارایی بالا در پردازش دادههای حجیم
🔹 ۲. کتابخانهی Gson
کتابخانهی Gson محصول شرکت Google است و بهدلیل سادگی و حجم کم، در پروژههای سبکتر بسیار محبوب است.
📘 نمونهی کد:
import com.google.gson.Gson;
class User {
String name;
int age;
}
public class GsonExample {
public static void main(String[] args) {
Gson gson = new Gson();
// شیء جاوا به JSON
User user = new User();
user.name = "Saleh";
user.age = 25;
String json = gson.toJson(user);
System.out.println("JSON: " + json);
// JSON به شیء جاوا
User newUser = gson.fromJson(json, User.class);
System.out.println("Name: " + newUser.name);
}
}
📍 خروجی مشابه Jackson است:
JSON: {"name":"Saleh","age":25}
Name: Saleh
📘 ویژگیهای مهم Gson:
* پشتیبانی از انواع Collectionها
* امکان کنترل دقیق Serialization با Annotationهایی مانند @Expose
* سادگی در استفاده و پیادهسازی
🧠 جمعبندی:
اگر در پروژههای بزرگ و سازمانی کار میکنید یا از فریمورکهایی مثل Spring Boot استفاده میکنید، کتابخانهی Jackson انتخاب بهتری است چون سریعتر، انعطافپذیرتر و سازگارتر با سیستمهای بزرگ است.
اما اگر پروژهی شما سبکتر است یا در محیطهایی مثل اندروید کار میکنید، کتابخانهی Gson بهدلیل سادگی و سبک بودن، گزینهی ایدهآلی محسوب میشود.
#کاربرـحرفهـای
🆔 @javapro_ir
🆔 @group_javapro
👍6❤1
ما در شریف کلینیک به دنبال افراد باانگیزه و باتجربه برای موقعیتهای زیر هستیم 👇
💻 Java (Mid / Senior)
⚙️ Laravel (Mid / Senior)
📱 Flutter (Mid / Senior)
🌐 Next.js / React (Mid / Senior)
اگر در یکی از این حوزهها تجربه و علاقه دارید،
📩 رزومهتون رو به ایمیل زیر ارسال کنید:
[email protected]
🏃♂️ تماموقت | حضوری
📍 محل کار: شریف کلینیک
⚡️ @javapro_ir✈️ @group_javapro
Please open Telegram to view this post
VIEW IN TELEGRAM
✳️ کار با JsonNode و Tree Model در Jackson — دسترسی به دادههای JSON بدون نیاز به ساخت کلاس
در بسیاری از مواقع، ممکن است بخواهید به دادههای داخل یک فایل یا رشتهی JSON دسترسی پیدا کنید بدون اینکه ابتدا کلاس جاوایی (POJO) برای آن بسازید. در این حالت، کتابخانهی Jackson راهکاری قدرتمند به نام Tree Model API ارائه میدهد که با استفاده از کلاس `JsonNode`، امکان پیمایش و خواندن دادهها را بهصورت درختی فراهم میکند.
🔹 ۱. مفهوم Tree Model در Jackson
در این مدل، دادهی JSON مانند یک درخت در نظر گرفته میشود که شامل گرهها (Nodes) است.
هر گره میتواند یک Object،Array، یا Value باشد.
کلاس اصلی برای کار با این مدل، `JsonNode` است که از طریق `ObjectMapper` ساخته میشود.
🔹 ۲. نمونهی کد — خواندن و دسترسی به دادهها
📍 خروجی برنامه:
🔹 ۳. بررسی دقیقتر JsonNode
* متد get() برای دسترسی به یک کلید خاص در شیء JSON استفاده میشود.
* متد asText()`، `asInt() و سایر متدهای asType() برای تبدیل مقدار گره به نوع دادهی مورد نظر کاربرد دارند.
* میتوانید با متد isArray() و isObject() نوع گره را بررسی کنید.
🔹 ۴. مثال پیشرفتهتر — پیمایش روی آرایهها
📍 خروجی:
🧠 جمعبندی:
استفاده از JsonNode و Tree Model در Jackson زمانی مفید است که:
* ساخت کلاس برای JSON ضروری نیست یا دادهها پویا هستند.
* میخواهید تنها بخشی از داده را بخوانید.
* نیاز دارید ساختار JSON را بررسی یا تحلیل کنید.
اگر دادههای JSON ساختار ثابتی دارند، بهتر است از Data Binding (با کلاسهای جاوا) استفاده کنید، اما اگر دادهها پویا یا ناشناختهاند، Tree Model بهترین گزینه است.
در بسیاری از مواقع، ممکن است بخواهید به دادههای داخل یک فایل یا رشتهی JSON دسترسی پیدا کنید بدون اینکه ابتدا کلاس جاوایی (POJO) برای آن بسازید. در این حالت، کتابخانهی Jackson راهکاری قدرتمند به نام Tree Model API ارائه میدهد که با استفاده از کلاس `JsonNode`، امکان پیمایش و خواندن دادهها را بهصورت درختی فراهم میکند.
🔹 ۱. مفهوم Tree Model در Jackson
در این مدل، دادهی JSON مانند یک درخت در نظر گرفته میشود که شامل گرهها (Nodes) است.
هر گره میتواند یک Object،Array، یا Value باشد.
کلاس اصلی برای کار با این مدل، `JsonNode` است که از طریق `ObjectMapper` ساخته میشود.
🔹 ۲. نمونهی کد — خواندن و دسترسی به دادهها
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonNodeExample {
public static void main(String[] args) throws Exception {
String json = """
{
"name": "Saleh",
"age": 25,
"skills": ["Java", "Spring", "Networking"],
"address": {
"city": "Tehran",
"country": "Iran"
}
}
""";
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(json);
// دسترسی به مقادیر
String name = root.get("name").asText();
int age = root.get("age").asInt();
String firstSkill = root.get("skills").get(0).asText();
String city = root.get("address").get("city").asText();
System.out.println("Name: " + name);
System.out.println("Age: " + age);
System.out.println("First Skill: " + firstSkill);
System.out.println("City: " + city);
}
}
📍 خروجی برنامه:
Name: Saleh
Age: 25
First Skill: Java
City: Tehran
🔹 ۳. بررسی دقیقتر JsonNode
* متد get() برای دسترسی به یک کلید خاص در شیء JSON استفاده میشود.
* متد asText()`، `asInt() و سایر متدهای asType() برای تبدیل مقدار گره به نوع دادهی مورد نظر کاربرد دارند.
* میتوانید با متد isArray() و isObject() نوع گره را بررسی کنید.
🔹 ۴. مثال پیشرفتهتر — پیمایش روی آرایهها
for (JsonNode skill : root.get("skills")) {
System.out.println("Skill: " + skill.asText());
}
📍 خروجی:
Skill: Java
Skill: Spring
Skill: Networking
🧠 جمعبندی:
استفاده از JsonNode و Tree Model در Jackson زمانی مفید است که:
* ساخت کلاس برای JSON ضروری نیست یا دادهها پویا هستند.
* میخواهید تنها بخشی از داده را بخوانید.
* نیاز دارید ساختار JSON را بررسی یا تحلیل کنید.
اگر دادههای JSON ساختار ثابتی دارند، بهتر است از Data Binding (با کلاسهای جاوا) استفاده کنید، اما اگر دادهها پویا یا ناشناختهاند، Tree Model بهترین گزینه است.
#کاربرـحرفهـای
🆔 @javapro_ir
🆔 @group_javapro
👍3
✳️ موضوع: Pattern Matching در switch — ویژگی قدرتمند از جاوا 17 به بعد
در نسخههای جدید جاوا، یکی از تغییرات مهم و زیبا، اضافه شدن Pattern Matching در عبارتهای switch است. این ویژگی باعث میشود کدهای شرطی ما خواناتر، کوتاهتر و ایمنتر از نظر نوع داده (Type-Safe) شوند.
🔹 ۱. مشکل در نسخههای قدیمیتر
در نسخههای قدیمی جاوا، وقتی از
برای بررسی نوع (type) یک شیء، مجبور بودیم از
کد بالا تکراری و مستعد خطاست. جاوا 17 با اضافه کردن Pattern Matching در switch این مشکل را به شکلی ظریف و هوشمند حل کرد.
🔹 ۲. Pattern Matching در switch — نسخهی جدید و تمیزتر
در نسخههای جدید، میتوانیم مستقیماً نوع متغیر را در case تعریف کنیم، بدون نیاز به casting دستی:
📍 توضیح:
* در
* نیازی به
* مقدار بازگشتی با فلش
🔹 ۳. مثال کامل از کاربرد عملی
📍 خروجی برنامه:
🔹 ۴. ویژگی جالب – استفاده از شرط اضافی (when clause)
عبارت
در مثال بالا،
🔹 ۵. مزایای Pattern Matching در switch
* حذف کدهای تکراری و نیاز به cast دستی
* افزایش ایمنی نوع دادهها (Type Safety)
* افزایش خوانایی و سادگی کد
* امکان ترکیب شرطها با
🧠 جمعبندی:
ویژگی Pattern Matching در switch یکی از گامهای بزرگ جاوا به سمت کدنویسی تابعیتر و خواناتر است.
این قابلیت نهتنها از نظر ظاهری زیباتر است، بلکه خطاهای احتمالی ناشی از تبدیل نوع را نیز کاهش میدهد.
در نسخههای جدید جاوا، یکی از تغییرات مهم و زیبا، اضافه شدن Pattern Matching در عبارتهای switch است. این ویژگی باعث میشود کدهای شرطی ما خواناتر، کوتاهتر و ایمنتر از نظر نوع داده (Type-Safe) شوند.
🔹 ۱. مشکل در نسخههای قدیمیتر
در نسخههای قدیمی جاوا، وقتی از
switch استفاده میکردیم، فقط نوعهای ساده مانند int, String یا enum پشتیبانی میشدند.برای بررسی نوع (type) یک شیء، مجبور بودیم از
instanceof استفاده کنیم و سپس آن را cast کنیم:static String format(Object obj) {
if (obj instanceof Integer) {
Integer i = (Integer) obj;
return "Integer: " + i;
} else if (obj instanceof String) {
String s = (String) obj;
return "String: " + s;
} else {
return "Unknown Type";
}
}کد بالا تکراری و مستعد خطاست. جاوا 17 با اضافه کردن Pattern Matching در switch این مشکل را به شکلی ظریف و هوشمند حل کرد.
🔹 ۲. Pattern Matching در switch — نسخهی جدید و تمیزتر
در نسخههای جدید، میتوانیم مستقیماً نوع متغیر را در case تعریف کنیم، بدون نیاز به casting دستی:
static String format(Object obj) {
return switch (obj) {
case Integer i -> "Integer: " + i;
case String s -> "String: " + s.toUpperCase();
case null -> "Null value detected!";
default -> "Unknown Type";
};
}📍 توضیح:
* در
case Integer i، اگر نوع ورودی Integer باشد، بهصورت خودکار متغیر i ساخته میشود.* نیازی به
instanceof یا cast دستی نیست.* مقدار بازگشتی با فلش
-> تعریف میشود و در یک خط قابل نوشتن است.🔹 ۳. مثال کامل از کاربرد عملی
public class PatternMatchingSwitch {
public static void main(String[] args) {
System.out.println(describe(42));
System.out.println(describe("Saleh"));
System.out.println(describe(3.14));
System.out.println(describe(null));
}
static String describe(Object obj) {
return switch (obj) {
case Integer i -> "Integer number: " + i;
case String s when s.length() > 5 -> "Long String: " + s;
case String s -> "Short String: " + s;
case Double d -> "Double number: " + d;
case null -> "Null value!";
default -> "Unknown type";
};
}
}📍 خروجی برنامه:
Integer number: 42
Long String: Saleh
Double number: 3.14
Null value!
🔹 ۴. ویژگی جالب – استفاده از شرط اضافی (when clause)
عبارت
when در جاوا 21 به switch اضافه شد و به شما اجازه میدهد برای هر case شرط خاصی تعریف کنید.در مثال بالا،
case String s when s.length() > 5 فقط زمانی اجرا میشود که مقدار obj رشتهای و طول آن بیشتر از ۵ کاراکتر باشد.🔹 ۵. مزایای Pattern Matching در switch
* حذف کدهای تکراری و نیاز به cast دستی
* افزایش ایمنی نوع دادهها (Type Safety)
* افزایش خوانایی و سادگی کد
* امکان ترکیب شرطها با
when برای کنترل دقیقتر🧠 جمعبندی:
ویژگی Pattern Matching در switch یکی از گامهای بزرگ جاوا به سمت کدنویسی تابعیتر و خواناتر است.
این قابلیت نهتنها از نظر ظاهری زیباتر است، بلکه خطاهای احتمالی ناشی از تبدیل نوع را نیز کاهش میدهد.
#کاربرـحرفهـای
🆔 @javapro_ir
🆔 @group_javapro
👍9❤1
🎓 موضوع: Generics در جاوا — حذف Type Casting و افزایش ایمنی نوع دادهها
در زبان Java، ویژگی Generics از نسخهی 5 معرفی شد تا بتوانیم نوع داده (Type) را بهصورت پارامتری تعریف کنیم. هدف اصلی Generics، افزایش ایمنی نوع (Type Safety) و حذف نیاز به Type Casting دستی است.
بهعنوان مثال:
در نسخههای قدیمیتر:
🔹 Type Parameters
نوع پارامترها معمولاً با حروف زیر نمایش داده میشوند:
*
*
*
*
مثلاً:
🔹 Wildcards (
در واقع Wildcards به ما اجازه میدهند با انواع نامشخص کار کنیم.
مثلاً:
اما در این حالت فقط میتوانیم بخوانیم، نه بنویسیم (به جز مقدار
🔹 تفاوت بین
*
🔸 نمیتوان در آن مقدار جدید اضافه کرد (بهجز
*
🔸 میتوان هر شیءای در آن قرار داد (String، Integer، و ...).
بنابراین
✅ جمعبندی
کلاس Generics در جاوا باعث میشود:
1. کد تمیزتر و امنتر باشد 🧩
2. از خطاهای زمان اجرا جلوگیری شود 💡
3. نیازی به Type Casting نباشد 🔒
در زبان Java، ویژگی Generics از نسخهی 5 معرفی شد تا بتوانیم نوع داده (Type) را بهصورت پارامتری تعریف کنیم. هدف اصلی Generics، افزایش ایمنی نوع (Type Safety) و حذف نیاز به Type Casting دستی است.
بهعنوان مثال:
List<String> names = new ArrayList<>();
names.add("Saleh");
String first = names.get(0); // نیازی به Cast نیست ✅
در نسخههای قدیمیتر:
List names = new ArrayList();
names.add("Saleh");
String first = (String) names.get(0); // نیاز به Cast ❌
🔹 Type Parameters
نوع پارامترها معمولاً با حروف زیر نمایش داده میشوند:
*
T → Type (نوع عمومی)*
E → Element (در Collectionها)*
K, V → Key و Value (در Mapها)*
? → Wildcard (نوع نامشخص)مثلاً:
class Box<T> {
private T value;
public void set(T value) { this.value = value; }
public T get() { return value; }
}🔹 Wildcards (
?)در واقع Wildcards به ما اجازه میدهند با انواع نامشخص کار کنیم.
مثلاً:
List<?> list = new ArrayList<String>();
اما در این حالت فقط میتوانیم بخوانیم، نه بنویسیم (به جز مقدار
null).🔹 تفاوت بین
List<?> و List<Object>*
List<?> یعنی لیستی از هر نوع (unknown type).🔸 نمیتوان در آن مقدار جدید اضافه کرد (بهجز
null).*
List<Object> یعنی لیستی که *حتماً* از نوع Object است.🔸 میتوان هر شیءای در آن قرار داد (String، Integer، و ...).
بنابراین
List<?> و List<Object> با هم یکسان نیستند.✅ جمعبندی
کلاس Generics در جاوا باعث میشود:
1. کد تمیزتر و امنتر باشد 🧩
2. از خطاهای زمان اجرا جلوگیری شود 💡
3. نیازی به Type Casting نباشد 🔒
#کاربرـپیشرفته
🆔 @javapro_ir
🆔 @group_javapro
👍7❤3
🎓موضوع: Bounded Generics در جاوا — محدودسازی نوع پارامترها با `extends` و `super`
در ادامهی مبحث Generics، حالا به یکی از ویژگیهای مهم آن میرسیم:
✅ مبحث Bounded Type Parameters
این ویژگی به ما اجازه میدهد نوع پارامتر Generic را محدود کنیم تا فقط از نوع خاصی (یا زیرکلاس آن) استفاده شود.
🔹 Upper Bound (`extends`)
وقتی از extends استفاده میکنیم، یعنی نوع پارامتر باید از یک کلاس خاص ارثبری کند یا یک اینترفیس خاص را پیادهسازی کرده باشد.
مثلاً:
✅ حالا فقط کلاسهایی مثل Integer, Double, Float و سایر زیرکلاسهای Number مجاز هستند:
🔹 Lower Bound (`super`)
وقتی از super در Wildcard استفاده میکنیم، یعنی نوع پارامتر باید ابرکلاس (Superclass) نوع مشخصشده باشد.
این روش معمولاً هنگام نوشتن دادهها در Collection بهکار میرود.
مثلاً:
اما هنگام خواندن از لیست، نوع بازگشتی فقط به صورت Object شناخته میشود.
🔹 نکته کاربردی: PECS اصل معروف در Generics
PECS = Producer Extends, Consumer Super
* اگر فقط از مجموعه میخوانی (Producer) ➤ از extends استفاده کن
* اگر فقط در مجموعه مینویسی (Consumer) ➤ از super استفاده کن
✅ جمعبندی
درواقع Bounded Generics به ما کمک میکند:
1. از نوعهای نامعتبر جلوگیری کنیم 🧩
2. انعطافپذیری و ایمنی نوعها را افزایش دهیم 🔒
3. کد قابلخواندنتر و قابلاعتمادتر بنویسیم 💡
در ادامهی مبحث Generics، حالا به یکی از ویژگیهای مهم آن میرسیم:
✅ مبحث Bounded Type Parameters
این ویژگی به ما اجازه میدهد نوع پارامتر Generic را محدود کنیم تا فقط از نوع خاصی (یا زیرکلاس آن) استفاده شود.
🔹 Upper Bound (`extends`)
وقتی از extends استفاده میکنیم، یعنی نوع پارامتر باید از یک کلاس خاص ارثبری کند یا یک اینترفیس خاص را پیادهسازی کرده باشد.
مثلاً:
class Box<T extends Number> {
private T value;
public void set(T value) { this.value = value; }
public T get() { return value; }
}
✅ حالا فقط کلاسهایی مثل Integer, Double, Float و سایر زیرکلاسهای Number مجاز هستند:
Box<Integer> intBox = new Box<>();
Box<Double> doubleBox = new Box<>();
// Box<String> stringBox ❌ خطا: String زیرکلاس Number نیست
🔹 Lower Bound (`super`)
وقتی از super در Wildcard استفاده میکنیم، یعنی نوع پارامتر باید ابرکلاس (Superclass) نوع مشخصشده باشد.
این روش معمولاً هنگام نوشتن دادهها در Collection بهکار میرود.
مثلاً:
List<? super Integer> list = new ArrayList<Number>();
list.add(10); // مجاز ✅
list.add(20); // مجاز ✅
اما هنگام خواندن از لیست، نوع بازگشتی فقط به صورت Object شناخته میشود.
🔹 نکته کاربردی: PECS اصل معروف در Generics
PECS = Producer Extends, Consumer Super
* اگر فقط از مجموعه میخوانی (Producer) ➤ از extends استفاده کن
* اگر فقط در مجموعه مینویسی (Consumer) ➤ از super استفاده کن
✅ جمعبندی
درواقع Bounded Generics به ما کمک میکند:
1. از نوعهای نامعتبر جلوگیری کنیم 🧩
2. انعطافپذیری و ایمنی نوعها را افزایش دهیم 🔒
3. کد قابلخواندنتر و قابلاعتمادتر بنویسیم 💡
#کاربرـپیشرفته
🆔 @javapro_ir
🆔 @group_javapro
👍5
🎓 متدهای Generic و Type Inference در جاوا — قدرت واقعی Generics در عمل
در پیام های قبل با مفاهیم پایه و Bounded Generics آشنا شدیم. حالا نوبت میرسه به بخش بسیار کاربردی این مبحث:
✅ Generic Methods و ✅ Type Inference (تشخیص خودکار نوع داده)
🔹 متد Generic چیست؟
در جاوا، میتوان خودِ متد را Generic تعریف کرد؛ یعنی متد نوع دادهی ورودی و خروجی را در زمان فراخوانی مشخص میکند، نه هنگام تعریف کلاس.
ساختار کلی:
🔍 در اینجا <T> قبل از نوع بازگشتی (`void`) آمده، و نشان میدهد متد از نوع عمومی (Generic) است.
مثلاً:
🔹 متد Generic با نوع بازگشتی
میتوانیم نوع بازگشتی را نیز بهصورت Generic تعیین کنیم:
هنگام فراخوانی، نوع T بهصورت خودکار از روی نوع آرگومان تشخیص داده میشود (Type Inference):
🔹 Type Inference (تشخیص خودکار نوع)
جاوا معمولاً میتواند نوع پارامتر Generic را خودش تشخیص دهد، اما در مواقعی میتوان آن را بهصورت صریح هم مشخص کرد:
در اینجا ما نوع T را بهصورت دستی Integer تعیین کردیم.
🔹 نکته کاربردی
متدهای Generic معمولاً در کلاسهای Utility و کتابخانههای عمومی (مثل Collections و Streams) استفاده میشوند تا کدها قابلاستفاده مجدد و ایمن از نظر نوع داده باشند.
برای مثال متد Collections.<T>emptyList() نمونهای از همین مفهوم است.
✅ جمعبندی
* متدهای Generic اجازه میدهند نوع داده در زمان فراخوانی تعیین شود 🧩
* و Type Inference باعث سادگی و خوانایی کد میشود 👀
* این مفاهیم پایهایترین اصول در طراحی APIهای مدرن جاوا هستند 💡
در پیام های قبل با مفاهیم پایه و Bounded Generics آشنا شدیم. حالا نوبت میرسه به بخش بسیار کاربردی این مبحث:
✅ Generic Methods و ✅ Type Inference (تشخیص خودکار نوع داده)
🔹 متد Generic چیست؟
در جاوا، میتوان خودِ متد را Generic تعریف کرد؛ یعنی متد نوع دادهی ورودی و خروجی را در زمان فراخوانی مشخص میکند، نه هنگام تعریف کلاس.
ساختار کلی:
public <T> void printItem(T item) {
System.out.println(item);
}
🔍 در اینجا <T> قبل از نوع بازگشتی (`void`) آمده، و نشان میدهد متد از نوع عمومی (Generic) است.
مثلاً:
printItem("Hello Java!"); // نوع T → String
printItem(42); // نوع T → Integer
🔹 متد Generic با نوع بازگشتی
میتوانیم نوع بازگشتی را نیز بهصورت Generic تعیین کنیم:
public static <T> T getFirst(List<T> list) {
return list.get(0);
}
هنگام فراخوانی، نوع T بهصورت خودکار از روی نوع آرگومان تشخیص داده میشود (Type Inference):
List<String> names = List.of("Ali", "Reza");
String first = getFirst(names); // نوع T → String
🔹 Type Inference (تشخیص خودکار نوع)
جاوا معمولاً میتواند نوع پارامتر Generic را خودش تشخیص دهد، اما در مواقعی میتوان آن را بهصورت صریح هم مشخص کرد:
Integer num = GenericUtils.<Integer>getFirst(List.of(1, 2, 3));
در اینجا ما نوع T را بهصورت دستی Integer تعیین کردیم.
🔹 نکته کاربردی
متدهای Generic معمولاً در کلاسهای Utility و کتابخانههای عمومی (مثل Collections و Streams) استفاده میشوند تا کدها قابلاستفاده مجدد و ایمن از نظر نوع داده باشند.
برای مثال متد Collections.<T>emptyList() نمونهای از همین مفهوم است.
✅ جمعبندی
* متدهای Generic اجازه میدهند نوع داده در زمان فراخوانی تعیین شود 🧩
* و Type Inference باعث سادگی و خوانایی کد میشود 👀
* این مفاهیم پایهایترین اصول در طراحی APIهای مدرن جاوا هستند 💡
#کاربرـپیشرفته
🆔 @javapro_ir
🆔 @group_javapro
👍5❤2
👑 دوره شاهکار پیشرفته جاوا
Please open Telegram to view this post
VIEW IN TELEGRAM
جاواپرو | برنامه نویسی جاوا | Java pinned «🇮🇷 🇮🇷 🇮🇷 🇮🇷 🇮🇷 🎓لیست مهارت های مورد نیاز برای شروع برنامه نویسی و بازارکار جاوا... 🏠 🚀 دوره پرتاب | آموزش پیش نیازهای برنامه نویسی 👩💻 دوره مقدماتی جاوا 👑 دوره شاهکار پیشرفته جاوا 👩💻 دوره طلایی Spring Core 👩💻 دوره فریمورک Spring Boot 👩💻 دوره پروژه محور…»
🎓 تفاوت بین Stack و Heap در حافظه جاوا
در زبان جاوا، حافظهی برنامه به دو بخش اصلی تقسیم میشود: Stack Memory و Heap Memory. درک تفاوت این دو بخش برای نوشتن برنامههای بهینه، جلوگیری از خطاهای حافظه و فهم رفتار اشیاء در زمان اجرا بسیار مهم است.
🧠 ۱. Stack Memory چیست؟
حافظهی Stack مخصوص ذخیرهی متغیرهای محلی (Local Variables)**، **ارجاعهای متدها و فریمهای فراخوانی (Call Frames) است.
هر بار که یک متد در جاوا فراخوانی میشود، یک Stack Frame جدید برای آن ایجاد میشود که شامل پارامترهای ورودی و متغیرهای محلی همان متد است.
هنگامی که متد تمام میشود، Stack Frame مربوطه بهصورت خودکار حذف میشود. این کار باعث میشود مدیریت حافظه در Stack بسیار سریع و کارآمد باشد.
📌 ویژگیها:
* حافظهی کوچکتر و سریعتر از Heap
* مدیریت خودکار (بدون نیاز به Garbage Collector)
* فقط دادههای موقتی در آن نگهداری میشوند
📍 مثال:
در این مثال، هنگام فراخوانی متد add()`، یک Stack Frame جدید ایجاد میشود و متغیرهای `a, b, و result در آن ذخیره میشوند.
وقتی متد تمام میشود، تمام دادههای داخل آن Frame از بین میروند.
💾 ۲. Heap Memory چیست؟
حافظهی Heap برای نگهداری اشیاء (Objects) و مقادیر ساختهشده با new استفاده میشود.
هر چیزی که با کلیدواژهی new ساخته شود، در Heap قرار میگیرد و ارجاع آن در Stack نگهداری میشود.
حافظهی Heap توسط Garbage Collector مدیریت میشود. این به آن معناست که وقتی دیگر هیچ ارجاعی به یک شیء وجود نداشته باشد، جاوا آن را بهصورت خودکار آزاد میکند.
📌 ویژگیها:
* حافظهی بزرگتر ولی کندتر از Stack
* دادهها تا زمانی که به آنها ارجاع وجود دارد، باقی میمانند
* مدیریت توسط Garbage Collector
📍 مثال:
در این مثال، اشیاء Person در حافظهی Heap ذخیره میشوند، در حالی که ارجاعهای p1 و p2 در Stack قرار دارند.
وقتی متد main() به پایان میرسد، ارجاعها از بین میروند و در نتیجه اشیاء مربوطه در Heap توسط Garbage Collector حذف میشوند.
⚙️ نتیجهگیری:
*در واقع Stack برای دادههای موقتی، متغیرهای محلی و فراخوانی متدهاست.
*و Heap برای اشیاء و دادههایی است که در زمان اجرا با new ایجاد میشوند.
* سرعت Stack بالاتر است، اما ظرفیت آن کمتر است.
* مدیریت Stack خودکار است، ولی Heap توسط Garbage Collector کنترل میشود.
✨ نکته پایانی:
درک تفاوت Stack و Heap به شما کمک میکند خطاهایی مانند OutOfMemoryError یا StackOverflowError را بهتر درک و رفع کنید، و طراحی بهینهتری برای کلاسها و متدها داشته باشید.
در زبان جاوا، حافظهی برنامه به دو بخش اصلی تقسیم میشود: Stack Memory و Heap Memory. درک تفاوت این دو بخش برای نوشتن برنامههای بهینه، جلوگیری از خطاهای حافظه و فهم رفتار اشیاء در زمان اجرا بسیار مهم است.
🧠 ۱. Stack Memory چیست؟
حافظهی Stack مخصوص ذخیرهی متغیرهای محلی (Local Variables)**، **ارجاعهای متدها و فریمهای فراخوانی (Call Frames) است.
هر بار که یک متد در جاوا فراخوانی میشود، یک Stack Frame جدید برای آن ایجاد میشود که شامل پارامترهای ورودی و متغیرهای محلی همان متد است.
هنگامی که متد تمام میشود، Stack Frame مربوطه بهصورت خودکار حذف میشود. این کار باعث میشود مدیریت حافظه در Stack بسیار سریع و کارآمد باشد.
📌 ویژگیها:
* حافظهی کوچکتر و سریعتر از Heap
* مدیریت خودکار (بدون نیاز به Garbage Collector)
* فقط دادههای موقتی در آن نگهداری میشوند
📍 مثال:
public class StackExample {
public static void main(String[] args) {
int x = 10; // در Stack ذخیره میشود
int y = 20; // در Stack ذخیره میشود
int sum = add(x, y);
System.out.println(sum);
}
static int add(int a, int b) {
int result = a + b; // در Stack ذخیره میشود
return result;
}
}
در این مثال، هنگام فراخوانی متد add()`، یک Stack Frame جدید ایجاد میشود و متغیرهای `a, b, و result در آن ذخیره میشوند.
وقتی متد تمام میشود، تمام دادههای داخل آن Frame از بین میروند.
💾 ۲. Heap Memory چیست؟
حافظهی Heap برای نگهداری اشیاء (Objects) و مقادیر ساختهشده با new استفاده میشود.
هر چیزی که با کلیدواژهی new ساخته شود، در Heap قرار میگیرد و ارجاع آن در Stack نگهداری میشود.
حافظهی Heap توسط Garbage Collector مدیریت میشود. این به آن معناست که وقتی دیگر هیچ ارجاعی به یک شیء وجود نداشته باشد، جاوا آن را بهصورت خودکار آزاد میکند.
📌 ویژگیها:
* حافظهی بزرگتر ولی کندتر از Stack
* دادهها تا زمانی که به آنها ارجاع وجود دارد، باقی میمانند
* مدیریت توسط Garbage Collector
📍 مثال:
public class HeapExample {
public static void main(String[] args) {
Person p1 = new Person("Saleh"); // شیء در Heap
Person p2 = new Person("Ali"); // شیء دیگر در Heap
p1.sayHello();
}
}
class Person {
String name;
Person(String name) {
this.name = name; // فیلد name در Heap ذخیره میشود
}
void sayHello() {
System.out.println("Hello, " + name);
}
}
در این مثال، اشیاء Person در حافظهی Heap ذخیره میشوند، در حالی که ارجاعهای p1 و p2 در Stack قرار دارند.
وقتی متد main() به پایان میرسد، ارجاعها از بین میروند و در نتیجه اشیاء مربوطه در Heap توسط Garbage Collector حذف میشوند.
⚙️ نتیجهگیری:
*در واقع Stack برای دادههای موقتی، متغیرهای محلی و فراخوانی متدهاست.
*و Heap برای اشیاء و دادههایی است که در زمان اجرا با new ایجاد میشوند.
* سرعت Stack بالاتر است، اما ظرفیت آن کمتر است.
* مدیریت Stack خودکار است، ولی Heap توسط Garbage Collector کنترل میشود.
✨ نکته پایانی:
درک تفاوت Stack و Heap به شما کمک میکند خطاهایی مانند OutOfMemoryError یا StackOverflowError را بهتر درک و رفع کنید، و طراحی بهینهتری برای کلاسها و متدها داشته باشید.
#کاربر_مبتدی
🆔 @javapro_ir
🆔 @group_javapro
👍8💯2
🎓 تفاوت بین Primitive Types و Reference Types در جاوا
در زبان جاوا، تمام متغیرها به دو دستهی اصلی تقسیم میشوند:
Primitive Types (انواع پایهای) و Reference Types (انواع ارجاعی).
درک تفاوت این دو نوع داده، برای جلوگیری از خطاهای مفهومی و نوشتن کدهای قابل اعتماد ضروری است.
🧩 ۱. Primitive Types — دادههای پایهای و ساده
در جاوا، Primitive Types مستقیماً مقدار خود را در حافظه ذخیره میکنند و به هیچ شیء یا ارجاعی وابسته نیستند.
این نوع دادهها بهصورت ثابت و سریع عمل میکنند، چون در Stack Memory نگهداری میشوند.
📌 هشت نوع Primitive Type در جاوا وجود دارد:
📍 مثال:
در این مثال، مقدار
در نتیجه تغییر مقدار
🏗️ ۲. Reference Types — ارجاع به اشیاء در حافظه Heap
هر دادهای که از نوع Primitive نباشد، یک Reference Type محسوب میشود.
بهجای نگهداری مقدار مستقیم، در این نوع متغیرها آدرس (Reference) شیء در حافظهی Heap ذخیره میشود.
📍 مثال:
در این مثال، متغیرهای
بنابراین تغییر در
🧠 ۳. تفاوت مفهومی بین Primitive و Reference Types
* Primitive Types: مقدار را مستقیماً در خود ذخیره میکنند.
* Reference Types: فقط آدرس شیء را در خود نگه میدارند.
* Primitive Types در Stack ذخیره میشوند، در حالی که Reference Types معمولاً در Heap قرار دارند.
* هنگام مقایسه با
📍 نمونه تفاوت مقایسه:
⚙️ ۴. نکتهی مهم دربارهی Wrapper Classes
جاوا برای هر نوع Primitive یک کلاس Wrapper در پکیج
این کلاسها Reference Type هستند اما رفتارشان تا حد زیادی شبیه Primitive است.
📍 مثال:
✨ جمعبندی:
* Primitive Types ساده، سریع و کمحافظه هستند.
* Reference Types پیچیدهترند و برای اشیاء استفاده میشوند.
* تفاوت در نحوهی نگهداری داده، مقایسه، و رفتار در متدها باعث تفاوت بنیادی در عملکرد این دو نوع داده میشود.
* درک درست این تفاوت از خطاهایی مانند NullPointerException و Unexpected Mutations جلوگیری میکند.
📘 نکته پایانی:
در جاوا همهچیز شیء نیست — انواع پایهای (
اما وقتی وارد ساختارهای دادهای مثل
در زبان جاوا، تمام متغیرها به دو دستهی اصلی تقسیم میشوند:
Primitive Types (انواع پایهای) و Reference Types (انواع ارجاعی).
درک تفاوت این دو نوع داده، برای جلوگیری از خطاهای مفهومی و نوشتن کدهای قابل اعتماد ضروری است.
🧩 ۱. Primitive Types — دادههای پایهای و ساده
در جاوا، Primitive Types مستقیماً مقدار خود را در حافظه ذخیره میکنند و به هیچ شیء یا ارجاعی وابسته نیستند.
این نوع دادهها بهصورت ثابت و سریع عمل میکنند، چون در Stack Memory نگهداری میشوند.
📌 هشت نوع Primitive Type در جاوا وجود دارد:
byte, short, int, long, float, double, char, boolean📍 مثال:
int a = 10;
int b = a;
b = 20;
System.out.println(a); // 10
System.out.println(b); // 20
در این مثال، مقدار
a در حافظه Stack ذخیره شده و وقتی مقدار آن به b داده میشود، کپی میشود نه ارجاع.در نتیجه تغییر مقدار
b هیچ اثری روی a ندارد.🏗️ ۲. Reference Types — ارجاع به اشیاء در حافظه Heap
هر دادهای که از نوع Primitive نباشد، یک Reference Type محسوب میشود.
بهجای نگهداری مقدار مستقیم، در این نوع متغیرها آدرس (Reference) شیء در حافظهی Heap ذخیره میشود.
📍 مثال:
class Person {
String name;
Person(String name) {
this.name = name;
}
}
public class ReferenceExample {
public static void main(String[] args) {
Person p1 = new Person("Saleh");
Person p2 = p1; // هر دو به یک شیء اشاره میکنند
p2.name = "Ali";
System.out.println(p1.name); // Ali
System.out.println(p2.name); // Ali
}
}در این مثال، متغیرهای
p1 و p2 هر دو به همان شیء در Heap اشاره میکنند.بنابراین تغییر در
p2 باعث تغییر در p1 نیز میشود، چون هر دو یک آدرس مشترک دارند.🧠 ۳. تفاوت مفهومی بین Primitive و Reference Types
* Primitive Types: مقدار را مستقیماً در خود ذخیره میکنند.
* Reference Types: فقط آدرس شیء را در خود نگه میدارند.
* Primitive Types در Stack ذخیره میشوند، در حالی که Reference Types معمولاً در Heap قرار دارند.
* هنگام مقایسه با
==، در Primitive مقدار مقایسه میشود، ولی در Reference آدرس حافظه بررسی میشود.📍 نمونه تفاوت مقایسه:
int x = 5;
int y = 5;
System.out.println(x == y); // true → مقدارها برابرند
String s1 = new String("Hello");
String s2 = new String("Hello");
System.out.println(s1 == s2); // false → آدرسها متفاوتاند
System.out.println(s1.equals(s2)); // true → محتوا برابر است
⚙️ ۴. نکتهی مهم دربارهی Wrapper Classes
جاوا برای هر نوع Primitive یک کلاس Wrapper در پکیج
java.lang دارد (مثل Integer, Double, Boolean و ...).این کلاسها Reference Type هستند اما رفتارشان تا حد زیادی شبیه Primitive است.
📍 مثال:
int num1 = 100;
Integer num2 = 100; // Auto-boxing از int به Integer
System.out.println(num1 == num2); // true → بهخاطر unboxing خودکار
✨ جمعبندی:
* Primitive Types ساده، سریع و کمحافظه هستند.
* Reference Types پیچیدهترند و برای اشیاء استفاده میشوند.
* تفاوت در نحوهی نگهداری داده، مقایسه، و رفتار در متدها باعث تفاوت بنیادی در عملکرد این دو نوع داده میشود.
* درک درست این تفاوت از خطاهایی مانند NullPointerException و Unexpected Mutations جلوگیری میکند.
📘 نکته پایانی:
در جاوا همهچیز شیء نیست — انواع پایهای (
int, double, boolean و غیره) استثنا هستند.اما وقتی وارد ساختارهای دادهای مثل
List<Integer> یا Map<String, Object> میشویم، جاوا از Wrapper Classes برای تبدیل خودکار آنها به Reference Types استفاده میکند (این فرایند را *Auto-boxing* میگویند).#کاربر_مبتدی
🆔 @javapro_ir
🆔 @group_javapro
👍5❤1
امروز یک آگهی استخدام در جاوا رو دیدم و گفتم برداشتم رو از این فرصت شغلی جاوا باهاتون به اشتراک بذارم.
❇️ Junior Java Developer:
تسلط بر مفاهیم پایه جاوا و OOP
آشنایی با Spring Boot و SQL
آشنایی با Git و Clean Code
❇️ Mid-Level Java Developer:
✳️تسلط بر Spring Boot، Hibernate، و Concurrency
✳️آشنایی با Spring Security و Docker
✳️درک مفاهیم دیتابیس و Performance
❇️ Senior Java Developer:
✳️تجربه معماری سیستم و Microservices
✳️تسلط بر Kafka، Elasticsearch، OAuth 2.0
✳️درک عملکرد، مقیاسپذیری و طراحی سیستمهای Enterprise
📌 حالا وقت سرمایهگذاری روی مهارتهاته:
یادگیری اصولی Java + Spring Boot + Microservices
یعنی گام گذاشتن در مسیر توسعهدهندههای حرفهای با درآمدهای بالا و جایگاه واقعی در تیمهای نرمافزاری.
جاوا فقط یک زبان نیست؛
💬 جاوا یعنی ساختن سیستمهایی که دنیا رویش میچرخه....
💻 مسیرت رو از امروز بساز...
روی مهارتت سرمایهگذاری کن، نه فقط برای استخدام،
بلکه برای اینکه «در هر شرایطی، خواستنی باشی».
#جاوا #Java #استخدام #برنامه_نویسی #SpringBoot #Microservices #فرصت_شغلی #JavaDeveloper
❇️ Junior Java Developer:
تسلط بر مفاهیم پایه جاوا و OOP
آشنایی با Spring Boot و SQL
آشنایی با Git و Clean Code
❇️ Mid-Level Java Developer:
✳️تسلط بر Spring Boot، Hibernate، و Concurrency
✳️آشنایی با Spring Security و Docker
✳️درک مفاهیم دیتابیس و Performance
❇️ Senior Java Developer:
✳️تجربه معماری سیستم و Microservices
✳️تسلط بر Kafka، Elasticsearch، OAuth 2.0
✳️درک عملکرد، مقیاسپذیری و طراحی سیستمهای Enterprise
📌 حالا وقت سرمایهگذاری روی مهارتهاته:
یادگیری اصولی Java + Spring Boot + Microservices
یعنی گام گذاشتن در مسیر توسعهدهندههای حرفهای با درآمدهای بالا و جایگاه واقعی در تیمهای نرمافزاری.
جاوا فقط یک زبان نیست؛
💬 جاوا یعنی ساختن سیستمهایی که دنیا رویش میچرخه....
💻 مسیرت رو از امروز بساز...
روی مهارتت سرمایهگذاری کن، نه فقط برای استخدام،
بلکه برای اینکه «در هر شرایطی، خواستنی باشی».
#جاوا #Java #استخدام #برنامه_نویسی #SpringBoot #Microservices #فرصت_شغلی #JavaDeveloper
🆔 @javapro_ir
🆔 @group_javapro
👍3🫡1
بهعنوان یک توسعهدهنده بکاند جاوا (Java Backend Developer)، بهتر است درک و آشنایی خوبی با موضوعات زیر داشته باشید 👇
۱. قضیه CAP
۲. مدلهای سازگاری (Consistency Models)
۳. معماریهای سیستمهای توزیعشده
۴. برنامهنویسی سوکت (Socket Programming) با TCP/IP و UDP
۵. پروتکل HTTP و APIهای RESTful
۶. فراخوانی رویه از راه دور (RPC) مانند gRPC، Thrift و RMI
۷. صفهای پیام (Message Queues) مانند Kafka، RabbitMQ و JMS
۸. همروندی در جاوا (Java Concurrency) — شامل ExecutorService، Future و ForkJoinPool
۹. ایمنی نخها (Thread Safety) و همگامسازی (Synchronization)
۱۰. مدل حافظه جاوا (Java Memory Model)
۱۱. پایگاهدادههای توزیعشده مانند Cassandra، MongoDB و HBase
۱۲. تقسیمبندی و پارتیشنبندی دادهها (Data Sharding & Partitioning)
۱۳. مکانیزمهای کش (Caching Mechanisms) مانند Redis، Memcached و Ehcache
۱۴. استفاده از Zookeeper برای هماهنگی در سیستمهای توزیعشده
۱۵. الگوریتمهای اجماع (Consensus Algorithms) مانند Paxos و Raft
۱۶. قفلهای توزیعشده (Distributed Locks) با Zookeeper یا Redis
۱۷. فریمورکهای Spring Boot و Spring Cloud برای معماری مایکروسرویسها
۱۸. کشف سرویسها (Service Discovery) با Consul، Eureka و Kubernetes
۱۹. دروازههای API (API Gateways) مانند Zuul، NGINX و Spring Cloud Gateway
۲۰. ارتباط بین سرویسها (Inter-service Communication) با REST، gRPC یا Kafka
۲۱. الگوهای شکست مدار و تلاش مجدد (Circuit Breakers & Retry Patterns) — مانند Hystrix و Resilience4j
۲۲. توازن بار (Load Balancing) با NGINX، Kubernetes و Ribbon
۲۳. مکانیزمهای Failover برای پایداری سیستم
۲۴. تراکنشهای توزیعشده (Distributed Transactions) — شامل 2PC و الگوی Saga
۲۵. لاگگیری و ردیابی توزیعشده (Logging & Distributed Tracing) با ELK Stack، Jaeger یا Zipkin
۲۶. مانیتورینگ و شاخصها (Monitoring & Metrics) با Prometheus، Grafana و Micrometer
۲۷. سیستمهای هشداردهی (Alerting Systems)
۲۸. احراز هویت و مجوزدهی (Authentication & Authorization) — شامل OAuth و JWT
۲۹. رمزنگاری (Encryption) با SSL/TLS
۳۰. محدودسازی نرخ درخواستها (Rate Limiting & Throttling)
۳۱. استفاده از Apache Kafka برای پردازش جریان دادههای توزیعشده
۳۲. Apache Zookeeper برای هماهنگی سرویسها
۳۳. شبکههای داده درونحافظهای (In-memory Data Grids) مانند Hazelcast و Infinispan
۳۴. Akka برای همروندی مبتنی بر Actor
۳۵. معماری رویدادمحور (Event-Driven Architecture): شامل Event Sourcing و CQRS (تفکیک فرمان و پرسوجو)
۳۶. مدیریت کلاستر (Cluster Management): با Kubernetes برای ارکستراسیون کانتینرها
۳۷. توسعه بومی ابری (Cloud-Native Development): با استفاده از پلتفرمهای ابری مانند AWS، GCP و Azure، و محاسبات Serverless مثل AWS Lambda
۳۸. پردازش دادههای توزیعشده (Distributed Data Processing): با فریمورکهایی مثل Apache Spark یا Apache Flink برای پردازش دادههای در مقیاس بزرگ
۳۹. GraphQL: جایگزینی برای REST در ارتباط بین سرویسها
۴۰. تنظیم و بهینهسازی JVM برای سیستمهای توزیعشده: شامل مدیریت حافظه و بهینهسازی عملکرد
۱. قضیه CAP
۲. مدلهای سازگاری (Consistency Models)
۳. معماریهای سیستمهای توزیعشده
۴. برنامهنویسی سوکت (Socket Programming) با TCP/IP و UDP
۵. پروتکل HTTP و APIهای RESTful
۶. فراخوانی رویه از راه دور (RPC) مانند gRPC، Thrift و RMI
۷. صفهای پیام (Message Queues) مانند Kafka، RabbitMQ و JMS
۸. همروندی در جاوا (Java Concurrency) — شامل ExecutorService، Future و ForkJoinPool
۹. ایمنی نخها (Thread Safety) و همگامسازی (Synchronization)
۱۰. مدل حافظه جاوا (Java Memory Model)
۱۱. پایگاهدادههای توزیعشده مانند Cassandra، MongoDB و HBase
۱۲. تقسیمبندی و پارتیشنبندی دادهها (Data Sharding & Partitioning)
۱۳. مکانیزمهای کش (Caching Mechanisms) مانند Redis، Memcached و Ehcache
۱۴. استفاده از Zookeeper برای هماهنگی در سیستمهای توزیعشده
۱۵. الگوریتمهای اجماع (Consensus Algorithms) مانند Paxos و Raft
۱۶. قفلهای توزیعشده (Distributed Locks) با Zookeeper یا Redis
۱۷. فریمورکهای Spring Boot و Spring Cloud برای معماری مایکروسرویسها
۱۸. کشف سرویسها (Service Discovery) با Consul، Eureka و Kubernetes
۱۹. دروازههای API (API Gateways) مانند Zuul، NGINX و Spring Cloud Gateway
۲۰. ارتباط بین سرویسها (Inter-service Communication) با REST، gRPC یا Kafka
۲۱. الگوهای شکست مدار و تلاش مجدد (Circuit Breakers & Retry Patterns) — مانند Hystrix و Resilience4j
۲۲. توازن بار (Load Balancing) با NGINX، Kubernetes و Ribbon
۲۳. مکانیزمهای Failover برای پایداری سیستم
۲۴. تراکنشهای توزیعشده (Distributed Transactions) — شامل 2PC و الگوی Saga
۲۵. لاگگیری و ردیابی توزیعشده (Logging & Distributed Tracing) با ELK Stack، Jaeger یا Zipkin
۲۶. مانیتورینگ و شاخصها (Monitoring & Metrics) با Prometheus، Grafana و Micrometer
۲۷. سیستمهای هشداردهی (Alerting Systems)
۲۸. احراز هویت و مجوزدهی (Authentication & Authorization) — شامل OAuth و JWT
۲۹. رمزنگاری (Encryption) با SSL/TLS
۳۰. محدودسازی نرخ درخواستها (Rate Limiting & Throttling)
۳۱. استفاده از Apache Kafka برای پردازش جریان دادههای توزیعشده
۳۲. Apache Zookeeper برای هماهنگی سرویسها
۳۳. شبکههای داده درونحافظهای (In-memory Data Grids) مانند Hazelcast و Infinispan
۳۴. Akka برای همروندی مبتنی بر Actor
۳۵. معماری رویدادمحور (Event-Driven Architecture): شامل Event Sourcing و CQRS (تفکیک فرمان و پرسوجو)
۳۶. مدیریت کلاستر (Cluster Management): با Kubernetes برای ارکستراسیون کانتینرها
۳۷. توسعه بومی ابری (Cloud-Native Development): با استفاده از پلتفرمهای ابری مانند AWS، GCP و Azure، و محاسبات Serverless مثل AWS Lambda
۳۸. پردازش دادههای توزیعشده (Distributed Data Processing): با فریمورکهایی مثل Apache Spark یا Apache Flink برای پردازش دادههای در مقیاس بزرگ
۳۹. GraphQL: جایگزینی برای REST در ارتباط بین سرویسها
۴۰. تنظیم و بهینهسازی JVM برای سیستمهای توزیعشده: شامل مدیریت حافظه و بهینهسازی عملکرد
🆔 @javapro_ir
🆔 @group_javapro
👍4❤2
یادگیری Spring Boot در سه مرحله (نقشه راه ساده)
🔹 مرحله ۱ – مبانی و مقدمات
در این مرحله باید با پایههای اصلی Spring Boot آشنا بشی:
یاد بگیر چطور با Spring Initializr یه پروژهی جدید بسازی.
بفهم Maven و Gradle چی هستن (ابزارهایی برای ساخت و مدیریت پروژه).
یاد بگیر از Annotationها استفاده کنی (علامتهایی که به Spring میگن هر بخش از برنامه چه کاری انجام بده).
یادبگیر چطور تنظیمات مخصوص هر محیط (مثلاً تست، توسعه یا تولید) رو بسازی با استفاده از Profiles.
آشنا شو با دستورهای مهم مثل:
@GetMapping برای گرفتن داده از سرور
@PostMapping برای ارسال داده
@PutMapping برای ویرایش داده
@DeleteMapping برای حذف داده
یاد بگیر چطور دادههایی که در مسیر یا پارامتر آدرس هستن رو بگیری (Path Variable و Request Parameter).
یاد بگیر چطور برنامهات رو به پایگاه داده وصل کنی (مثل H2، MySQL یا PostgreSQL).
یاد بگیر چطور از JpaRepository و CrudRepository برای ذخیره و خواندن دادهها استفاده کنی.
با ابزار Spring Boot DevTools آشنا شو تا وقتی برنامهات رو تغییر دادی، خودش سریع دوباره اجرا بشه (Hot Reloading).
در آخر هم یه نگاهی بنداز به Spring Batch (برای کارهای زمانبندیشده) و تنظیم زمان با Cron Expressions.
🔹 مرحله ۲ – سطح متوسط
وقتی مقدمات رو یاد گرفتی، باید وارد مفاهیم عمیقتر بشی:
یاد بگیر چطور با @ControllerAdvice و @ExceptionHandler خطاها رو مدیریت کنی.
بتونی پیامهای خطای مخصوص خودت بسازی و همهی خطاهای برنامه رو به شکل سراسری کنترل کنی.
یاد بگیر چطور از احراز هویت ساده (Basic Authentication) استفاده کنی.
چطور امنیت APIها رو تنظیم کنی.
یاد بگیر چطور با JWT (Json Web Token) سیستم ورود بدون نیاز به نشست (Stateless) بسازی.
با مفهوم HATEOAS آشنا شو (اضافه کردن لینکهای مفید به پاسخهای API).
یاد بگیر چطور نسخهبندی API انجام بدی (مثلاً از طریق آدرس، پارامتر یا هدر).
تستنویسی یاد بگیر:
با JUnit و Mockito برای تست واحدها (Unit Test)
با Spring Boot Test برای تست یکپارچه (Integration Test)
با MockMvc برای تست سرویسهای REST
یاد بگیر از Spring Boot Actuator استفاده کنی تا سلامت و وضعیت برنامهات رو بررسی کنی.
حتی میتونی شاخص سلامت سفارشی (Custom Health Indicators) بسازی.
🔹 مرحله ۳ – سطح پیشرفته
حالا وقتشه وارد دنیای حرفهایتر بشی:
یاد بگیر از @Profile برای ساخت Beanهای مخصوص هر محیط استفاده کنی.
یاد بگیر چطور بین محیطها (مثل dev، test، prod) جابهجا بشی.
شروع کن به ساخت پروژهای با Spring Cloud.
با اجزای اصلی Spring Cloud آشنا شو:
راهاندازی Eureka Server برای ثبت سرویسها
ثبت میکروسرویسها در Eureka
انجام Service Discovery یعنی سرویسها خودشون همدیگه رو پیدا کنن
یاد بگیر API Gateway چیه و چطور با Spring Cloud Gateway راهش بندازی.
مسیرها (Routes) و فیلترها (Filters) رو تنظیم کن.
یاد بگیر Spring Cloud Config Server چیه و چطور میتونی همهی تنظیمات پروژههات رو در یه جای مرکزی نگهداری کنی.
در آخر یاد بگیر چطور پروژههات رو طوری تنظیم کنی که از Config Server استفاده کنن.
✅ نکته مهم
این نقشه راه تقریباً همه چیز رو برای یادگیری Spring Boot پوشش میده،
اما بدون یه چیز مهم هنوز ناقصه 👇🏻
باید پروژههای واقعی و باکیفیت بسازی و بتونی این مفاهیم رو برای دیگران توضیح بدی 💯
🔹 مرحله ۱ – مبانی و مقدمات
در این مرحله باید با پایههای اصلی Spring Boot آشنا بشی:
یاد بگیر چطور با Spring Initializr یه پروژهی جدید بسازی.
بفهم Maven و Gradle چی هستن (ابزارهایی برای ساخت و مدیریت پروژه).
یاد بگیر از Annotationها استفاده کنی (علامتهایی که به Spring میگن هر بخش از برنامه چه کاری انجام بده).
یادبگیر چطور تنظیمات مخصوص هر محیط (مثلاً تست، توسعه یا تولید) رو بسازی با استفاده از Profiles.
آشنا شو با دستورهای مهم مثل:
@GetMapping برای گرفتن داده از سرور
@PostMapping برای ارسال داده
@PutMapping برای ویرایش داده
@DeleteMapping برای حذف داده
یاد بگیر چطور دادههایی که در مسیر یا پارامتر آدرس هستن رو بگیری (Path Variable و Request Parameter).
یاد بگیر چطور برنامهات رو به پایگاه داده وصل کنی (مثل H2، MySQL یا PostgreSQL).
یاد بگیر چطور از JpaRepository و CrudRepository برای ذخیره و خواندن دادهها استفاده کنی.
با ابزار Spring Boot DevTools آشنا شو تا وقتی برنامهات رو تغییر دادی، خودش سریع دوباره اجرا بشه (Hot Reloading).
در آخر هم یه نگاهی بنداز به Spring Batch (برای کارهای زمانبندیشده) و تنظیم زمان با Cron Expressions.
🔹 مرحله ۲ – سطح متوسط
وقتی مقدمات رو یاد گرفتی، باید وارد مفاهیم عمیقتر بشی:
یاد بگیر چطور با @ControllerAdvice و @ExceptionHandler خطاها رو مدیریت کنی.
بتونی پیامهای خطای مخصوص خودت بسازی و همهی خطاهای برنامه رو به شکل سراسری کنترل کنی.
یاد بگیر چطور از احراز هویت ساده (Basic Authentication) استفاده کنی.
چطور امنیت APIها رو تنظیم کنی.
یاد بگیر چطور با JWT (Json Web Token) سیستم ورود بدون نیاز به نشست (Stateless) بسازی.
با مفهوم HATEOAS آشنا شو (اضافه کردن لینکهای مفید به پاسخهای API).
یاد بگیر چطور نسخهبندی API انجام بدی (مثلاً از طریق آدرس، پارامتر یا هدر).
تستنویسی یاد بگیر:
با JUnit و Mockito برای تست واحدها (Unit Test)
با Spring Boot Test برای تست یکپارچه (Integration Test)
با MockMvc برای تست سرویسهای REST
یاد بگیر از Spring Boot Actuator استفاده کنی تا سلامت و وضعیت برنامهات رو بررسی کنی.
حتی میتونی شاخص سلامت سفارشی (Custom Health Indicators) بسازی.
🔹 مرحله ۳ – سطح پیشرفته
حالا وقتشه وارد دنیای حرفهایتر بشی:
یاد بگیر از @Profile برای ساخت Beanهای مخصوص هر محیط استفاده کنی.
یاد بگیر چطور بین محیطها (مثل dev، test، prod) جابهجا بشی.
شروع کن به ساخت پروژهای با Spring Cloud.
با اجزای اصلی Spring Cloud آشنا شو:
راهاندازی Eureka Server برای ثبت سرویسها
ثبت میکروسرویسها در Eureka
انجام Service Discovery یعنی سرویسها خودشون همدیگه رو پیدا کنن
یاد بگیر API Gateway چیه و چطور با Spring Cloud Gateway راهش بندازی.
مسیرها (Routes) و فیلترها (Filters) رو تنظیم کن.
یاد بگیر Spring Cloud Config Server چیه و چطور میتونی همهی تنظیمات پروژههات رو در یه جای مرکزی نگهداری کنی.
در آخر یاد بگیر چطور پروژههات رو طوری تنظیم کنی که از Config Server استفاده کنن.
✅ نکته مهم
این نقشه راه تقریباً همه چیز رو برای یادگیری Spring Boot پوشش میده،
اما بدون یه چیز مهم هنوز ناقصه 👇🏻
باید پروژههای واقعی و باکیفیت بسازی و بتونی این مفاهیم رو برای دیگران توضیح بدی 💯
🆔 @javapro_ir
🆔 @group_javapro
❤2
دوره پروژه محور مدیریت رستوران با معماری مایکروسرویس و Spring Boot به صورت دیپلوی و واقعی بزودی در آکادمی جاواپرو خواهیم داشت....
❤5👍2😍1💯1
جاواپرو | برنامه نویسی جاوا | Java
دوره پروژه محور مدیریت رستوران با معماری مایکروسرویس و Spring Boot به صورت دیپلوی و واقعی بزودی در آکادمی جاواپرو خواهیم داشت....
این دوره توسط یکی از سینیورهای عاشق جاوا، با بیش از ۲۰ سال سابقه برنامهنویسی در این زبان و بیش از ۱۰ سال تجربه در حوزه دواپس، تهیه میشود. ایشان دانشجوی سال آخر دکتری هوش مصنوعی، از لینوکس کارهای باسابقه و مدیرعامل استارتاپ «جاواهاستینگ» هستند.
❤5😍1💯1
در جاواپرو تلاش میکنیم سطح آموزشهای جاوا در ایران را چندین پله ارتقا دهیم. اگر شما هم به رشد جامعه برنامهنویسی جاوا در ایران باور دارید، با معرفی جاواپرو به دوستان خود، ما را در این مسیر همراهی کنید.🤝
🆔 @javapro_ir
🆔 @group_javapro
❤2😍1
🎓 موضوع: Auto-boxing و Unboxing در جاوا — پلی بین Primitive و Reference Types
در زبان جاوا، نوعهای Primitive (مثل int, double, boolean
اما جاوا برای سهولت کار، قابلیتی به نام Auto-boxing و Unboxing معرفی کرده است که بهصورت خودکار بین این دو نوع تبدیل انجام میدهد.
🧩 ۱. Auto-boxing چیست؟
فرآیند تبدیل خودکار یک مقدار Primitive به شیء متناظر آن (Wrapper Class) را Auto-boxing میگویند.
یعنی جاوا خودش بهصورت خودکار، نوع پایهای را داخل یک کلاس بستهبندی (wrap) میکند.
📍 مثال:
در اینجا، جاوا بهصورت خودکار مقدار num را به Integer.valueOf(num) تبدیل کرده است.
یعنی نیازی به نوشتن تبدیل دستی نیست.
⚙️ ۲. Unboxing چیست؟
فرآیند تبدیل خودکار یک شیء Wrapper به نوع Primitive معادلش را Unboxing مینامند.
در این حالت جاوا مقدار درون شیء را بیرون میکشد تا بتوان از آن در محاسبات عددی یا منطقی استفاده کرد.
📍 مثال:
در اینجا جاوا خودش obj.intValue() را فراخوانی کرده و مقدار پایهای را به num اختصاص داده است.
💡 ۳. کاربرد Auto-boxing در Collectionها
ساختارهایی مانند ArrayList فقط با Reference Types کار میکنند.
بنابراین وقتی نوعی مثل int را در آنها ذخیره میکنیم، جاوا خودش Auto-boxing انجام میدهد.
📍 مثال:
در این مثال، نیازی نیست خودمان بنویسیم new Integer(10) یا list.get(0).intValue()
جاوا تمام این کارها را پشت صحنه انجام میدهد.
⚠️ ۴. نکات و دامهای مهم Auto-boxing
هرچند این ویژگی بسیار راحت است، اما اگر درست استفاده نشود، باعث مشکلات کارایی یا حتی خطاهای منطقی میشود.
📌 الف) مقایسه اشتباه با ==
در مقایسهی ==
فقط مقادیر بین -128 تا 127 در cache نگهداری میشوند و ممکن است با == برابر شوند، ولی بقیهی مقادیر خیر.
📌 ب) مصرف زیاد حافظه در حلقهها
اگر در حلقهها از Auto-boxing استفاده کنید، ممکن است تعداد زیادی شیء اضافی در Heap ساخته شود.
📍 مثال:
در اینجا در هر تکرار، جاوا یک شیء جدید Long میسازد چون sum از نوع Reference است.
برای جلوگیری از این مشکل، باید از نوع Primitive (
✨ ۵. جمعبندی
* در واقع Auto-boxing: تبدیل خودکار از نوع Primitive به Wrapper
* و Unboxing: تبدیل خودکار از Wrapper به Primitive
* استفاده از آن باعث سادهتر شدن کد میشود اما باید مراقب عملکرد و مقایسهی اشتباه باشید.
* همیشه در حلقهها و عملیات پرتکرار از انواع Primitive استفاده کنید تا از ایجاد اشیاء غیرضروری جلوگیری شود.
📘 نکته پایانی:
خب Auto-boxing یکی از ویژگیهایی است که باعث میشود جاوا هم “شیءگرا” باقی بماند و هم با نوعهای پایهای بهصورت بهینه کار کند.
اما فهم درست تفاوت بین مقدار (Value) و ارجاع (Reference) همچنان کلید اصلی درک رفتار واقعی آن است.
📚لیست دوره های مرتبط با جاوا-آکادمی جاواپرو
در زبان جاوا، نوعهای Primitive (مثل int, double, boolean
) و نوعهای Reference (مثل Integer, Double, Boolean) از هم جدا هستند.اما جاوا برای سهولت کار، قابلیتی به نام Auto-boxing و Unboxing معرفی کرده است که بهصورت خودکار بین این دو نوع تبدیل انجام میدهد.
🧩 ۱. Auto-boxing چیست؟
فرآیند تبدیل خودکار یک مقدار Primitive به شیء متناظر آن (Wrapper Class) را Auto-boxing میگویند.
یعنی جاوا خودش بهصورت خودکار، نوع پایهای را داخل یک کلاس بستهبندی (wrap) میکند.
📍 مثال:
public class AutoBoxingExample {
public static void main(String[] args) {
int num = 10; // نوع Primitive
Integer obj = num; // Auto-boxing → از int به Integer
System.out.println(obj); // خروجی: 10
}
}در اینجا، جاوا بهصورت خودکار مقدار num را به Integer.valueOf(num) تبدیل کرده است.
یعنی نیازی به نوشتن تبدیل دستی نیست.
⚙️ ۲. Unboxing چیست؟
فرآیند تبدیل خودکار یک شیء Wrapper به نوع Primitive معادلش را Unboxing مینامند.
در این حالت جاوا مقدار درون شیء را بیرون میکشد تا بتوان از آن در محاسبات عددی یا منطقی استفاده کرد.
📍 مثال:
public class UnboxingExample {
public static void main(String[] args) {
Integer obj = 25; // Auto-boxing
int num = obj; // Unboxing → از Integer به int
System.out.println(num + 5); // خروجی: 30
}
}در اینجا جاوا خودش obj.intValue() را فراخوانی کرده و مقدار پایهای را به num اختصاص داده است.
💡 ۳. کاربرد Auto-boxing در Collectionها
ساختارهایی مانند ArrayList فقط با Reference Types کار میکنند.
بنابراین وقتی نوعی مثل int را در آنها ذخیره میکنیم، جاوا خودش Auto-boxing انجام میدهد.
📍 مثال:
import java.util.ArrayList;
public class CollectionBoxing {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(10); // Auto-boxing → int → Integer
list.add(20);
int sum = list.get(0) + list.get(1); // Unboxing خودکار
System.out.println(sum); // خروجی: 30
}
}
در این مثال، نیازی نیست خودمان بنویسیم new Integer(10) یا list.get(0).intValue()
جاوا تمام این کارها را پشت صحنه انجام میدهد.
⚠️ ۴. نکات و دامهای مهم Auto-boxing
هرچند این ویژگی بسیار راحت است، اما اگر درست استفاده نشود، باعث مشکلات کارایی یا حتی خطاهای منطقی میشود.
📌 الف) مقایسه اشتباه با ==
Integer a = 1000;
Integer b = 1000;
System.out.println(a == b); // false → آدرسها متفاوت
System.out.println(a.equals(b)); // true → مقدار برابر
در مقایسهی ==
، دو شیء Integer در حافظهی جداگانه قرار دارند.فقط مقادیر بین -128 تا 127 در cache نگهداری میشوند و ممکن است با == برابر شوند، ولی بقیهی مقادیر خیر.
📌 ب) مصرف زیاد حافظه در حلقهها
اگر در حلقهها از Auto-boxing استفاده کنید، ممکن است تعداد زیادی شیء اضافی در Heap ساخته شود.
📍 مثال:
Long sum = 0L;
for (long i = 0; i < 1_000_000; i++) {
sum += i; // هر بار Auto-boxing انجام میشود!
}
System.out.println(sum);
در اینجا در هر تکرار، جاوا یک شیء جدید Long میسازد چون sum از نوع Reference است.
برای جلوگیری از این مشکل، باید از نوع Primitive (
long sum = 0;) استفاده کنید.✨ ۵. جمعبندی
* در واقع Auto-boxing: تبدیل خودکار از نوع Primitive به Wrapper
* و Unboxing: تبدیل خودکار از Wrapper به Primitive
* استفاده از آن باعث سادهتر شدن کد میشود اما باید مراقب عملکرد و مقایسهی اشتباه باشید.
* همیشه در حلقهها و عملیات پرتکرار از انواع Primitive استفاده کنید تا از ایجاد اشیاء غیرضروری جلوگیری شود.
📘 نکته پایانی:
خب Auto-boxing یکی از ویژگیهایی است که باعث میشود جاوا هم “شیءگرا” باقی بماند و هم با نوعهای پایهای بهصورت بهینه کار کند.
اما فهم درست تفاوت بین مقدار (Value) و ارجاع (Reference) همچنان کلید اصلی درک رفتار واقعی آن است.
#کاربر_مبتدی
📚لیست دوره های مرتبط با جاوا-آکادمی جاواپرو
🆔 @javapro_ir
🆔 @group_javapro
👍7