JavaRush /จาวาบล็อก /Random-TH /คลาสที่ไม่ระบุชื่อใน Java

คลาสที่ไม่ระบุชื่อใน Java

เผยแพร่ในกลุ่ม
สวัสดี! ในบทเรียนวันนี้ เราจะมาดูหัวข้อของคลาสที่ซ้อนกันต่อไป ถึงคราวของกลุ่มสุดท้าย - คลาสภายในที่ไม่ระบุชื่อใน Java กลับไปที่แผนภาพของเรา: คลาสที่ไม่ระบุชื่อ - 2เช่นเดียวกับชั้นเรียนในท้องถิ่นที่เราพูดถึงในการบรรยายครั้งล่าสุด ชั้นเรียนที่ไม่ระบุชื่อเป็นส่วนหนึ่งของชั้นเรียนภายใน พวกเขายังมีความเหมือนและความแตกต่างหลายประการระหว่างกัน แต่ก่อนอื่น เรามาดูกันก่อน: ทำไมพวกเขาถึงถูกเรียกว่า "ไม่เปิดเผยตัวตน" จริงๆ? เมื่อต้องการทำเช่นนี้ ลองดูตัวอย่างง่ายๆ ลองนึกภาพว่าเรามีโปรแกรมหลักที่ทำงานอยู่ตลอดเวลาและทำอะไรบางอย่าง เราต้องการสร้างระบบการตรวจสอบสำหรับโปรแกรมนี้ซึ่งประกอบด้วยหลายโมดูล โมดูลหนึ่งจะตรวจสอบตัวบ่งชี้ประสิทธิภาพทั่วไปและเก็บบันทึก โมดูลที่สองจะบันทึกและบันทึกข้อผิดพลาดในบันทึกข้อผิดพลาด โมดูลที่สามจะตรวจสอบกิจกรรมที่น่าสงสัย: ตัวอย่างเช่น ความพยายามในการเข้าถึงโดยไม่ได้รับอนุญาตและสิ่งอื่น ๆ ที่เกี่ยวข้องกับความปลอดภัย เนื่องจากทั้งสามโมดูลควรเริ่มต้นที่จุดเริ่มต้นของโปรแกรมและทำงานในเบื้องหลัง จึงเป็นความคิดที่ดีที่จะสร้างอินเทอร์เฟซทั่วไปสำหรับโมดูลเหล่านี้:
public interface MonitoringSystem {

   public void startMonitoring();
}
มันจะถูกนำไปใช้โดย 3 คลาสเฉพาะ:
public class GeneralIndicatorsMonitoringModule implements MonitoringSystem {

@Override
   public void startMonitoring() {
       System.out.println("Monitoring of general indicators has started!");
   }
}


public class ErrorMonitoringModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Bug Tracking Monitoring Started!");
   }
}


public class SecurityModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Security monitoring started!");
   }
}
ดูเหมือนว่าทุกอย่างจะเป็นไปตามลำดับ เรามีระบบที่ค่อนข้างชัดเจนในหลายโมดูล แต่ละคนมีพฤติกรรมของตัวเอง หากเราต้องการโมดูลใหม่ เราก็สามารถเพิ่มโมดูลเหล่านั้นได้ เนื่องจากเรามีอินเทอร์เฟซที่ใช้งานง่าย แต่ลองคิดดูว่าระบบติดตามของเราจะทำงานอย่างไร คลาสที่ไม่ระบุชื่อ - 3โดยพื้นฐานแล้ว เราควรสร้างวัตถุ 3 ชิ้น - GeneralIndicatorsMonitoringModule, ErrorMonitoringModule, SecurityModule- และเรียกใช้เมธอดstartMonitoring()ในแต่ละวัตถุ นั่นคือสิ่งที่คุณต้องทำคือสร้างวัตถุ 3 ชิ้นและเรียก 1 วิธีกับวัตถุนั้น
public class Main {

   public static void main(String[] args) {

       GeneralIndicatorsMonitoringModule generalModule = new GeneralIndicatorsMonitoringModule();
       ErrorMonitoringModule errorModule = new ErrorMonitoringModule();
       SecurityModule securityModule = new SecurityModule();

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
เอาต์พุตคอนโซล:

Мониторинг общих показателей стартовал!
Мониторинг отслеживания ошибок стартовал!
Мониторинг безопасности стартовал!
และสำหรับงานเล็กๆ เช่นนี้ เราได้เขียนทั้งระบบ: 3 คลาสและหนึ่งอินเทอร์เฟซ! และทั้งหมดนี้เพื่อประโยชน์ของโค้ด 6 บรรทัด ในทางกลับกัน เรามีทางเลือกอะไรบ้าง? ใช่ มันไม่เจ๋งเลยที่เราเขียนคลาสแบบ "ใช้แล้วทิ้ง" แบบนี้ แต่เราจะแก้ไขปัญหานี้ได้อย่างไร? นี่คือจุดที่ ชั้นเรียนภายในที่ไม่เปิดเผยตัวตนเข้ามาช่วยเหลือเรา! นี่คือลักษณะที่ปรากฏในกรณีของเรา:
public class Main {

   public static void main(String[] args) {

       MonitoringSystem generalModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Monitoring of general indicators has started!");
           }
       };



           MonitoringSystem errorModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Bug Tracking Monitoring Started!");
           }
       };

       MonitoringSystem securityModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Security monitoring started!");
           }
       };

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
เรามาดูกันว่าเกิดอะไรขึ้นที่นี่! ดูเหมือนว่าเรากำลังสร้างวัตถุอินเทอร์เฟซ:
MonitoringSystem generalModule = new MonitoringSystem() {

@Override
   public void startMonitoring() {
       System.out.println("Monitoring of general indicators has started!");
   }
};
แต่เรารู้มานานแล้วว่าเป็นไปไม่ได้ที่จะสร้างวัตถุส่วนต่อประสาน! ถูกต้อง มันเป็นไปไม่ได้ จริงๆ แล้ว เราไม่ทำอย่างนั้น ช่วงเวลาที่เราเขียน:
MonitoringSystem generalModule = new MonitoringSystem() {

};
ภายในเครื่อง Java สิ่งต่อไปนี้เกิดขึ้น:
  1. มีการสร้างคลาส Java ที่ไม่มีชื่อซึ่งใช้MonitoringSystem.
  2. คอมไพเลอร์เมื่อเห็นคลาสดังกล่าวต้องการให้คุณใช้วิธีการอินเทอร์เฟซทั้งหมดMonitoringSystem(เราทำ 3 ครั้ง)
  3. มีการสร้างวัตถุหนึ่งของคลาสนี้ ให้ความสนใจกับรหัส:
MonitoringSystem generalModule = new MonitoringSystem() {

};
มีอัฒภาคต่อท้าย! เธอยืนอยู่ตรงนั้นด้วยเหตุผล เราประกาศคลาสพร้อมกัน (ผ่านเครื่องหมายปีกกา) และสร้างอ็อบเจ็กต์โดยใช้(); อ็อบเจ็กต์ทั้งสามของเราได้แทนที่วิธีการstartMonitoring()ในแบบของตัวเอง ในตอนท้ายเราเรียกวิธีนี้กับแต่ละวิธี:
generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
เอาต์พุตคอนโซล:

Мониторинг общих показателей стартовал!
Мониторинг отслеживания ошибок стартовал!
Мониторинг безопасности стартовал!
นั่นคือทั้งหมด! เราทำงานของเราเสร็จแล้ว: เราได้สร้างวัตถุสามชิ้นMonitoringSystemกำหนดนิยามใหม่ด้วยวิธีที่แตกต่างกันสามวิธี และเรียกมันสามครั้ง ทั้งสามโมดูลเปิดตัวและทำงานได้สำเร็จ ในขณะเดียวกัน โครงสร้างของโปรแกรมของเราก็ง่ายขึ้นมาก! GeneralIndicatorsMonitoringModuleท้าย ที่สุดคลาสต่างๆ ก็สามารถ ถูกลบออกจากโปรแกรมได้ErrorMonitoringModuleแล้ว ! SecurityModuleเราไม่ต้องการพวกมัน - เราจัดการได้ดีหากไม่มีพวกมัน หากคลาสโมดูลที่ไม่ระบุชื่อแต่ละคลาสของเราต้องการพฤติกรรมที่แตกต่างกัน วิธีการเฉพาะของตัวเองที่คลาสอื่นไม่มี เราสามารถเพิ่มคลาสเหล่านั้นได้อย่างง่ายดาย:
MonitoringSystem generalModule = new MonitoringSystem() {

   @Override
   public void startMonitoring() {
       System.out.println("Monitoring of general indicators has started!");
   }

   public void someSpecificMethod() {

       System.out.println("Specific method for first module only");
   }
};
เอกสารของ Oracle มีคำแนะนำ ที่ดี : "ใช้คลาสที่ไม่ระบุชื่อหากคุณต้องการคลาสโลคัลสำหรับการใช้งานครั้งเดียว" คลาสที่ไม่เปิดเผยตัวตนคือคลาสภายในที่เต็มเปี่ยม ดังนั้นจึงสามารถเข้าถึงตัวแปรคลาสภายนอก รวมถึงตัวแปรแบบคงที่และส่วนตัว:
public class Main {

   private static int currentErrorsCount = 23;

   public static void main(String[] args) {

       MonitoringSystem errorModule = new MonitoringSystem() {

           @Override
           public void startMonitoring() {
               System.out.println("Bug Tracking Monitoring Started!");
           }

           public int getCurrentErrorsCount() {

               return currentErrorsCount;
           }
       };
   }
}
พวกเขามีบางอย่างที่เหมือนกันกับคลาสท้องถิ่น: มองเห็นได้เฉพาะภายในวิธีการที่กำหนดไว้เท่านั้น ในตัวอย่างข้างต้น ความพยายามในการเข้าถึงวัตถุerrorModuleภายนอกวิธีการmain()จะล้มเหลว และข้อ จำกัด ที่สำคัญอีกประการหนึ่งที่คลาสที่ไม่ระบุชื่อสืบทอดมาจาก "บรรพบุรุษ" - คลาสภายใน: คลาสที่ไม่ระบุชื่อไม่สามารถมีตัวแปรและวิธีการแบบคงที่ หากเราพยายามสร้างวิธีการgetCurrentErrorsCount()จากตัวอย่างข้างต้นแบบคงที่ คอมไพลเลอร์จะเกิดข้อผิดพลาด:
//error! Inner classes cannot have static declarations
public static int getCurrentErrorsCount() {

   return currentErrorsCount;
}
เราจะได้ผลลัพธ์เดียวกันหากเราพยายามประกาศตัวแปรคงที่:
MonitoringSystem errorModule = new MonitoringSystem() {

   //error! Inner classes cannot have static declarations!
   static int staticInt = 10;

   @Override
   public void startMonitoring() {
       System.out.println("Bug Tracking Monitoring Started!");
   }

};
สุดท้ายนี้ ฉันสามารถแนะนำวิดีโอที่ยอดเยี่ยมเกี่ยวกับหัวข้อชั้นเรียนที่ไม่ระบุชื่อให้คุณได้ โดยจะมีการอธิบายหัวข้อนี้อย่างเรียบง่ายและชัดเจนที่สุด :)
และบทเรียนของเราในวันนี้ก็สิ้นสุดลงแล้ว! และแม้ว่าเราจะครอบคลุมคลาสที่ซ้อนกันกลุ่มสุดท้ายแล้ว แต่เรายังไม่จบหัวข้อนี้ เราจะศึกษาอะไรต่อไปเกี่ยวกับคลาสที่ซ้อนกัน? คุณจะพบคำตอบเร็วๆ นี้แน่นอน! :)
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION