JavaRush /בלוג Java /Random-HE /הפסקת קפה מס' 165. חבילות ב-Java. שיטות בטוחות לחוטים למת...

הפסקת קפה מס' 165. חבילות ב-Java. שיטות בטוחות לחוטים למתחילים

פורסם בקבוצה

חבילות Java

מקור: Usemynotes פוסט זה יעזור לך להבין טוב יותר חבילות ב-Java, להבין את מטרתן וכיצד ליישם אותן. הפסקת קפה מס' 165.  חבילות ב-Java.  שיטות בטוחות לחוטים למתחילים - 1

מהן חבילות ב-Java

חבילה ב-Java היא דרך לקבץ קבוצה של מחלקות, ממשקים וחבילות משנה. חבילות משמשות ליצירת קבוצות של מחלקות קשורות, ממשקים, ספירות וכדומה. חבילות משנה הן חבילות שנמצאות בתוך חבילה אחרת. הם אינם מיובאים כברירת מחדל, אך ניתן לייבא אותם באופן ידני במידת הצורך. מפרט הגישה אינו מסופק לחברים בודדים של חבילת משנה; הם מטופלים כחבילות נפרדות.

כמה סוגי חבילות ב-Java:

  • java.lang - מגיע עם Java כברירת מחדל.
  • java.io - מכיל מחלקות, שיטות ואלמנטים אחרים הקשורים לקלט/פלט.

למה צריך חבילות?

  • כדי למנוע התנגשויות שמות.
  • כדי לספק גישה מבוקרת.
  • כדי להשיג אנקפסולציה של נתונים.

איך יוצרים חבילה ב-Java?

בואו ניצור חבילה בשם מחשב . בדרך כלל שם החבילה כתוב באותיות קטנות. זה נעשה רק כדי למנוע התנגשויות שמות עם שמות מחלקות. כמו כן, ניצור ממשק בשם Pluggable , אשר ימוקם בחבילת המחשב .
package computer;

interface Pluggable {
   public void pluggedIn();
   public void pluggedOut();
}
כעת ניצור מחלקה בשם PenDrive שתטמיע את הממשק הנ"ל.
package computer;

public class PenDrive implements Pluggable {

   int storage = 64;

   public void pluggedIn () {
     System.out.println("Pen Drive is connected");
   }

   public void pluggedOut () {
     System.out.println("Pen Drive is removed");
   }

   public int storage() {
     return storage;
   }

   public static void main(String args[]) {
     PenDrive p = new PenDrive ();
     p.pluggedIn();
     System.out.println("Pen Drive Storage: " + p.storage());
     p.pluggedOut();
   }
}

כיצד ליצור היררכיית חבילות ב-Java?

בעת יצירת היררכיה, שמות החבילות ב-Java נקראות בסדר הפוך. זה גורם להם להיות דומים מאוד לספריות או לתיקיות. בדיוק כמו במחשב אישי, שבו תיקיה אחת יכולה להכיל תיקיית משנה אחת או יותר, אותו הדבר חל על חבילות ב-Java. בואו נסתכל על חבילה בשם Asia.India.Kolkata . כל אלה הם תיקיות קיימות, אבל אם מחשיבים את הגיאוגרפיה, ברור שכלכותה נמצאת בהודו, והודו היא באסיה. המטרה העיקרית של היררכיה היא להקל על מציאת שיעורים.

סוגי חבילות ב-Java

חבילות מובנות

חבילות מובנות הן חבילות המורכבות ממספר רב של מחלקות מובנות שהן חלק מ-Java API. חבילות אלו כוללות:
  • java.util - חבילה זו מכילה מספר סופי של מחלקות שירות המשמשות ליישום מבני נתונים כגון רשימה מקושרת, סטים וכדומה. זה גם תומך בפעולות תאריך ושעה ועוד הרבה יותר.
  • java.net - הוא מכיל מחלקות המשמשות לפעולות רשת.

חבילות מוגדרות על ידי משתמש

חבילות שהוגדרו על ידי המשתמש נקראות חבילות משתמש. המשתמש יכול ליצור חבילה ידנית ולהכיל בה כמה מחלקות שהוא רוצה.

איך לגשת לחבילה מחבילה אחרת?

אתה יכול לגשת לחבילה מחבילה אחרת בשלוש דרכים פשוטות:
  • שימוש בכוכבית בהצהרת ייבוא
תו הכוכבית ( * ) משמש לייצוג "כל הדברים" ב-Java. באמצעותו נוכל לייבא את כל מה שנמצא בתוך חבילת משנה של חבילה. דוגמה: שקול חבילה בשם tools . אם אנחנו רוצים לייבא את כל מה שנמצא בתוך החבילה הזו, אנחנו צריכים להשתמש בהצהרת ייבוא ​​כמו:
import tools.*;
  • באמצעות חבילת ייבוא .ClassName;
אזכור שם המחלקה בחבילה היא דרך יעילה לייבא רק את המחלקות הדרושות לתוכנית שלך, ובכך למנוע ייבוא ​​מחלקות מיותרות. דוגמה: שקול חבילה בשם ספרים . אם אנחנו רוצים לייבא רק מחלקה או ממשק ספציפיים ממנה (נסתכל על המחלקה Pages ), אז נוכל לייבא בדיוק את זה באמצעות:
import book.Pages;
  • שימוש בשמך המלא
יש דרך להשתמש ישירות בחבילת Java או במחלקות שלה על ידי שימוש בשם המלא שלהם. כך אינך צריך לייבא את החבילה ותוכל להשתמש בה ישירות בתוכנית. דוגמא:
java.awt.List aSimpleList = new java.awt.List();

גודל אצווה ברירת מחדל ב-Java

כברירת מחדל, Java מייבאת את חבילת java.lang . יש לו מחלקות רבות הנמצאות בשימוש נפוץ בתוכניות Java פשוטות כגון String , Integer ואחרות. אחת המחלקות החשובות ביותר היא מחלקת Object , שבתורה נמצאת גם בחבילת java.lang . הגודל של חבילה זו מבוסס על מרכיביה: 8 ממשקים, 37 מחלקות, 3 enums, 27 חריגים, 23 סוגי שגיאות ו-5 סוגי הערות.

שיטות ג'אווה בטוחות בשרשור למתחילים

מקור: בינוני באמצעות מאמר זה, תוכל ללמוד על פעולתן של שיטות בטוחות בשרשור ב-Java. הפסקת קפה מס' 165.  חבילות ב-Java.  שיטות בטוחות לחוטים למתחילים - 2גיליתי שמפתחי ג'אווה זוטרים/בינוניים רבים לא מבינים איך שיטות בטוחות בשרשור צריכות לעבוד בפרויקטים אמיתיים. ומכיוון שלרוב אנו עובדים בסביבה מרובת חוטים, השימוש הנכון בהם חשוב מאוד. שיטה בטוחה לשרשור היא שיטה שניתן לקרוא לה ממספר שרשורים בו זמנית מבלי להשפיע על מצב הנתונים של זה. הבנה לא מספקת של מושג זה מובילה לבאגים שקשה למצוא ולתקן. כדי להימנע מטעויות כאלה, בואו נסתכל על דוגמאות.

דוגמה מס' 1:

public static int countLetters(String input) {
    int counter = 0;

    for (Character c : input.toCharArray()) {
        if (Character.isAlphabetic(c)) {
            counter++;
        }
    }

    return counter;
}
  • שיטת countLetters היא סטטית, היא מחזירה ערך int ומקבלת פרמטר מחרוזת כקלט.
  • מונה משתנים פרימיטיבי נוצר בתוך השיטה, ואז הלולאה עוברת בלולאה בין התווים של מחרוזת הקלט ומגדילה את מונה המשתנים בכל פעם שנתקל בתו אות.
האם חוט השיטה הזה בטוח? מפתחים רבים אומרים שלא, מכיוון שבמקרה זה יש לנו פעולת תוספת שאינה בטוחה בחוט. בואו נבין את זה. במודל הזיכרון של Java יש לנו מחסנית וערימה. לכל חוט יש ערימה משלו, וכל החוטים חולקים את אותה ערימה. בהקשר זה, נתוני מחסנית תמיד בטוחים בשרשור, אך נתוני ערימה אינם. המחסנית מאחסנת פרימיטיבים והפניות לאובייקט. הערימה מכילה את החפצים עצמם. המשמעות היא שבדוגמה זו של קוד, כל שרשור מאחסן את מונה המשתנים שלו על הערימה ואין לו השפעה על הנתונים של שרשורים אחרים, כך שהשיטה בטוחה ל-thread . שים לב שערך המחרוזת הקלט הוא גם אובייקט, אבל מחרוזת ועטיפות פרימיטיביות ( Ingetal , Long , Double , Boolean וכן הלאה) בטוחות בשרשרת כי הן בלתי ניתנות לשינוי.

דוגמה מס' 2:

public static int countLetters2(String input) {
    List<Character> listCounter = new ArrayList<>();

    for (Character c : input.toCharArray()) {
        if (Character.isAlphabetic(c)) {
            listCounter.add(c);
        }
    }

    return listCounter.size();
}
קוד זה השתמש באותה לוגיקה כמו בדוגמה הראשונה, אך השתמש באובייקט List במקום במשתנה int פרימיטיבי . מהחלק הקודם, אנו יודעים שאובייקטים בג'אווה מאוחסנים בערימה ו- List הוא אובייקט. אנחנו גם יודעים שהמחסנית מאחסנת הפניות לאובייקטים על הערימה. בדוגמה מס' 2, כל שרשור יוצר אובייקט ArrayList חדש : והמשתנה listCounter מאחסן הפניה לאובייקט שלו בערימה, כך שאף שרשור אחר לא יכול לשנות את האובייקט הזה.
List<Character> listCounter = new ArrayList<>();
המשמעות היא ששיטה זו בטוחה בשרשור.

דוגמה מס' 3:

public class CounterUtil { // singleton

    List<Character> listCounter = new ArrayList<>();

    public int countLetters3(String input) {
        for (Character c : input.toCharArray()) {
            if (Character.isAlphabetic(c)) {
                listCounter.add(c);
            }
        }

        return listCounter.size();
    }
}
בדוגמה זו, יש לנו מחלקה יחידה (זה חשוב) CounterUtil עם משתנה גלובלי listCounter . משתנה זה נוצר במקביל למופע הסינגלטון. כאשר שרשורים מרובים קוראים לשיטת countChars3 , כולם משתמשים באותו משתנה גלובלי listCounter , שמאחסן הפניה לאותו אובייקט בערימה, והשרשורים שם ישפיעו זה על זה. לכן אנו יכולים להסיק ששיטה זו אינה בטוחה בחוט. וגם אם נשנה את List<Character> listCounter למשתנה פרימיטיבי int counter , הוא גם לא יהיה בטוח בשרשור כי כל השרשורים ישתמשו באותו משתנה פרימיטיבי.

דוגמה אחרונה:

public static int countLetters4(List<Character> inputList) {
    List<Character> listCounter = new ArrayList<>();

    for (Character c : inputList) {
        if (Character.isAlphabetic(c)) {
            listCounter.add(c);
        }
    }

    return listCounter.size();
}
שיטת countLetters4 מקבלת רשימה של תווים במקום פרמטר מחרוזת . כאן אנחנו לא יכולים להבטיח ששיטה זו בטוחה בשרשור. למה? כי אנחנו לא יכולים להיות בטוחים כיצד מפתחים ישתמשו בשיטה זו. אם שרשור אחר מבחוץ משנה את הנתונים ב- inputList במקביל לשיטת counterLetters4 שלנו , זה עלול להשפיע על התוצאה הסופית.

סיכום

הסתכלנו רק על ארבע דוגמאות, והן לא מכסות את כל ההיבטים של בטיחות חוטים בפרויקטים של Java, אבל הן מקום טוב להתחיל. בפעם הבאה שתראה שיטה בקוד שלך, שאל את עצמך, "האם שרשור השיטה הזה בטוח?" ומהר מאוד תבינו בבירור את התשובה.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION