JavaRush /จาวาบล็อก /Random-TH /การแยกสาขาใน Java

การแยกสาขาใน Java

เผยแพร่ในกลุ่ม
ในบทความนี้เราจะดูแนวคิดการแยกสาขาในโปรแกรมคอมพิวเตอร์โดยทั่วไปและที่เขียนด้วยภาษา Java พูดคุยเกี่ยวกับโครงสร้างการควบคุมเช่น:
  • if-then(หรือif)
  • if-then-else(หรือif-else)
  • switch-case
การแตกแขนงใน Java - 1

การแตกแขนง

เริ่มจากแนวคิดพื้นฐานกันก่อน โปรแกรมใด ๆ คือชุดคำสั่งที่ดำเนินการโดยคอมพิวเตอร์ บ่อยครั้งที่คำสั่งต่างๆ ดำเนินการตามลำดับ ทีละคำสั่ง สถานการณ์เกิดขึ้นไม่บ่อยนัก (แต่ยังคงค่อนข้างบ่อย) เมื่อคุณต้องการเปลี่ยนลำดับคำสั่งของโปรแกรม บางครั้ง อาจจำเป็นต้องดำเนินการหนึ่งบล็อคคำสั่งแทนคำสั่งอื่น ทั้งนี้ขึ้นอยู่กับเงื่อนไขบางประการ และเมื่อเงื่อนไขเหล่านี้เปลี่ยนแปลง ให้ทำตรงกันข้าม ตัวอย่างเช่น มีเว็บไซต์จำนวนหนึ่งที่ห้ามไม่ให้ผู้ที่มีอายุต่ำกว่า 18 ปีเข้าชม โดยปกติ เมื่อเยี่ยมชมแหล่งข้อมูลดังกล่าวเป็นครั้งแรก ผู้ใช้จะได้รับการต้อนรับด้วยรูปแบบบางอย่างที่ผู้ใช้จะได้รับคำเตือนเกี่ยวกับการจำกัดอายุและขอให้ป้อนวันเกิดของเขา จากนั้นขึ้นอยู่กับข้อมูลที่ผู้ใช้ป้อน เขาจะได้รับอนุญาตให้เข้าสู่ทรัพยากรหรือไม่ ฟังก์ชันนี้มีให้โดยสิ่งที่เรียกกันทั่วไปว่าการแยกสาขา ลองเปรียบเทียบกันอีกครั้ง ลองจินตนาการว่าเราอยู่ที่สี่แยกถนนเจ็ดสาย เรากำลังเผชิญกับทางเลือก: เลี้ยวซ้ายหรือขวาหรือตรงไป ทางเลือกของเราขึ้นอยู่กับเงื่อนไขบางประการ เราไม่มีโอกาสใช้ถนนหลายสายพร้อมกัน เหล่านั้น. เราจะต้องเลือกถนนเส้นเดียวขึ้นอยู่กับเงื่อนไขบางประการ หลักการเดียวกันนี้ใช้กับการแตกแขนง ทีนี้ลองให้คำจำกัดความของการแตกแขนงกัน การแตกแขนงคือการออกแบบอัลกอริธึมซึ่งขึ้นอยู่กับความจริงของเงื่อนไขบางประการ การดำเนินการหนึ่งในหลาย ๆ ลำดับจะดำเนินการ การแตกแขนงถูกนำไปใช้ (มีแนวโน้มมากที่สุด) ในทุกภาษาการเขียนโปรแกรมอย่างแน่นอน ภาษาการเขียนโปรแกรม Java มีสิ่งที่เรียกว่าโครงสร้างการควบคุมหลายอย่างที่ช่วยให้คุณสามารถใช้การแยกสาขาในโปรแกรมของคุณได้ ในภาษาโปรแกรมมีโครงสร้างดังกล่าว 3 แบบ:
  • ผู้ดำเนินการif-then
  • ผู้ดำเนินการif-then-else
  • ตัวดำเนินการแบบไตรภาค? :
ในบทความนี้เราจะดูที่if-elseและ ตัวดำเนิน switch-caseการ

ถ้า-แล้ว

ตัวดำเนินการif-thenหรือบางทีifอาจเป็นตัวดำเนินการที่พบบ่อยที่สุด สำนวน “ใช่ เขียน 1 ถ้า” ได้รับความนิยมไปแล้ว ตัวดำเนินการifมีโครงสร้างดังต่อไปนี้:
if (bool_condition) {
	statement
}
ในการออกแบบนี้:
  • bool_conditionเป็นนิพจน์บูลีนที่ประเมินว่าเป็นจริงหรือเท็จ นิพจน์นี้เรียกว่าเงื่อนไข
  • statement— คำสั่ง (อาจมีมากกว่าหนึ่งคำสั่ง) ที่ต้องดำเนินการหากเงื่อนไขเป็นจริง ( bool_statement==true)
โครงสร้างนี้สามารถอ่านได้ดังนี้:

Если (bool_condition), то {statement}
นี่คือตัวอย่างบางส่วน:
public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);

    System.out.print("Сколько процентов заряда батареи осталось на вашем смартфоне?");
    int a = scanner.nextInt();

    if (a < 10) {
        System.out.println("Осталось менее 10 процентов, подключите ваш смартфон к зарядному устройству");
    }
}
ในโปรแกรมนี้ ผู้ใช้จะถูกขอให้ป้อนเปอร์เซ็นต์ของการชาร์จแบตเตอรี่บนสมาร์ทโฟนของเขา หากประจุเหลือน้อยกว่า 10 เปอร์เซ็นต์ โปรแกรมจะเตือนผู้ใช้เกี่ยวกับความจำเป็นในการชาร์จสมาร์ทโฟน นี่คือตัวอย่างของการออกแบบที่ง่ายifที่สุด เป็นที่น่าสังเกตว่าหากตัวแปร `a` มากกว่าหรือเท่ากับ 10 ก็จะไม่มีอะไรเกิดขึ้น โปรแกรมจะยังคงรันโค้ดที่ตามหลังif. โปรดทราบด้วยว่าในกรณีนี้ โครงสร้างifมีลำดับการดำเนินการเพียงลำดับเดียวเท่านั้น นั่นคือ พิมพ์ข้อความ หรือไม่ทำอะไรเลย นี่คือรูปแบบหนึ่งของการแยกแขนงด้วย "สาขา" เดียว บางครั้งสิ่งนี้ก็จำเป็น เช่น เมื่อเราต้องการปกป้องตนเองจากค่านิยมที่ไม่ถูกต้อง ตัวอย่างเช่น เราไม่สามารถค้นหาจำนวนตัวอักษรในสตริงได้หากสตริงnullเป็น ตัวอย่างด้านล่าง:
public static void main(String[] args) {
    String x = null;
    printStringSize(x);
    printStringSize("Не представляю своей жизни без ветвлений...");
    printStringSize(null);
    printStringSize("Ифы это так захватывающе!");
}

static void printStringSize(String string) {
    if (string != null) {
        System.out.println("Кол-во символов в строке `" + string + "`=" + string.length());
    }
}
จากการดำเนินการตามวิธีการหลัก ผลลัพธ์ต่อไปนี้จะถูกส่งไปยังคอนโซล:

Количество символов в строке `Не представляю своей жизни без ветвлений...`=43
Количество символов в строке `Ифы это так захватывающе!`=25
ต้องขอบคุณการตรวจสอบนั้นstring != nullเราจึงสามารถหลีกเลี่ยงข้อผิดพลาดในโปรแกรมได้ และไม่ทำอะไรเลยในกรณีที่ตัวแปร มี ค่า stringเท่ากับnull

ถ้า-แล้ว-อย่างอื่น

หากในกรณีปกติifโปรแกรมมีตัวเลือก: “ทำอะไรบางอย่างหรือไม่ทำอะไรเลย” ในif-elseการเลือกโปรแกรมจะขึ้นอยู่กับ “ทำอะไรอย่างใดอย่างหนึ่ง” ตัวเลือก "ไม่ทำอะไรเลย" จะหายไป มีการดำเนินการสองรูปแบบขึ้นไป (หรือจำนวนสาขา) ที่มีการแยกสาขาประเภทนี้ ลองพิจารณากรณีที่มีสองตัวเลือก จากนั้นโครงสร้างการควบคุมจะมีรูปแบบดังนี้:
if (bool_condition) {
	statement1
} else {
	statement2
}
ที่นี่:
  • bool_statementเป็นนิพจน์บูลีนที่ประเมินว่าเป็นจริงหรือเท็จ นิพจน์นี้เรียกว่าเงื่อนไข
  • statement1— คำสั่ง (อาจมีมากกว่าหนึ่งคำสั่ง) ที่ต้องดำเนินการหากเงื่อนไขเป็นจริง ( bool_statement==true)
  • statement2— คำสั่ง (อาจมีมากกว่าหนึ่งคำสั่ง) ที่ต้องดำเนินการหากเงื่อนไขเป็นเท็จ ( bool_statement==false)
โครงสร้างนี้สามารถอ่านได้ดังนี้:

Если (bool_condition), то {statement1}
Иначе {statement2}
นี่คือตัวอย่าง:
public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);

    System.out.print("Сколько процентов заряда батареи осталось на вашем смартфоне?");
    int a = scanner.nextInt();

    if (a < 10) {
        System.out.println("Осталось менее 10 процентов, подключите ваш смартфон к зарядному устройству");
    } else {
        System.out.println("Заряда вашей батареи достаточно для того, чтобы прочитать статью на Javarush");
    }
}
ตัวอย่างเดียวกันเกี่ยวกับระดับแบตเตอรี่บนสมาร์ทโฟน เฉพาะในกรณีที่ครั้งสุดท้ายที่โปรแกรมเตือนเฉพาะเกี่ยวกับความจำเป็นในการชาร์จสมาร์ทโฟน คราวนี้เรามีการแจ้งเตือนเพิ่มเติม ลองดูอันนี้if:
if (a < 10) {
    System.out.println("Осталось менее 10 процентов, подключите ваш смартфон к зарядному устройству");
} else {
    System.out.println("Заряда вашей батареи достаточно для того, чтобы прочитать статью на Javarush");
}
หากa < 10เป็นจริง (ระดับแบตเตอรี่น้อยกว่า 10) โปรแกรมจะพิมพ์ข้อความเดียว มิฉะนั้น หากไม่ตรงตามเงื่อนไขa < 10โปรแกรมจะแสดงข้อความที่แตกต่างไปจากเดิมอย่างสิ้นเชิง มาสรุปตัวอย่างที่สองของเรากัน โดยที่เราแสดงจำนวนตัวอักษรในบรรทัด ครั้งล่าสุดที่โปรแกรมไม่ส่งออกสิ่งใดหากสตริงที่ส่งผ่านมีค่าnullเท่ากับ มาแก้ไขปัญหานี้โดยเปลี่ยนอันปกติifเป็นif-else:
public static void main(String[] args) {
    String x = null;
    printStringSize(x);
    printStringSize("Не представляю своей жизни без ветвлений...");
    printStringSize(null);
    printStringSize("Ифы это так захватывающе!");
}

static void printStringSize(String string) {
    if (string != null) {
        System.out.println("Кол-во символов в строке `" + string + "`=" + string.length());
    } else {
        System.out.println("Ошибка! Переданная строка равна null!");
    }
}
ในวิธีการนี้เราได้เพิ่มบล็อกprintStringSizeเข้าไปในการก่อสร้าง ตอนนี้ถ้าเรารันโปรแกรม มันจะส่งออกไปยังคอนโซลไม่ใช่ 2 บรรทัด แต่เป็น 4 แม้ว่าอินพุต (method ) จะยังคงเหมือนกับครั้งก่อนก็ตาม ข้อความที่โปรแกรมจะส่งออก: ifelsemain

Ошибка! Переданная строка равна null!
Кол-во символов в строке `Не представляю своей жизни без ветвлений...`=43
Ошибка! Переданная строка равна null!
Кол-во символов в строке `Ифы это так захватывающе!`=25
สถานการณ์เป็นที่ยอมรับได้เมื่อelseไม่ได้ตามด้วยคำสั่งดำเนินการ แต่ตามด้วยคำสั่งอื่นif. จากนั้นการก่อสร้างจะใช้แบบฟอร์มต่อไปนี้:
If (bool_condition1) {
	statement1
} else if (bool_condition2) {
	statement2
} else if (bool_conditionN) {
	statementN
} else {
	statementN+1
}
การออกแบบนี้มีเงื่อนไขหลายประการ:
  • bool_condition1
  • bool_condition2
  • bool_conditionN
เงื่อนไขดังกล่าวไม่จำกัดจำนวน แต่ละเงื่อนไขมีคำสั่งของตัวเอง:
  • คำชี้แจง 1
  • คำสั่ง2
  • คำสั่งN
แต่ละรายการstatementสามารถมีโค้ดได้ 1 บรรทัดขึ้นไป มีการตรวจสอบเงื่อนไขทีละรายการ เมื่อกำหนดเงื่อนไขจริงข้อแรกแล้ว ชุดคำสั่ง "ผูก" กับเงื่อนไขจริงจะถูกดำเนินการ หลังจากดำเนินการคำสั่งเหล่านี้ โปรแกรมจะออกจากบล็อกifแม้ว่าจะมีการตรวจสอบเพิ่มเติมอีกก็ตาม นิพจน์ “statementN+1” จะถูกดำเนินการ หากไม่มีเงื่อนไขใดๆ ที่กำหนดไว้ข้างต้นเป็นจริง โครงสร้างนี้สามารถอ่านได้ดังนี้:

Если (bool_condition1) то {statement1}
Иначе если (bool_condition2) то {statement2}
Иначе если (bool_conditionN) то {statementN}
Иначе {statementN+1}
บรรทัดสุดท้ายในกรณีนี้เป็นทางเลือก คุณสามารถทำได้โดยไม่ต้องเหงาครั้งelseสุดท้าย จากนั้นการออกแบบจะอยู่ในรูปแบบต่อไปนี้:
If (bool_condition1) {
	statement1
} else if (bool_condition2) {
	statement2
} else if (bool_conditionN) {
	statementN
}
และมันจะอ่านได้ดังนี้:

Если (bool_condition1) то {statement1}
Иначе если (bool_condition2) то {statement2}
Иначе если (bool_conditionN) то {statementN}
ดังนั้น หากไม่มีเงื่อนไขใดเป็นจริง ก็จะไม่มีคำสั่งใดถูกดำเนินการ เรามาดูตัวอย่างกันดีกว่า กลับมาที่สถานการณ์ระดับการชาร์จบนสมาร์ทโฟนกันดีกว่า มาเขียนโปรแกรมที่จะแจ้งให้เจ้าของทราบรายละเอียดเพิ่มเติมเกี่ยวกับระดับการชาร์จของอุปกรณ์ของเขา:
public static void main(String[] args) {
    String alert5 = "Я скоро отключусь, но помни меня бодрым";
    String alert10 = "Я так скучаю по напряжению в моих жилах";
    String alert20 = "Пора вспоминать, где лежит зарядка";
    String alert30 = "Псс, пришло время экономить";
    String alert50 = "Хм, больше половины израсходовали";
    String alert75 = "Всё в порядке, заряда больше половины";
    String alert100 = "Я готов к приключениям, если что..";
    String illegalValue = "Такс, кто-то ввел некорректное meaning";

    Scanner scanner = new Scanner(System.in);
    System.out.print("Сколько процентов заряда батареи осталось на вашем смартфоне?");
    int a = scanner.nextInt();

    if (a <= 0 || a > 100) {
        System.out.println(illegalValue);
    } else if (a < 5) {
        System.out.println(alert5);
    } else if (a < 10) {
        System.out.println(alert10);
    } else if (a < 20) {
        System.out.println(alert20);
    } else if (a < 30) {
        System.out.println(alert30);
    } else if (a < 50) {
        System.out.println(alert50);
    } else if (a < 75) {
        System.out.println(alert75);
    } else if (a <= 100) {
        System.out.println(alert100);
    }
}
ตัวอย่างเช่น ในกรณีนี้ หากผู้ใช้ป้อน 15 โปรแกรมจะแสดงบนหน้าจอ: "ถึงเวลาที่ต้องจำไว้ว่าที่ชาร์จอยู่ที่ไหน" แม้ว่าที่จริงแล้ว 15 จะน้อยกว่าและ 30 และ 50 และ 75 และ 100 แต่เอาต์พุตบนหน้าจอจะเป็นเพียง 1 มาเขียนแอปพลิเคชันอื่นที่จะพิมพ์บนคอนโซลว่าเป็นวันในสัปดาห์อะไร:
public static void main(String[] args) {
    // Определим текущий день недели
    DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();

    if (dayOfWeek == DayOfWeek.SUNDAY) {
        System.out.println("Сегодня воскресенье");
    } else if (dayOfWeek == DayOfWeek.MONDAY) {
        System.out.println("Сегодня понедельник");
    } else if (dayOfWeek == DayOfWeek.TUESDAY) {
        System.out.println("Сегодня вторник");
    } else if (dayOfWeek == DayOfWeek.WEDNESDAY) {
        System.out.println("Сегодня среда");
    } else if (dayOfWeek == DayOfWeek.THURSDAY) {
        System.out.println("Сегодня четверг");
    } else if (dayOfWeek == DayOfWeek.FRIDAY) {
        System.out.println("Сегодня пятница");
    } else if (dayOfWeek == DayOfWeek.SATURDAY) {
        System.out.println("Сегодня суббота");
    }
}
แน่นอนว่าสะดวก แต่ข้อความที่ซ้ำซากจำเจมากมายจะทำให้คุณตาพร่าเล็กน้อย ในสถานการณ์ที่เรามีตัวเลือกจำนวนมาก ควรใช้ตัวดำเนินการซึ่งจะกล่าวถึงด้านล่างนี้

สวิตช์กรณี

อีกทางเลือกหนึ่งนอกจากตัวหนาifที่มีสาขาจำนวนมากคือตัวดำเนินswitch-caseการ โอเปอเรเตอร์นี้ดูเหมือนจะพูดว่า "ดังนั้นเราจึงมีตัวแปรนี้ ดูสิ ถ้าค่าของมันเท่ากับ `x` เราก็ทำสิ่งนี้และสิ่งนั้น ถ้าค่าของมันเท่ากับ 'y` เราก็ทำแตกต่างออกไป และถ้ามันไม่เท่ากับข้อใดข้อหนึ่งข้างต้น เราก็ทำ เป็นแบบนี้...” โอเปอเรเตอร์นี้มีโครงสร้างดังนี้
switch (argument) {
	case value1:
		statement1;
		break;
	case value2:
		statement2;
		break;
	case valueN:
		statementN;
		break;
	default:
		default_statement;
		break;
}
ลองดูโครงสร้างนี้โดยละเอียด argument เป็นตัวแปรที่มีค่าซึ่งเราจะนำมาเปรียบเทียบกับตัวเลือกต่างๆ สมมุติ ตัวแปรจะต้องfinalเป็น นอกจากนี้ยังควรบอกด้วยว่าตัวดำเนินการswitchไม่รองรับประเภทข้อมูลใด ๆ ที่เป็นอาร์กิวเมนต์ ประเภทที่ถูกต้องแสดงอยู่ด้านล่าง:
  • ไบต์และไบต์
  • สั้นและสั้น
  • int และจำนวนเต็ม
  • ถ่านและตัวละคร
  • แจกแจง
  • สตริง
case value1 (value2, valueN)argument- นี่คือค่า ซึ่งเป็น ค่าคงที่เฉพาะที่เราเปรียบเทียบค่าของตัวแปร นอกจากนี้ แต่ละกรณีจะกำหนดชุดคำสั่งที่ต้องดำเนินการ statement1, statement2, statementNเป็นคำสั่งที่จะต้องดำเนินการหากargumentพบว่ามีค่าเท่ากับคำสั่งใดคำสั่งvalueหนึ่ง เช่น ถ้าargumentมีค่าเท่ากับvalue2โปรแกรมจะดำเนินstatement2การ defaultและdefault_statementเป็น "ค่าเริ่มต้น" หากargumentมันไม่เท่ากับอันใดอันหนึ่งที่นำเสนอvalueสาขาจะถูกทริกเกอร์defaultและคำสั่งจะถูกดำเนินdefault_statementการ defaultและdefault_statementเป็นแอตทริบิวต์ทางเลือกของตัวดำเนินswitch-caseการ break— คุณจะสังเกตเห็นว่าที่ส่วนท้ายของแต่ละ case block จะมีข้อความbreakสั่ง โอเปอเรเตอร์นี้ยังเป็นทางเลือกและทำหน้าที่แยกแยะรหัสของกรณีต่างๆ บางครั้งจำเป็นต้องดำเนินการเดียวกันในบางกรณี: จากนั้นจึงสามารถรวมกรณีเหล่านี้เข้าด้วยกันได้ ในกรณีนี้ คำหลักbreakจะถูกละเว้น และโครงสร้างของตัวดำเนินการswitch-caseจะมีลักษณะดังนี้:
switch (argument) {
	case value1:
		statement1;
		break;
	case valueX:
	case valueY:
		statementXY;
		break;
}
เป็นที่น่าสังเกตว่าไม่มีตัวดำเนินการระหว่าง `case valueX:` และ `case valueY: break` ที่นี่ถ้าargumentมันเท่ากับvalue1มันจะถูกดำเนินstatement1การ และถ้าอาร์กิวเมนต์เท่ากับvalueXอย่างใดอย่างหนึ่งvalueY, statementXY. มาเจือจางทฤษฎีที่เข้าใจยากให้เป็นแบบฝึกหัดที่เข้าใจง่ายกัน ลองเขียนตัวอย่างใหม่ด้วยวันในสัปดาห์โดยใช้โอเปอเรswitch-caseเตอร์
public static void main(String[] args) {
    // Определим текущий день недели
    DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();

    switch (dayOfWeek) {
        case SUNDAY:
            System.out.println("Сегодня воскресенье");
            break;
        case MONDAY:
            System.out.println("Сегодня понедельник");
            break;
        case TUESDAY:
            System.out.println("Сегодня вторник");
            break;
        case WEDNESDAY:
            System.out.println("Сегодня среда");
            break;
        case THURSDAY:
            System.out.println("Сегодня четверг");
            break;
        case FRIDAY:
            System.out.println("Сегодня пятница");
            break;
        case SATURDAY:
            System.out.println("Сегодня суббота");
            break;
    }
}
ตอนนี้เรามาเขียนโปรแกรมที่แสดงว่าวันนี้เป็นวันธรรมดาหรือสุดสัปดาห์โดยใช้โอเปอเรswitch-caseเตอร์
public static void main(String[] args) {
    // Определим текущий день недели
    DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();

    switch (dayOfWeek) {
        case SUNDAY:
        case SATURDAY:
            System.out.println("Сегодня выходной");
            break;
        case FRIDAY:
            System.out.println("Завтра выходной");
            break;
        default:
            System.out.println("Сегодня рабочий день");
            break;

    }
}
ให้ฉันอธิบายเล็กน้อย ในโปรแกรมนี้ เราได้รับenum DayOfWeekซึ่งหมายถึงวันปัจจุบันของสัปดาห์ ต่อไปเรามาดูกันว่าค่าของตัวแปรของเราเท่ากับdayOfWeekค่าของSUNDAYตัวใดตัวหนึ่งหรือSATURDAYไม่ ในกรณีนี้ โปรแกรมจะแสดงข้อความ “วันนี้เป็นวันหยุด” ถ้าไม่เช่นนั้นเราจะตรวจสอบว่าค่าของตัวแปรเท่ากับdayOfWeekค่าของหรือFRIDAYไม่ ในกรณีนี้ โปรแกรมจะแสดงข้อความ “พรุ่งนี้เป็นวันหยุด” หากไม่มีในกรณีนี้ เราก็มีตัวเลือกน้อย วันที่เหลือคือวันธรรมดา ดังนั้นตามค่าเริ่มต้น หากวันนี้ไม่ใช่วันศุกร์ ไม่ใช่วันเสาร์ และไม่ใช่วันอาทิตย์ โปรแกรมจะแสดงข้อความ “วันนี้เป็นวันทำการ”

บทสรุป

ดังนั้นในบทความนี้เรามาดูกันว่าการแตกสาขาในโปรแกรมคอมพิวเตอร์คืออะไร นอกจากนี้เรายังพบว่าโครงสร้างการควบคุมใดที่ใช้ในการแยกสาขาใน Java เราได้หารือเกี่ยวกับการออกแบบเช่น:
  • if-then
  • if-then-else
  • switch-case
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION