אובמ - Home - Eytam Robotics · 2009-09-16 · יעיבצמ קרו א שי C/C++ ב שיש...
Transcript of אובמ - Home - Eytam Robotics · 2009-09-16 · יעיבצמ קרו א שי C/C++ ב שיש...
פרק 1 : מבוא 15
1 . מבוא
מבוא לתכנות מונחה עצמי
גישות בפיתוח תוכנה � מתודולוגיות
קיימות גישות שונות לפיתוח תוכנה, כלומר לניתוח ולתיכו� של מערכת, ובהתא� לכ�, ג� למימוש המערכת. לגישה או לשיטה בפיתוח תוכנה נהוג לקרוא מתודולוגיה. בפיתוח מערכת כשלהי נית� לבחור מבי� מספר מתודולוגיות פיתוח ובכול� אפשרי לממש אותה לכדי מוצר מוגמר. השאלה היא, איזו שיטה מבצעת זאת באופ� יעיל יותר, כלומר, איזו מהשיטות פשוטה
וטבעית יותר, ומאפשרת ביצוע שינויי� ותוספות ביתר קלות.
נסקור מספר מתודולוגיות עיקריות לפיתוח תוכנה:
• פיתוח מונחה תהליכי / פיתוח מבני: החשיבה היא בכיוו� התהליכי� שהתוכנה צריכה לבצע. שפות תומכות: C, פסקל, פורטר� ועוד רבות:
Data Structure X- - - - - - -
- - - - - - -- - - - - - -
Data Structure Y- - - - - - -
- - - - - - -- - - - - - -
Data Structure Z- - - - - - -
- - - - - - -- - - - - - -
Process 1 Process 2 Process 3
Java 16 על כוס קפה
• פיתוח מונחה נתוני/טבלאות: פיתוח יישומי� סביב טבלאות נתוני�. כלי פיתוח: מחוללי :(SQL) , שפות שאילתות�, מנועי בסיסי נתוני�יישומי
Data Table 1
Data Table 2
Data Table 3
SQL Query 1
SQL Query 1
SQL Query 1
• פיתוח מונחה עצמי: עצ� הוא שילוב של נתוני� ופעולות (Methods). היישו� מורכב C++, Java, Smalltalk, Simula :. שפות תומכות�ואינטראקציה ביניה �עצמי �מאוס
ועוד:
Object
Data- - - - - - -- - - - - - -- - - - - - -
Method 1
Method 2
Method 3
Object
Data- - - - - - -- - - - - - -
- - - - - - -
Method 1
Method 2
Method 3
Object
Data- - - - - - -- - - - - - -
- - - - - - -
Method 1
Method 2
Method 3
תכנות מונחה עצמי � מה זה?
תכנות מונחה עצמי� היא גישה פופולרית כיו� בעול� התוכנה, מכיוו� שבגישה זו מערכות
פרק 1 : מבוא 17
מפותחות באופ� מודולרי ויעיל. מדדי� בהנדסת תוכנה כמו יכולת שימוש חוזר במודולי תוכנה, יכולת הרחבה ויכולת שינוי של מרכיבי� שוני� במערכת, מובאי� לאופטימו� במערכות
שמפותחות בגישה זו.
במתודולוגיית פיתוח מונחה עצמי�, נוהגי� להתייחס למודל העצ�, הכולל את העקרונות הבאי�:
1. הפשטת נתוני (Data Abstraction) התעלמות מפרטי המימוש של העצ� והתרכזות במאפייני� הרלוונטיי� שלו.
לדוגמא, תוכנת סימולציה לכלי רכב כוללת ייצוג של מכונית:
תוכנה זו עשוייה לטפל רק במאפייני המשקל, הצבע, מספר הגלגלי�, הנהג, ההאצה, המהירות והמיקו�. מצד שני ייתכ� שלא יבואו לידי ביטוי סוג ומבנה השילדה, מבנה
המנוע, מערכת החשמל ועוד מערכות רבות, א� אינ� רלוונטיות.
ג� הפעולות על המכונית עשויות להיות כלליות, מבלי לרדת לפרטי� טכניי�: לדוגמא, הפעולה "פנה ימינה" עשויה להיות פעולה אטומית של המכונית, כהפשטה מעל הפעולות "האט", "סובב את ההגה", "בסיו� החזר את ההגה למצבו הרגיל"
שאינ� חשופות למשתמש.
(Information Hiding) והסתרת המידע (Encapsulation) 2. כימוסהאינפורמציה והפעולות הקשורות בתפקוד העצ� מרוכזות במקו� אחד, ופרטי המימוש חבויי� מהמשתמש. באמצעות שתי תכונות אלו מסופקת למעשה הפשטת
הנתוני� (Data Abstraction) שלעיל.
3. מודולריות הפרדת ליחידות נושאיות (=מודולי�), כ� שכל נושא מיוצג על ידי עצ�:
4. היררכיה הגדרת יחסי� היררכיי� (היררכיות ירושה, היררכיות הכלה, היררכיות קריאות) בי� עצמי�. כחלק מהיררכית הירושה קיי� מנגנו� הפולימורפיז, שמשמעותו טיפול אחיד בעצמי� בעלי צורות שונות. לדוגמא, כלי רכב שוני� בתוכנית מכילי� מכנה משות� ברמות שונות, ולכ� נית� לייצג� באמצעות ירושה
:(Inheritance)
Java 18 על כוס קפה
5. טיפוסיות חזקה (Strong Typing) מניעת בלבול/ערבוב בי� טיפוסי עצמי� שוני�. לדוגמא, א� בתכנית קיי� ייצוג למתק� שירות לרחיצת כלי רכב, למתק� זה לא
ייכנסו מטוסי� או ספינות...
6. בו�זמניות (Concurrency) תמיכה בפעולות בו זמניות של עצמי� שוני�. לדוגמא, כלי רכב המייוצגי� ביישו� הנ"ל עשויי� לנוע במקומות שוני� באותו פרק
זמ�. לש� כ� נדרשת הדמייה של פעילות אסינכרונית של העצמי� השוני�.
7. הימשכות (Persistency) יכולת שמירת מצב העצ� לאור� זמ�, כגו� שמירת
העצ� לקוב& או למדיה אחרת. עקרו� זה ידוע ג� בש� Serialization. לדוגמא, המשתמש בתוכנה המייצגת כלי רכב עשויי לבקש לשמור את "תמונת העול�" ולכבות את המחשב. מאוחר יותר הוא יהיה מעוניי� לטעו� את התוכנה מאותה נקודה בה
הפסיק, ולהמשי� מש�.
כיו� קיימות שפות תכנות רבות התומכות בעקרונות העצ�. דוגמאות פופולריות לשפות כאלו ה� ++Python ,Smalltalk ,Java ,C. המושג העיקרי בתכנות מונחה עצמי� בשפות אלו הוא
,C) בשפות פרוצדורליות �הקיי struct/record זוהי הרחבה של מושג ה :(class) "מחלקה"Pascal) הכוללת בנוס� לנתוני� של המבנה ג� פעולות לטיפול בה�. בנוס� לכ�, כוללות שפות אלו ג� תמיכה מובנית בהסתרת מידע, אתחול והריסה אוטומטיי� של עצמי�, ירושה
ופולימורפיז�, טיפול בחריגות ועוד.
פיתוח תוכנה מונחה עצמי� היא הגישה המקובלת והפופולרית כיו� בעול� התוכנה. גישה זו מומשה כבר בשנות השישי� בשפה Simula67 , ובמש� עשרי� השני� הבאות בשפות
.Smalltalk, Objective C, Eiffel, Ada
יתרונות פיתוח מונחה עצמי
• רכיבי תוכנה מפותחי� באופ� מאוד מודולרי ובמינימו� תלויות
• תמיכה טובה יותר בתוספות ושינויי� לתוכנה קיימת
• מאפייני העצ� הבסיסיי כימוס והסתרת מידע מספקי� יכולת אבסטרקציה מעולה.
• יכולת טובה יותר בשימוש חוזר בתוכנה
• מעבר ישיר בי� שלבי הפיתוח: ניתוח (Analysis), תיכו� (Design) ומימוש (Implementation)
• עבור מערכות סימולציה: מודל טבעי יותר של העול� האמיתי
פרק 1 : מבוא 19
Javaב� תכנות מונחה עצמי שפת Java היא בי� השפות ה"צעירות" בעול� התוכנה ובו בזמ� בי� הפופולריות ביותר. הפשטות והקלות שמציעה Java לפיתוח יישומי� מורכבי�, גרמו לכ� שכבר חלק נכבד מתעשיית
ההיי טק מאמ& אותה כשפת הפיתוח הרשמית שלו.
Java הושפעה מקודמתה, שפת ++C, מי שהפכה את הגישה מונחית העצמי� לפופולרית. ג� מ
Eiffel, Smalltalk ו Objective C הועתקו עקרונות ומנגנוני שפות תכנות. Java נבנתה כהמש� התפתחות החשיבה בכוו� מונחה עצמי�, א� יוצריה בחרו בפשטות ככוו� עיקרי בהגדרתה. אי� ב Java תחביר ערכי� המשולב ע� תחביר מצביעי� כפי שיש ב ++C/C יש א� ורק מצביעי� (הנקראי� בתיעוד references). מספר מנגנוני השפה מועט, אי� ירושה מרובה וקיי� טיפול
.(Garbage Collection) אוטומטי בשחרור זיכרו�
יתרו� נוס� של Java הוא היותה שפה בלתי תלויה במחשב ובמערכת הפעלה, ולכ� היא מתאימה Java . תכניות�שוני �ומערכות מסוגי �באופ� מבוזר מעל מחשבי �ליישומי אינטרנט הפועלימורצות על ידי מכונה מדומה (Virtual Machine) תכנית המשמשת כמתוו� בי� היישו� לבי� המערכת שעליה הוא מור&. נית� להדר תכניות Java על מחשב אחד ולהריצ� על מחשב אחר, או
להרי& יישו� מבוזר על פני מספר מערכות מחשב שונות!
בנוס� לכ�, Java נחשבת כשפה מונחית עצמי� אמיתית הכוללת תמיכה בכל 7 עקרונות העצ� שסקרנו לעיל.
רקע היסטורי
James Gosling על ידי Oak �פותחה בתחילת שנות ה 90 של המאה הקודמת תחת הש Java
מחברת Sun. היא יועדה ליישומי מערכות אלקטרוניות משובצות מחשב. מאוחר יותר הוסבה לשפה כללית כשעיקר מטרתה פיתוח תוכנה לאינטרנט.
Java היא שפה שפותחה על ידי חברת Sun מתו� אסטרטגיה של ביטול תלות היישומי�
במחשבי� ובמערכות ההפעלה. המטרה על פי Sun היא "כתוב פע� אחת, הר& בכל מקו�" .("Write Once, Run Anywhere")
מרכיבי השפה Java היא שפה פשוטה וקלה ללימוד: היא מאוד דומה לשפות ++C/C מבחינת תחביר ההוראות
הבסיסי, א� המנגנוני� המורכבי� והמסורבלי� הוצאו ממנה.
:Java ב� מנגנוני
• מחלקות ועצמי�
• ממשקי משתמש (AWT, Swing) וגרפיקה מובני�
Serialization ,קלט/פלט •
• תמיכה בשירותי מערכת: הדפסה, Drag & Drop, נגישות
• Threads, ריבוי משימות
Java 20 על כוס קפה
• תמיכה במולטימדיה
(Applets) �תמיכה באינטרנט, ובפרט תכניות המורצות מדפדפני •
(Beans) �מודל רכיבי •
(JDBC) �תמיכה בבסיסי נתוני •
JNI ,RMI, IDL/CORBA :�מתקדמי �מבוזרי �פרוטוקולי •
• מנגנוני בטיחות, הצפנה ופענוח
• תמיכה בשפות ובמערכות סימני� בינלאומיות
XML תמיכה ב •
(PDAs) �נישאי �תמיכה בתכנות להתקני •
• ויש עוד...
:Java ב� קיימי שאינ C/C++ מנגנוני
,(p-- ,p++) או חיסור �לדוגמא, לא נית� לבצע על מצביע קידו �אריתמטיקת מצביעי • מצביע מקבל ער� רק על ידי הקצאת עצ�, ולא נית� לשנות את כתובתו.
(Preprocessor) מעבד �קד •
typedef ,union ,struct •
(data segment) �או על מקטע הנתוני (call stack) הקצאה סטטית על המחסנית •
• ירושה מרובה (קיימת ירושת ממשקי� מרובה)
• שחרור זכרו� מפורש על ידי המתכנת Java כוללת מנגנו� לשחרור זיכרו� אוטומטי על ידי .Garbage Collector
JDK סביבת הפיתוח Java Development Kit ,JDK, היא סביבת הפיתוח הבסיסית שמספקת חברת Sun בחינ�
לפיתוח יישומי Java. סביבת פיתוח זו היא "עירומה" במוב� זה שאינה כוללת ממשק משתמש ידידותי או כלי פיתוח מתקדמי� ויזואליי�. סביבת פיתוח זו היא טקסטואלית, תו� ביצוע
.(Command Line) , הידור והרצה משורת הפקודה�פעולות עריכה, ארגו� קבצי
:Sun ניתנת להורדה מהאינטרנט מאתר הבית של חברת JDK סביבת ה
http://java.sum.com
לעבודה ע� גירסה מתאימה לספר זה, יש לבחור בגירסה 5 של Java ומעלה.
מרכיבי סביבת הפיתוח
סביבת הפיתוח כוללת את המרכיבי� הבאי�:
• כלי פיתוח:
.Java לשפת המכונה המדומה java משמש להידור תכניות (javac) מהדר −
− כלי להרצה (java) מרי& את היישו� על המכונה המדומה.
java כלי לניפוי תכניות (jdb) מנפה −
פרק 1 : מבוא 21
− כלי תיעוד אוטומטי (javadoc) משמש ליצירת תיעוד אוטומטי לתכנית
(appletviewer) Applets כלי לצפייה ב −
− כלי� נוספי�: כלי יצירת ממשק לקוד C (javah), כלי פיתוח ל RMI, כלי דחיסה
(jar), כלי לחתימה דיגיטלית (javasign) ועוד.
• מכונה מדומה (Virtual Machine) התוכנה המריצה את יישומי Java (להל�).
• תיעוד מסמכי תיעוד מקוו� (ב HTML) של סביבת הפיתוח.
Java מדרי� לפיתוח בשפת −
(Java API Documentation) Java תיעוד ספריות −
− תיעוד כלי הפיתוח
− דוגמאות תכניות
(JLS) Java מפרט שפת −
(JVM Spec.) מפרט המכונה המדומה −
.Sun באתר הבית של חברת �תיעוד רב נוס �כמו כ� קיי
סביבות פיתוח גרפיות מתקדמות
קיימות סביבות פיתוח גרפיות עשירות יותר הניתנות להורדה בחינ� ה� מאתר האינטרנט של חברת Sun וה� מאתרי� אחרי�.
להל� שתי סביבות חינמיות הנחשבות לפופולריות כיו�:
.Java סביבת פיתוח תוכנה קוד פתוח, המתאימה במיוחד ל Eclipse •
http://www.eclipse.org
.Java עבור Sun סביבת פיתוח של חברת NetBeans •
http://www.netbeans.org/
Java כיצד פועלת
קבצי והידור
.java יכולה להיות מורכבת ממספר קבצי מקור, כשכל קוב& הוא בעל סיומת Java תכנית
מהדרי� את קבצי המקור על ידי מהדר java. ב JDK ש� המהדר הוא javac לדוגמא, א� ש� הקוב& הוא file1.java, נהדר אותו על ידי
javac file1.java
א� ההידור הצליח, נוצר קוב& מהודר בפורמט קודי בתי� (byte codes) בש� file1.class. נית� להדר מספר קבצי מקור בהוראה יחידה באופני� הבאי�:
1) javac file1.java file2.java file3.java
2) javac *.java
Java 22 על כוס קפה
הערה: בכדי להדר את התכנית ע� תאימות כלפי כל התוספות והשינויי� שהוכנסו בגירסה 5 יש לבצע הידור כ�:
javac -source 1.5 file1.java file2.java file3.java
(Java Virtual Machine) הרצה על ידי המכונה מדומה
המכונה המדומה של Java (JVM) היא תוכנה המריצה את יישומי Java. היא מופעלת על ידי כלי
ההרצה java. פעולתה הראשונה היא טעינת הקוד להרצה תו� אימות (Verification) תקינות התכנית. בזמ� הרצת תכנית מבוצעות בדיקות בטיחות תו� הרצת הקוד כגו� חריגה מגבולות .Applets &בדפדפני אינטרנט בכדי שיוכלו להרי �מער�. המכונה המדומה היא מרכיב הכרחי ג
לאחר ההידור נית� להרי& את התכנית. לדוגמא, א� התכנית מורכבת משלושה קבצי מקור כנ"ל, והקוב& file2.java כולל את המתודה ()main נבצע
java file2
הוראה זו תפעיל את המכונה המדומה (VM), תטע� את קבצי התכנית המהודרי� ותתחיל לבצע :main() החל מ �אות
(java) הרצה
file3.class
VM מכונה מדומה
file1.javafile2.java
file3.java
file1.class file2.class
מערכת הפעלה
חומרה
(javac) הידור
main()
כפי שנית� לראות, המכונה המדומה פועלת מעל מערכת ההפעלה, תו� בידוד היישו� מהמערכת שעליה הוא מור&. משו� כ�, נית� להרי& את היישו� בכל פלטפורמת מחשב (מערכת הפעלה +
מחשב), בתנאי שנכתבה לה מכונה מדומה מתאימה:
פרק 1 : מבוא 23
Windows JVM
Windows
PC� Pentium
Unix JVM
Unix
Sun � Sparc
Linux JVM
Linux
PC � Pentium
file3.classfile1.class file2.class
Cell Phone JVM
Cell phone OS
Cell Phone HW
JIT Compiling
Just-In-Time (JIT) Compiling הוא מנגנו� אופטימיזציה של Java, אשר פירושו הידור קוד
המכונה המדומה של Java לקוד המכונה (האמיתית, אסמבלר) עליה מור& היישו�. יישומי� המהודרי� על ידי מהדר JIT מאפשרי� הידור דינמי של קוד Java (כלומר תו� כדי ריצת היישו�
עצמו) לקוד מכונה (האמיתית) על מנת שיבוצע מהר יותר.
Java גירסאות גירסאות Java על שמ� ומספריה� גורמות לבילבול בקרב משתמשי� רבי�, בעיקר עקב ההפרדה Standard ההפרדה שבי� גירסת ה �שבי� גירסת סביבת הפיתוח לבי� סביבת הריצה, כמו ג
לגירסת ה Enterprise. בסעי� זה נתאר את גירסאות Java השונות עד עתה.
JVM וגירסאות JDK גירסאות
Java לעומת גירסת המכונה המדומה של Java של (JDK) זה לגירסת הפיתוח �נתייחס בסעי
(JVM), שהיא סביבת זמ� הריצה: ההבחנה הזו גרמה לבילבול רב, ולמעשה היא לא קיימת בפועל: לכל גירסת JDK מותאמת גירסת JVM אחת ויחידה, ולכ� אפשר לראות אות� כמערכת
אחת, בעלת גירסת Java יחידה.
ה� הש� המתלווה למספר הגירסה וה� אופ� מספור הגירסה הוחלפו במהל� השני�:
SE הבא), ואחר כ� ב �(ראה/י בסעי J2SE ב �הוחל JDK •
• x.1 הוחל� ב x. לדוגמא, במקו� 1.5 מספר הגירסה הוא 5.
Java 24 על כוס קפה
הטבלה הבאה מפרטת את כל גירסאות Java עד עתה ואת הגירסאות המתוכננות לעתיד הקרוב:
מאפייני עיקריי תאריD כינוי גירסה
JDK 1.0 1996 .והמכונה המדומה בגירסתה ינו Java שפתהראשונה
JDK 1.1 1997 .משופר פב �מודל אירועי •
• מנגנוני� לתמיכה בשפות בינלאומיות
RMI, JDBC, Java Beans, :ספריות •
• שיפור ביצועי�
J2SE 1.2 Playground 1998 .דצמ Collections, 2D ,Swing :ספריות • Graphics
• מנגנוני בטיחות משופרי�
J2SE 1.3 Kestrel 2000 מאי ,Sound, Naming/Directory :ספריות • CORBA
• שיפור ביצועי�
J2SE 1.4 Merlin 2002 .פב assert :תוספת לשפה •
XML, :לספריות �תוספות/שיפורי • IPv6, IO
J2SE 5 (1.5)
Tiger 2004 .ספט ,Enums ,Generics :תוספות לשפה • Autoboxing/ ,משופרת for לולאת .Annotaions ,static import ,Unboxing
• תוספות/שיפורי� לסיפריות רבות
• תוספות/שיפורי� למכונה המדומה של Java: שיפורי ביצועי�, שיפורי בטיחות
SE 6 (1.6)
Mustang 2006 �סותחילת 2007
GUI בספרית ה �שיפורי • (AWT/Swing/2D)
• שיפורי� בתמיכה בשפות בינלאומיות
• ניפוי: גישה לתוכ� ה Heap, ועוד
File ,Collections :בספריות �שיפורי • Floating Point ,IO
XML ,JDBC ב �שיפורי •
• שיפורי� בניהול ובקרה
• שיפורי� ותוספות בבטיחות
Compiler גישה ל •
SE 7 (1.7)
Dolphin עתידי עתידי
כיו�, גירסאות Java מתוכננות להתעדכ� במחזורי� של 12 עד 18 חודשי�.
פרק 1 : מבוא 25
J2ME, J2SE, J2EE :גירסאות על פי פלטפורמה
חלוקה נוספת של גירסאות Java היא על פי הפלטפורמה המיועדת לפיתוח:
פלטפורמה גירסה
J2ME - Java 2 Micro Edition PDAs , ל�סלולריי �מיועדת למכשירי (Personal Digital Assistant)
ולמערכות משובצות.
J2SE - Java 2 Standard Edition מיועדת ליישומי מחשב שולחני וליישומישרת לקוח קטני�.
J2EE - Java 2 Enterpirse Edition .�מיועדת ליישומי שרת לקוח כבדיכוללת את J2SE + ספריות לתכנות
בסביבת שרתי�.
.Java 2 גירסאות הפלטפורמה החל מיציאת גירסת �לב לכ� שהספרה 2 הוספה לש �יש לשיבגירסאות העדכניות הספרה 2 מושמטת מש� הגירסה, לדוגמא, SE 6 הוא ש� הגירסה
העדכנית. .J2SE הגירסה המומלצת להורדה וללימוד באמצעות ספר זה הינה
Java 26 על כוס קפה
מקורות וספרות הרחבה Effective Java, Addison-Wesley, 2001/2005
ספר שנכתב על ידי אחד ממפתחי Java וכולל המלצות חשובות לשימוש יעיל בשפה.
[Bloch 01]
The Unified Modeling Language User Guide, GradyBooch, James Rumbaugh, Ivar Jacobson, Addison Wesley,1999
ספר מקי� ללימוד UML, מאת האבות היוצרי� של תק� זה. החומר מובא בצורה שוטפת וברורה, ע� תרשימי� רבי� ודוגמאות ממערכות
עדכניות.
[Booch99]
Design Patterns: Elements of Reusable Object-Oriented
Software, Erich Gamma, Richard Helm, Ralph Johnson, andJohn Vlissides. (GOF), Addison Wesley 1995.
המקור הרשמי לנושאי Design Patterns. התוכ� ברור ומובא בצורה נוחה לקריאה. עקב גילו של הספר, מוסכמות הסימוני� והדוגמאות
המובאות בו לא עדכניות.
[Gamma95]
Java2 SDK Documentation, Sun Microsystems,http://java.sun.com/
התיעוד המלא והמקי� ביותר לשפת Java ולספריות הפיתוח שלה.
[Java2sdk]
The Java Language Specification, Sun Microsystems,http://java.sun.com/
.Java מפרט שפת התכנות
[JLS]
The Java Virtual Machine Specification, SunMicrosystems, http://java.sun.com/
.(JVM) Java מפרט המכונה המדומה של
[JVMSpec]
The Java Tutorial, Sun Microsystems,http://java.sun.com/docs/books/tutorial/
מדרי� מעולה לתכנות מעשי ב Java, תו� מת� דוגמאות רבות ומגוונות.
[JTutorial]
Just Java 2, Peter van der Linden, Sun icrosystems/PrenticeHall, 2004
מדרי� נרחב ל Java 2 שנכתב על ידי אחד ממפתחיה הוותיקי� של .Sun Microsystems ב Java
[Linden 04]
Design Patterns תכנות מונחה עצמי� מתקד�, מאיר סלע, מרכז
ההדרכה עיט�, 2004 [MH-DP 2004]
פרק 2 : תכנות בסיסי 27
2 . תכנות בסיסי
Java תכנית ראשונה ב� נכתוב תכנית Java בסיסית המדפיסה למס� את הפלט:
H e l l o J a v a !
קוד התכנית:
/** display "Hello Java!" to the standard output. */
public class Hello {
public static void main(String[] args) {
System.out.println("Hello Java!"); // display the text
}
}
כדי להרי& את התכנית יש לבצע:
1. הקלדה של הקוד בקוב& בש� Hello.java על ידי תכנית עריכה כלשהי.
2. הידור הקוב&. בסביבת JDK מהדרי� את התכנית כ�:
javac Hello.java
.Hello.class �לאחר ההידור נוצר קוב& בש
3. הרצת התכנית. בסביבת JDK מריצי� את התכנית כ�:
java Hello
פלט התכנית:
H e l l o J a v a !
הסבר התכנית
התכנית כוללת מספר חלקי�:
Java 28 על כוס קפה
• הגדרת המחלקה הראשית
• הגדרת המתודה הראשית במחלקה
• הערות ותיעוד
הגדרת המחלקה הראשית
:public והגדרתה כ , class מבוצעת תו� שימוש במילה Hello הגדרת המחלקה
public class Hello {
}
כל תכנית Java כוללת לפחות מחלקה ראשית אחת. תיתכנה מחלקות נוספות באותו קוב& , א�
.public רק אחת מה� מצוינת כראשית על ידי
בי� הסוגריי� המסולסלות נית� להגדיר מתודות ומשתני� השייכי� למחלקה, כפי שנראה בהמש�.
ש� קוב& התכנית חייב להיות בדיוק כש� המחלקה הראשית בקוב&, כלומר Hello.java (ע� .(!Windows במערכת �גדולה, ג H האות
הגדרת המתודה הראשית במחלקה :C/C++ בדומה לתכניות בשפות ,main המתודה הראשית נקראת
public static void main(String[] args) {
System.out.println("Hello Java!"); // display the text
}
המתודה main חייבת להופיע במחלקה הראשית של התכנית. כותרת המתודה חייבת להיות בצורה הנ"ל. הסוגריי� המסולסלות מציינות את התחלת וסיו� המתודה. כפי שנראה בהמש�,
המחלקה יכולה להכיל מתודות נוספות.
משמעות הכותרת של המתודה:
public static void main(String[] args)
public המתודה ניתנת לקריאה על ידי מתודות ממחלקות אחרות.
static נית� לקרוא למתודה ללא הגדרת עצ� מהמחלקה.
void המתודה לא מחזירה ער� כלשהו.
String[] args מער� מחרוזות הפרמטרי� לתכנית מקביל ל argc, argv בתכניות
.C/C++
הערה : בשלב זה לא נכנס למשמעות הגדרה זו של המתודה די להבי� כרגע שזוהי הגדרה הכרחית בכל תכנית Java בכדי שנית�
יהיה להרי& אותה.
החלק הנמצא בי� הסוגריי� המסולסלות
פרק 2 : תכנות בסיסי 29
System.out.println("Hello Java!"); // display the text
.System שבמחלקה out �של העצ println המתודה, והוא כולל קריאה למתודה �הוא גוהמתודה מדפיסה את המחרוזת הנתונה לה כפרמטר לפלט התקני, כלומר למס�. לאחר המחרוזת מודפס תו שורה חדשה. ההוראה ()System.out.print ללא הסיומת ”ln“ מבצעת
הדפסה דומה, א� ללא תוספת תו שורה חדשה.
הערה : אנו נחזור ונכיר מנגנו� קלט/פלט זה באופ� מעמיק יותר בהמש�. די להבי� כרגע שזוהי הדר� להדפיס תוכ� כלשהו למס�.
הערות ותיעוד בתכנית שתי צורות רישו� הערות:
1. הערות בצורה הנהוגה ב ++C, ע� קו נטוי כפול:
System.out.println("Hello Java!"); // display the text
2. הערות בתו� בלוק דמוי הערת C ע� כוכבית כפולה בתחילתו, /* ...... **/ : /** display "Hello Java!" to the standard output. */
הערות מסוג זה משמשות את הכלי ליצירת תיעוד אוטומטי javadoc. הערה זו לפני (HTML) לקוב& תיעוד javadoc הגדרת מחלקה, מתודה ו/או משתנה תוכנס על ידי
של התכנית.
כמו כ�, נית� לרשו� הערות בלוק בסגנו� שפת C על ידי /* ...... */, כלומר ללא כוכבית כפולה בתחילת�, מה שאומר שה� לא ייכללו בתיעוד האוטומטי.
טיפוסי ומשתני
נכתוב את התכנית הנ"ל מעט אחרת:
/** display "Hello Java!" to the standard output. */
public class Hello {
public static void main(String[] args) {
String s = "Hello Java!"; System.out.println(s); // display the text
}
}
הסבר: תכנית זו דומה לקודמתה, למעט העובדה שכא� הגדרנו משתנה מטיפוס מחרוזת:
String s = "Hello Java!";
בהצהרה על משתנה , ראשית מופיע הטיפוס (type) ואח"כ ש� המשתנה. בדוגמא, הטיפוס הוא
.s והמשתנה הוא String
Java 30 על כוס קפה
משתנה הוא כתובת בזכרו� שבו מאוחס� ער� המשתנה. בדוגמא הנ"ל, הש� s מציי� כתובת .“Hello Java!" בזכרו� בו נמצאת המחרוזת
println() נית� לבצע פעולות שונות על המשתנה, אחת מה� היא להדפיסו על ידי ההוראהשהכרנו קוד�:
System.out.println( s );
אנחנו יכולי� להוסי� משתני� נוספי� לתכנית ולבצע עליה� פעולות שונות. בסעי� הבא נראה תכנית כזו.
חישוב ממוצע של מספרי
בסעי� זה נכתוב תכנית שתחשב ותדפיס את הממוצע (מספר ממשי) של שלושה מספרי� שלמי� נתוני�. קוד התכנית:
public class Average{
public static void main(String[] args) {
int num1, num2, num3;
float avg;
num1 = 21;
num2 = 15;
num3 = 94;
avg = num1 + num2 + num3;
avg = avg / 3;
System.out.println("The average is: " + avg);
}
}
פלט התכנית:
T h e a v e r a g e i s : 4 3 . 3 3 3 3 3 2
הסבר:
• הצהרה על משתני וטיפוסיה אנו שוב רואי� הגדרת משתני� הפע� מטיפוסי� מספריי�:
− הטיפוס int (integer) משמש להצהרה על משתנה מטיפוס של�: int num1, num2, num3;
:avg מציי� טיפוס ממשי בהצהרת המשתנה (floating point) float הטיפוס − float avg;
avg הוא משתנה ממשי שבו תחושב תוצאת הסכו� ולאחר מכ� הממוצע.
טיפוסי� נוספי� לדוגמא הקיימי� בשפה:
פרק 2 : תכנות בסיסי 31
byte בית בודד
unicode תו char
long של� ארו�
double ממשי בעל דיוק כפול
נרחיב עוד בנושא טיפוסי משתני� בפרק הבא.
: avg מחושב ומוצב ל �, סכומ�למשתני �לאחר מת� הערכי
avg = num1 + num2 + num3;
הסימ� "=" ב C מציי� פעולת הצבה (Assignment). תוצאת הביטוי שמימי� לסימ� מוצבת לתא בזיכרו� שמשמאל לו. פעולה זו נקראת ג� השמה.
שאלה: אי� מסמני� שוויו� בביטוי לוגי?
תשובה: על ידי שני תווי� רצופי� כנ"ל : "==". נרחיב בנושא בהמש�.
חישוב הממוצע מתבצע על ידי חילוק avg ב 3 :
avg = avg / 3;
avg / 3 מבצע פעולת חילוק וזו מוצבת ל avg. אי� כל בעיה בהימצאותו של avg משני צידי הוראת ההצבה הצד הימני מחושב קוד�, ולאחר מכ� מוצבת התוצאה למשתנה שבצד
השמאלי. נית� לקצר את התכנית על ידי ביצוע פעולות החיבור והחלוקה בהוראה יחידה:
avg = (num1 + num2 + num3) / 3;
כא� ביצענו חיבור בתו� סוגריי� מכיוו� שלאופרטור החילוק עדיפות על אופרטור החיבור. הסוגריי� מצייני� את סדר הפעולות הנדרש. בסיו� מודפס ערכו של avg על ידי קריאה לשירות
ההדפסה:
System.out.println("The average is: " + avg);
סימ� החיבור המופיע בי� המחרוזת ל avg גור� לשירשור של avg לטקסט המחרוזת, ולכ� מודפס המשפט השל�:
T h e a v e r a g e i s : 4 3 . 3 3 3 3 3 2
גירסה מקוצרת של התכנית נכתוב שוב את התכנית, הפע� בגירסה מקוצרת:
public class Average{
public static void main(String[] args) {
int num1=21, num2=15, num3=94;
float avg = (num1 + num2 + num3) / 3.0F;
System.out.println("The average is: " + avg);
}
}
Java 32 על כוס קפה
• המשתני� השלמי� num1,num2 ו num3 מאותחלי� עוד בהגדרת�.
• המשתנה הממשי avg מאותחל ג� הוא בהגדרתו כתוצאת החלוקה של סכו� 3 השלמי�: avg = (num1 + num2 + num3) / 3.0F;
− ביצענו חיבור בתו� סוגריי� מכיוו� שלאופרטור החילוק עדיפות על אופרטור החיבור. הסוגריי� מצייני� את סדר הפעולות הנדרש.
− בחלוקה, ציינו שהמנה היא 3.0 ומסוג ממשי float על ידי ”3.0F“ : זאת מכיוו� שלו חילקנו בשל� 3, היתה מתבצעת פעולת חילוק בשלמי�, והתוצאה היתה 43!
התוספת F מציינת עבור המהדר שמדובר בממשי רגיל מסוג float. לו כתבנו 3.0 בלבד, היה ער� זה מוב� כממשי מטיפוס double, מה שהיה גור� לכ� שתוצאת החלוקה היתה א� היא מטיפוס double, ונסיו� ההצבה ל avg היה נות� שגיאת הידור! שגיאה זו טמונה בעובדה שלא נית� להציב למשתנה מטיפוס מסויי� ער� של טיפוס "גדול" יותר יש כא� חשש לאבד� מידע, ולכ� זוהי המרה לא חוקית. בפרק הבא נרחיב בנושא
טיפוסי� והמרות.
טיפוסי בסיסיי ב Java קיימי� מספר טיפוסי� בסיסיי� המובאי� בטבלה שלהל�:
תאור טיפוס קטגוריה
תו בודד בפורמט Unicode, 16 סיביות char תוי
של� בית, 8 סיביות byte שלמי
short קצר, 16 סיביות �של
int , 32 סיביות�של
long ארו�, 64 סיביות �של
ממשי, 32 סיביות float ממשיי
double ממשי כפול, 64 סיביות
משתנה בוליאני boolean בוליאני
כל הטיפוסי� המספריי� (שלמי� וממשיי�) ה� מסומני (signed) כלומר, יכולי� לקבל ה� ערכי� חיוביי� וה� ערכי� שליליי�.
בתכנית הדוגמא הקודמת ראינו שימוש בשלמי� ובממשיי�. נראה כעת דוגמאות נוספות.
• שימוש בתו: char c;
c = 'a';
System.out.print(c);
הטיפוס char הוא ב� 16 סיביות ומייצג ער� Unicode, כ� שנית� לייצג באמצעותו תווי� מכל
פרק 2 : תכנות בסיסי 33
השפות הקיימות. לדוגמא, נית� לכתוב:
char c ='א';
System.out.print(c);
מודפס:
א
• שימוש בממשי: float f = 10.0; // error: cannot convert from double to float
f = 10.0F; // OK
f = f - 0.5F;
System.out.print(f);
מדוע מתקבלת הודעת שגיאה בשורה הראשונה ? ב Java ליטרל (=ער�) ממשי הוא בברירת מחדל מסוג double, והמרה מרומזת של משתנה מטיפוס זה לטיפוס "קט�" יותר (float) אינה
חוקית.
סימו� הליטרל על ידי האות F או f מציינת שהוא מסוג float ולכ� השורה השנייה תקינה.
הגדרת קבועי
קבועי� ה� תאי זכרו� המחזיקי� בערכי� כלשה�, בדומה למשתני�, אול� בניגוד לה� לא
נית� לשנות ער� של קבוע לאחר שאותחל. ב Java המילה השמורה final משמשת להגדרת קבועי�. לדוגמא:
final int N = 10; // N is constant
כעת N מוגדר כקבוע ולא נית� לשנותו במהל� התכנית. נסיו� לעשות זאת יגרו� לשגיאת הידור.
מחרוזות ב Java קיימת מחלקה תקנית לייצוג מחרוזת בש� String. מחלקה זו כוללת מיגוו� פעולות על
:String מחרוזות כגו� העתקה, שרשור, הדפסה, הצבה וכו'. דוגמא לשימוש ב
public class StringApp{
public static void main (String[] args) {
String s1 = "Hello";
String s2 = " Java";
System.out.println(s1 + s2); // prints "Hello Java"
System.out.println(s1 + s2 + "!"); // prints "Hello Java!"
String s3 = s1; // s3 = "Hello"
}
}
Java 34 על כוס קפה
בתכנית מגדירי� מספר עצמי� מסוג String, ומבצעי� עליה� פעולות:
− הצבת מחרוזת אחת לשנייה על ידי אופרטור ההצבה "="
− שרשור מחרוזות על ידי אופרטור השרשור "+"
− הדפסת המחרוזות על ידי המתודה println שהכרנו בתכניות הקודמות. מתודה זו .String עצמי �ובכלל �שוני �מסוגי �מועמסת לקבל פרמטרי
משפטי תנאי לעיתי� תכופות מהל� התכנית נקבע באופ� דינמי על פי הקלטי� או חישובי� מספריי�. בנקודות מסוימות בתכנית נרצה לבצע קטע קוד כתלות בתנאי מסוי�. בנקודות אחרות נרצה לבצע קטע
קוד מספר פעמי�. Java כוללת הוראות בקרה לקביעת מהל� התכנית:
• משפט if-else לביצוע מותנה של הוראות
• לולאות מסוגי� שוני� המשמשות לביצוע חוזר של קטע קוד
if-else משפט
:if-else ו if מההוראות �משפטי התנאי מורכבי
: if תחביר הוראת
if( תנאי )
הוראה/ות
: if-else תחביר הוראת
if( תנאי )
הוראה/ות
else
הוראה/ות
בתו� גו� המשפט יכולה להופיע הוראה בודדת או מספר הוראות, מוקפות על ידי הסוגריי� {}.
• במשפט if א� התנאי מתקיי�, מבוצעת/ות ההוראה/ות שבגו� משפט התנאי, אחרת ממשיכי� להוראה העוקבת למשפט התנאי.
• במשפט if - else א� התנאי מתקיי�, מבוצעת/ות ההוראה/ות שבגו� הוראת if, אחרת מבוצעת/ות ההוראה/ות שבגו� הוראת else. לאחר מכ� ממשיכי� להוראה העוקבת למשפט
התנאי.
פרק 2 : תכנות בסיסי 35
נית� לתאר את משפטי התנאי if ו if-else על ידי תרשי� זרימה באופ� הבא:
תנאישקראמת
ות/הוראהות/הוראה
if - else
תנאישקראמת
ות/הוראה
if
לדוגמא, א� נרצה להדפיס את ההפרש שבי� 2 מספרי�, num1 ו num2, בערכו המוחלט נבצע:
System.out.print("|num1 - num2|= ");
if( num1 > num2 )
System.out.print(num1 - num2);
else
System.out.print(num2 - num1);
נית� לתאר את ההוראה הנ"ל על ידי תרשי� זרימה:
num1 > num2
System.out.print(num1 - num2);
כן לא
System.out.print(num2 - num1);
המשך להוראה הבאה
num2 גדול מ num1 , ובמידה וערכו אמת כלומר�כוללת ביטוי לוגי בסוגריי if ההוראהההוראה העוקבת מבוצעת:
if( num1 > num2 )
System.out.print(num1 - num2);
ההוראה else לאחר ההוראה if מציינת פעולה אלטרנטיבית לביצוע א� תוצאת הביטוי הלוגי הייתה שקר:
Java 36 על כוס קפה
else
System.out.print(num2 - num1);
.else ללא הוראת if היא אופציונלית ייתכ� משפט else ההוראה
תכנית דוגמא: התכנית קוראת מהקלט שני מספרי� שלמי� ומדפיסה את ההפרש ביניה� בערכו המוחלט:
import java.util.*;
public class Test {
public static void main(String[] args) {
int num1, num2;
System.out.print("Enter 2 integers: ");
Scanner sc = new Scanner(System.in);
num1 = sc.nextInt();
num2 = sc.nextInt();
System.out.print("|num1 - num2|= ");
if( num1 > num2 )
System.out.print(num1 - num2);
else
System.out.print(num2 - num1);
}
}
הרצת התכנית דוגמא להרצת התכנית: בתחילת הריצה מודפס למס�
E n t e r 2 i n t e g e r s :
כעת נדרש להכניס קלט, נקליד למשל את המספרי� 7 ו 11:
E n t e r 2 i n t e g e r s : 7 1 1
כעת מתקבל פלט התכנית:
| n u m 1 - n u m 2 | = 4
הסבר התכנית : int ,�מטיפוס של �כפי שנית� לראות, התכנית מגדירה 2 משתני
int num1, num2;
Scanner �על ידי עצ �נקראי �, וה�שלמי �לאחר מכ� מתבקש המשתמש להקליד 2 מספרילתו� num1, num2 אנו לא נרד פה לפרטי פעולת הקלט, מכיוו� שהיא מעט מורכבת. בשלב זה
די בהבנה של הפעולות הנדרשות לביצוע הקלט:
1. ייבוא הספריה java.util על ידי:
פרק 2 : תכנות בסיסי 37
import java.util.*;
:System.in על בסיס Scanner �2. ייצור עצ
Scanner sc = new Scanner(System.in);
וכעת נית� לקרוא מהקלט התקני מספרי� שלמי� (על ידי הקריאה ()nextInt) מספרי� ממשיי� (על ידי הקריאה ()nextFloat), מספרי� ממשיי� כפולי� (על ידי קריאה ל ()nextDouble) וכו'.
בתכנית הדוגמא אנו קוראי� שני מספרי� שלמי� כ�:
Scanner sc = new Scanner(System.in);num1 = sc.nextInt();
num2 = sc.nextInt();
:if-else כמשפט �לאחר מכ� מבוצע משפט התנאי לבדיקה ולהדפסת הער� המקסימלי מביניה
System.out.print("|num1 - num2|= ");
if( num1 > num2 )
System.out.print(num1 - num2);
else
System.out.print(num2 - num1);
ביצוע מספר הוראות בלוק א� רוצי� לבצע מספר הוראות בהוראת if או else, יש להקיפ� בסוגריי� מסולסלות, לדוגמא:
if( num1 > num2 ) {
max = num1;
System.out.println(“num1 is greater than num2”);
}
true ,הוא ביטוי לוגי המחזיר ער� מטיפוס בוליאני כלומר num1 > num2 הביטוי −
(אמת) או false (שקר).
− סדרת הוראות מוקפת בסוגריי� {} נקראת בלוק.
Java 38 על כוס קפה
בדומה לאופרטור '<' המציי� את היחס הלוגי "גדול מ ", בטבלה הבאה מובאי� שאר האופרטורי� הלוגיי� ומשמעות�:
x == y y שווה ל x
x != y y שונה מ x
x > y y גדול מ x
x >= y או שווה לו y גדול מ x
x < y y קט� מ x
x <= y או שווה לו y קט� מ x
לולאות לולאה היא אמצעי לביצוע חוזר של פעולות מסוימות מספר פעמי�, או כתלות בתנאי כלשהו. הלולאה מאפשרת חסכו� בכתיבת קוד הכולל חזרות במקו� לכתוב קוד זה מספר פעמי�
כמספר החזרות, הוא נכתב פע� אחת בגו� הלולאה:
לולאה
כל ביצוע של גו� הלולאה נקרא חזרה (איטרציה). הלולאות ב C כוללות אפשרויות בקרה מגוונות כגו�: הפסקת הלולאה, הפסקת החזרה הנוכחית ומעבר לחזרה הבאה. הלולאות
:Java הקיימות ב
while ••••
do-while ••••
for •
• for משופרת (החל מגירסה 5)
פרק 2 : תכנות בסיסי 39
while לולאת
לולאת while משמשת לביצוע חוזר של הוראות כתלות בתנאי מסוי�: תחביר הלולאה הוא
while(ביטוי לוגי) {
הוראות
}
כל עוד ערכו של הביטוי הלוגי אמת ההוראות שבגו� הלולאה מתבצעות. תרשי� זרימה עבור :while ביצוע לולאת
הא� ערכו של הביטוי
הלוגי אמת?
בצע את
ההוראות
המשך להוראה שאחרי
לולאת
while
כן
לא
תכנית הדוגמא הבאה מדפיסה את העצרת של מספר של� n הנקרא מהקלט כלומר מכפלת :while על ידי שימוש בלולאת n 1 עד �המספרי
import java.util.*;
public class Test {
public static void main(String[] args) {
int n;
System.out.print("Enter a number: ");
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
int i=1;
int factorial =1;
while(i<=n) {factorial = factorial * i;i = i+1;
}System.out.print("factorial of " + n + " = " + factorial);
}
}
Java 40 על כוס קפה
הרצה לדוגמא של התכנית:
E n t e r a n u m b e r : 1 0
f a c t o r i a l o f 1 0 = 3 6 2 8 8 0 0
הסבר:
− המספר n נקרא מהקלט על ידי : n = sc.nextInt();
− בשלב הבא מאותחל משתנה הלולאה, i, ל 1: int i=1;
− ג� תוצאת העצרת מאותחלת ל 1 (מדוע?) לפני תחילת הלולאה: int factorial =1;
:n קט� או שווה ל i מבוצעת כל עוד while לולאת ה − while(i<=n) {
factorial = factorial * i;
i = i+1;
}
(facotrial) הלולאה) מוכפלת תוצאת העצרת �בכל איטרציה (=מחזור ביצוע גובמשתנה הלולאה i, הר& על פני הערכי� n..1. בסו� הלולאה i מקוד� ב 1.
ביטויי הצבה וביטויי אריתמטיי מקוצרי נית� לקצר את קוד התכנית הקודמת במספר צורות:
− במקו� factorial = factorial * i;
נית� לכתוב
factorial *= i;
."x והצב את המכפלה ב ,y ב x היא "הכפל את x *= y הסבר: משמעות הסימ�
− במקו� הביטוי i = i+1;
נית� לכתוב בקיצור
i ++;
משמעות הביטוי ++x היא "קד� את x ב 1".
do-while לולאת
לולאת do-while היא בעלת המבנה הבא:
do{
הוראות
פרק 2 : תכנות בסיסי 41
} while (תנאי);
ההוראות שבגו� הלולאה מתבצעות כל עוד התנאי מתקיי�. תרשי� זרימה של הלולאה:
תנאי הלולאה בעל
ערך אמת
?
בצע הוראות
המשך להוראה שאחרי
לולאת
do-while
כן
לא
מה ההבדל שבי� לולאה זו לקודמת (while)? בלולאת while התנאי נבדק לפני ביצוע הלולאה,
ולכ� א� הוא אינו מתקיי� הלולאה לא מבוצעת. בלולאת do-while גו� הלולאה ראשית מתבצע ואח"כ נבדק התנאי, ולכ� מובטח לפחות ביצוע של חזרה אחת.
לדוגמא, את הלולאה לחישוב העצרת בתכנית הנ"ל נית� לרשו� ג� כ�:
do {
factorial = factorial * i;
i = i+1;
} while(i<=n) ;
for לולאת
לולאת for היא לולאה כללית נוחה מאוד לביצוע של הוראות מספר פעמי� או כתלות בתנאי כלשהו. המבנה שלה מסתמ� על הרעיו� שכל לולאה מכילה בדר� כלל שלושה חלקי� : 1) אתחול
2)בדיקת תנאי הלולאה 3) קידו� צעד.
: for תחביר לולאת
for ( <1 ביטוי 3> ; <ביטוי 2> ; <ביטוי>) {
הוראות
}
בתו� הסוגריי� שלאחר המלה for שלושה חלקי�, מופרדי� על ידי התו ";" :
ביטוי 1 הוא אתחול המתבצע לפני תחילת הלולאה.
Java 42 על כוס קפה
ביטוי 2 הוא תנאי הלולאה ביטוי לוגי שכל עוד ערכו אמת הלולאה מתבצעת.
ביטוי 3 הוא קידו הצעד בלולאה.
נית� לתאר את הוראת for על ידי אלגורית� טקסטואלי:
בצע את ביטוי 1
כל עוד ערכו של ביטוי 2 אמת
בצע את גוG הלולאה
בצע את ביטוי 3
כמו כ� נית� לתאר את לולאת for על ידי תרשי� זרימה:
תנאי הלולאה בעל
ערך אמת
?
בצע הוראות
3בצע ביטוי
המשך להוראה שאחרי
לולאת
for
כן
לא
1בצע ביטוי
:for לדוגמא, את התכנית לחישוב העצרת נית� לכתוב כ� על ידי לולאת
import java.util.*;
public class Test {
public static void main(String[] args) {
int n;
System.out.print("Enter a number: ");
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
int factorial=1;
for(int i=1 ; i<=n; i++)factorial = factorial * i;
System.out.print("factorial of " + n + " = " + factorial);
}
}
פרק 2 : תכנות בסיסי 43
כפי שנית� לראות קיבלנו תכנית קצרה יותר ומובנית יותר. בלולאת for שבתכנית ביצענו את הגדרת מונה הלולאה ואיתחולו בביטוי 1 (אתחול הלולאה) על ידי :
for(int i=1 ; i<=n; i++)
ובביטוי 3, מבוצע קידו� ההמשתנה. ביטוי i<=n 2 הוא תנאי הלולאה.
מכיוו� שהלולאה קצרה היא כוללת רק הוראה יחידה, ולכ� אי� צור� בהגדרת בלוק על ידי "}" ו ."}"
מסקנה: הלולאה הנוחה ביותר לכתיבה היא for. לולאת for מכילה בכותרתה את שלושת השלבי� הבסיסיי� בטיפול בלולאה : אתחול, בדיקת תנאי להמש� הביצוע וקידו�/שינוי
משתנה.
for בלולאת �השמטת חלקי בלולאת for אי� חובה להגדיר את כל חלקיה: נית� להשמיט כל אחד משלושת חלקיה או את
כול� ביחד. ע� זאת, חובה עדיי� להפריד בי� החלקי� על ידי התו ";".
• השמטת ביטוי האתחול. במקרה זה האתחול פשוט אינו מבוצע. לדוגמא: for(; num< 5; num++) {
...
}
• השמטת תנאי הלולאה. במקרה זה הלולאה היא אינסופית, לדוגמא: for(i=0; ; i++) { // forever
...
}
• השמטת קידו� הצעד. לדוגמא: for(i=0; i< 1000; ) {
num = sc.nextInt();
i = i + num;
System.out.println("current iteration = "+ i);
}
• השמטת כל שלושת החלקי�. הלולאה היא אינסופית : for(;;) { // forever
...
}
:for דוגמא נוספת ללולאת
for(char c='א'; c<='ת'; c++)
System.out.print(c);
System.out.print('\n');
מודפס:
א ב ג ד ה ו ז ח ט י ך כ ל ם מ ן נ ס ע ף פ ץ צ ק ר ש ת
בדוגמא האחרונה המשתנה c הוגדר בכותרת הלולאה.
Java 44 על כוס קפה
בהגדרת משתנה בביטוי 1 שבלולאת for, בניגוד ל ++C, טווח (Scope) המשתנה ב Java הוא הלולאה בלבד (ב ++C הטווח שלו
הוא טווח הבלוק המכיל את הלולאה).
לולאות כפולות
נית� לבצע לולאה בתו� לולאה אחרת. דוגמא ללולאה כפולה הדפסת לוח הכפל של המספרי� 1 עד 5 :
for(int i=1; i <= 5; i++) {
for(int j=1; j <= 5; j++)
System.out.print(j*i + " ");
System.out.println();
}
פלט התכנית:
1 2 3 4 5
2 4 6 8 1 0
3 6 9 1 2 1 5
4 8 1 2 1 6 2 0
5 1 0 1 5 2 0 2 5
הלולאה החיצונית עוברת על המספרי� 1..5 ע� האינדקס i. בכל חזרה מבוצעת לולאה פנימית העוברת על המספרי� 1..5 ע� האינדקס j, ומדפיסה את מכפלת שני האינדקסי�.
הערה : ההוראה החיצונית מכילה 2 הוראות לכ� יש צור� בסוגריי�, בעוד שבלולאה הפנימית אי� בכ� צור�.
בעיה: הפלט אינו מיושר כהלכה אנו מעונייני� בהדפסה בעמודות מסודרות.
פתרוH: נעשה שימוש ב Formatter השירות ()String.format מאפשר להדפיס ערכי� בצורה מסוגננת:
for(int i=1; i <= 5; i++) {
for(int j=1; j <= 5; j++) {
System.out.printf("%1$4d",i*j);}
System.out.println();
}
והפלט כעת:
פרק 2 : תכנות בסיסי 45
1 2 3 4 5
2 4 6 8 1 0
3 6 9 1 2 1 5
4 8 1 2 1 6 2 0
5 1 0 1 5 2 0 2 5
הסבר: ההוראה
System.out.printf("%1$4d",i*j);
גורמת להדפסת ער� המכפלה i*j, כאשר הוא מוצב בשדה בעל רוחב 4 מקומות.
− המציי� % מתאר תחילת שדה
i*j לארגומנט הראשו� (ובמקרה זה היחיד),הער� �המציי� 1$ מתאר שמתייחסי −
− המציי� 4 מתאר את רוחב השדה
− המציי� d מתאר את טיפוס הארגומנט של� דצימלי במקרה זה
break ו� continue משפטי
כאשר נמצאי� באמצע ביצוע של חזרה בלולאה מסוימת נית� לסיימה בשני אופני�:
1. הוראת continue הפסקת החזרה הנוכחית ומעבר לחזרה הבאה בלולאה. דוגמא :
for (int i=1; i<=n; i++) {
if (i==3)
continue;factorial = factorial * i;
}
א� n=5 אזי יתבצע: 40 = 5 * 4 * 2 * 1
2. הוראת break הפסקה מוחלטת של הלולאה ומעבר לביצוע ההוראה העוקבת ללולאה. דוגמא:
for (int i=1; i<=n; i++) {
if (i==3)
break;factorial = factorial * i;
}
כעת יתבצע: 2 = 2 * 1.
switch-case משפט ההוראה switch משמשת לברירה בי� מספר אפשרויות, כלומר להסתעפות רב כוונית. לדוגמא,
תכנית הקוראת את מספר החודש בשנה ומעוניינת להדפיס את שמו הטסטואלי:
Java 46 על כוס קפה
− מימוש האלגורית� על ידי משפטי תנאי if-else הוא ארו� ומסורבל: int month = sc.nextInt();
if (month == 1) {
System.out.println("January");
}
else if (month == 2) {
System.out.println("February");
} . . .
משפט switch-case הוא תחלי� טבעי וקריא יותר למימוש הסתעפות רב כוונית. תחביר המשפט:
switch( ביטוי ) {
case �הוראות : קבוע של
break;
case �הוראות : קבוע של
break;
case �הוראות : קבוע של
break;
default: הוראות
}
במשפט switch הער� הנבדק מושווה לכל אחד מהערכי� שבכניסות ה case, החל מהראשו�. הכניסה הראשונה שנמצאת נכונה גורמת לביצוע סדרת ההוראות שבאותה כניסה. א� לא
.default כניסה מתאימה, נבחרת הכניסה �נמצאה א
טיפוס הנתו� הנבדק בהוראת case חייב להיות ממשפחת השלמי�, כלומר של� או תו. כאשר
מזוהה כניסה נכונה בהוראת switch הביצוע נמש� ג� לכניסות הבאות עד אשר מזוהה ההוראה
.falling-through תכונה זאת נקראת .break
: switch-case נממש את התכנית על ידי משפט
switch (month) {
case 1: System.out.println("January");
break;
case 2: System.out.println("February");
break;
case 3: System.out.println("March");
break;
case 4: System.out.println("April");
break;
case 5: System.out.println("May");
break;
case 6: System.out.println("June");
break;
case 7: System.out.println("July");
break;
פרק 2 : תכנות בסיסי 47
case 8: System.out.println("August");
break;
case 9: System.out.println("September");
break;
case 10: System.out.println("October");
break;
case 11: System.out.println("November");
break;
case 12: System.out.println("December");
break;
default: System.out.println("This is not a valid month!");
}
כפי שכבר הוסבר, כאשר מזוהה כניסה נכונה בהוראת switch הביצוע נמש� ג� לכניסות הבאות עד אשר מזוהה ההוראה break. לכ�, א� למשל נרצה להדפיס את מספר הימי� שיש בחודש
הנתו�, בהינת� ש month הוא מספר החודש ו year הוא השנה, נבצע:
int month = sc.nextInt(); // read month
int year= sc.nextInt(); // read year
int days;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
days = 31;
break; case 4:
case 6:
case 9:
case 11:
days = 30;
break; case 2:
if ( ((year % 4 == 0) && !(year % 100 == 0))
|| (year % 400 == 0) )
days = 29;
else
days = 28;
break;default: System.out.println("This is not a valid month!");
days=0;
}
System.out.println("Number of Days = " + days);
Java 48 על כוס קפה
(Methods) מתודות מתודות מאפשרות לחלק משימות מורכבות למשימות משנה. כמו כ�, מתודות ה� אמצעי לביצוע
משימות מסויימות באופ� פרמטרי. לדוגמא, נתונה המשימה הבא:
כתוב/י תכנית שתדפיס את כל החזקות החד ספרתיות (המספרי 0..9) של 2 ושל 3 בטבלה.
מטרת המשימה היא להדפיס את הטבלה הבאה:
i p o w e r ( 2 , i ) p o w e r ( 3 , i )
- - - - - - - - - - - - - - - - - - - - -
0 1 1
1 2 3
2 4 9
3 8 2 7
4 1 6 8 1
5 3 2 2 4 3
6 6 4 7 2 9
7 1 2 8 2 1 8 7
8 2 5 6 6 5 6 1
9 5 1 2 1 9 6 8 3
במבט ראשו�, נראה שכדאי לפרק את המשימה על ידי לולאה:
הדפס כותרות לטבלה
בלולאה ע אינדקס i מ� 0 עד 9 בצע:
(res1) i חשב את החזקה של 2 ב�
(res2) i חשב את החזקה של 3 ב�
res2 ו� res1 ,i � הדפס שורה בטבלה
כעת יש לפרק את הוראות הלולאה הדורשות את חישוב החזקה: נבצע זאת על ידי לולאה פנימית העוברת על המספרי� i..1 ומבצעת הכפלה של 2 או 3 כמספר החזרות.
האלגורית� המלא:
משתני: i,j � אינדקסי בלולאות, res1, res2 � משתני לחישוב החזקות
1 ��> res2 ,1 ��> res1:אתחול
הדפס כותרות לטבלה
בלולאה ע אינדקס i מ� 0 עד 9 בצע:
בלולאה ע אינדקס j מ� 1 עד i בצע:
res1*2 ��> res1
בלולאה ע אינדקס j מ� 1 עד i בצע:
res2*3 ��> res2
פרק 2 : תכנות בסיסי 49
res2 ו� res1 ,i � הדפס שורה בטבלה
כפי שנית� לראות, res1 ו res2 מטופלי� באופ� דומה לחישוב החזקה ה i ית של 2 ו 3 בהתאמה. כל אחד מה� מוכפל j פעמי� בבסיס החזקה (2 או 3). בכדי לבצע את חישוב החזקה
נכו� יש לאתחל את res1 ו res2 ל 1.
מה� חסרונות פירוק זה?
− ביצענו פעמיי� פעולה זהה של מציאת חזקה של מספר אחד במספר אחר, ולצור� כ� שכפלנו קוד דומה מאוד לחישוב ע� בסיס ו/או מערי� שוני�.
− במידה ובמקו� אחר בתכנית נצטר� לבצע חישוב נוס� של חזקה, ע� בסיס ומערי� זהי� או שוני�, נצטר� שוב לכתוב לולאה דומה.
הגדרת משימה עצמאית על ידי מתודה
בסעי� זה נראה כיצד נית� לפרק את המשימה הכללית הקודמת למשימות משנה עצמאיות כמתודות. מתודות ניתנות לביצוע בכל שלב של התכנית ופעולת� יכולה להיקבע על ידי פרמטרי. בסיו� החישוב ה� מחזירות את התוצאה. את המשימה של חישוב חזקה נית� להגדיר כמתודה
המקבלת 2 פרמטרי� את הבסיס ואת המערי� ומחשבת את החזקה.
מתודה power לחישוב חזקה:
פרמטרי: base � בסיס החזקה, n � מעריD החזקה
1 ��> result :אתחול
בלולאה ע אינדקס i מ� 1 עד n בצע:
result * base ��> result
result החזר את
כעת נית� להשתמש במתודה שהגדרנו power על ידי ציו� שמה והעברת פרמטרי� מתאימי�. לדוגמא, בכדי לחשב את החזקה של 2 ב 5 נכתוב power(2,5). א� נרצה לקבל את התוצאה
במשתנה res למשל, נכתוב:
power(2,5) ��> res1
: power המשימה הכללית תו� שימוש במתודה שהגדרנו �נגדיר את אלגורית
משתני: i � אינדקס הלולאה, res1, res2 � משתני תוצאות החזקות
הדפס כותרות לטבלה
בלולאה ע אינדקס i מ� 0 עד 9 בצע:
power(2,i) ��> res1
power(3,i) ��> res2
res2 ו� res1 ,i � הדפס שורה בטבלה
Java 50 על כוס קפה
מנגנוH המתודות
כאשר ממתודה מסוימת קוראי� למתודה אחרת מתבצעת הפסקה זמנית בביצוע המתודה הקוראת ועוברי� לביצוע המתודה הנקראת, עד אשר זו מסתיימת. מתודה נקראת יכולה
להמשי� ולקרוא למתודה נוספת ובכ� ליצור שרשרת קריאות.
לדוגמא, נניח שיש לנו תכנית שבה קיימות המתודות ()main .h(), g(), f(), main מבצעת קריאה : h ו g קוראת למתודות f ו f ל
main()
{
f() קריאה ל
}
f()
{
g() קריאה ל
h() קריאה ל
}
g()
{
}
h()
{
}
לאחר שהמתודה הנקראת מסתיימת, חוזר הביצוע למתודה הקוראת, אל ההוראה העוקבת להוראת הקריאה למתודה.
נית� להעביר מידע ביו המתודה הקוראת לנקראת: המתודה הקוראת מעבירה רשימת פרמטרי (או ארגומנטי) למתודה הנקראת לצור� העיבוד. כאשר המתודה הנקראת מסתיימת, היא
מחזירה את תוצאת העיבוד למתודה הקוראת. תוצאה זו היא הערD המוחזר של המתודה.
הגדרת מתודה
המבנה התחבירי של הגדרת מתודה:
} (<הצהרת פרמטרי>) <ש�המתודה> < טיפוס�ער�Dהמוחזר>
<הגדרות טיפוסי, קבועי ומשתני>
<הוראות>
}
הגדרות מתודות יכולות להיות בסדר כלשהו.
כתכנית דוגמא, נממש את האלגורית� שהגדרנו בתחילת סעי� זה, להדפסת החזקות של 2 ו 3. התכנית הכוללת:
public class Functions {
public static int power (int base, int n) {int result=1;
פרק 2 : תכנות בסיסי 51
for (int i=1; i<=n; ++i)
result = result * base;
return result;
}
public static void main(String[] args) {int res1, res2;
System.out.printf("%-4s %-13s %-13s%n", "i", "power(2,i)", "power(3,i)");
System.out.printf("%-4s %-13s %-13s%n", "-", "----------", "----------");
for (int i=0; i<10; ++i) {
res1 = power(2,i);
res2 = power(3,i);
System.out.printf("%-4d %-13d %-13d%n", i, res1, res2);
}
}
}
פלט התכנית:
i p o w e r ( 2 , i ) p o w e r ( 3 , i )
- - - - - - - - - - - - - - - - - - - - -
0 1 1
1 2 3
2 4 9
3 8 2 7
4 1 6 8 1
5 3 2 2 4 3
6 6 4 7 2 9
7 1 2 8 2 1 8 7
8 2 5 6 6 5 6 1
9 5 1 2 1 9 6 8 3
הסבר
power בהגדרת המתודה • public static int power (int base, int n) {
int result=1;
...
}
ציינו ש :
− היא public ו static כמו main כרגע אי� לנו צור� בהבנת מצייני� אלו.
.n ו base : �מטיפוס של �המתודה מקבלת שני פרמטרי −
− המתודה מחזירה ער� מטיפוס של�.
− בתו� המתודה נית� להגדיר משתני� מקומיי� (result) לצור� חישובי ביניי�.
:for המתודה כולל את חישוב החזקה על ידי לולאת �גו − for (int i=1; i<=n; ++i)
result = result * base;
− התוצאה המוצבת במשתנה result מוחזרת בסו� המתודה על ידי ההוראה:
Java 52 על כוס קפה
return result ;
: main בתו� power השימוש במתודה •
− הקריאה למתודה power מתבצעת פעמיי� בכל ביצוע של הלולאה:
res1 = power(2,i);
res2 = power(3,i);בכל קריאה מועברי� 2 פרמטרי� למתודה ומוחזר ער� התוצאה, שמוצב במתודה
הקוראת למשתנה המתאי�.
קריאה ישירה למתודה בהוראת ההדפסה
נכתוב את המתודה הראשית main שוב באופ� מקוצר:
public static void main(String[] args) {
System.out.printf("%-4s %-13s %-13s%n", "i", "power(2,i)", "power(3,i)");
System.out.printf("%-4s %-13s %-13s%n", "-", "----------", "----------");
for (int i=0; i<10; ++i) {
System.out.printf("%-4d %-13d %-13d%n", i, power(2,i), power(3,i));
}
}
הפע� נקראת המתודה power בתו� הוראת ההדפסה, ותוצאתה מועברת ישירות כפרמטר למתודה printf לצור� הדפסה:
System.out.printf("%-4d %-13d %-13d%n", i, power(2,i), power(3,i));
.res1, res2 �אי� צור� בהגדרת המשתני main בגרסה זו של המתודה
הכרזה על הפרמטרי
בקטע ההכרזה על הפרמטרי� נקבע אילו פרמטרי� יועברו למתודה, כלומר מאיזה טיפוס וכמה פרמטרי�. פרמטרי� אלה נקראי� פרמטרי� פורמליי�.
המתודה הקוראת מעבירה למתודה הנקראת פרמטרי� הנקראי� פרמטרי� אקטואליי�. הפרמטרי� הפורמליי� ה� העתק של הפרמטרי� האקטואליי�. ה� מקבלי� את ערכ� בתחילת
ביצוע המתודה:
void main()
{
power (2 , 5);
}
int power ( int base, int n )
{
}
פרמטרים אקטואליים
פרמטרים פורמליים
פרק 2 : תכנות בסיסי 53
המהדר בודק התאמה בי� הפרמטרי� האקטואליי� לפרמטרי� הפורמליי� בקריאה למתודה. א� קיימת אי התאמה הוא ינסה לבצע המרה מרומזת (תו� הודעת אזהרה במידת הצור�)
אחרת הוא יודיע על שגיאה.
לדוגמא, א� מהמתודה ()main ננסה לקרוא למתודה ()power ע� ער� ממשי, נקבל שגיאת הידור:
int i = 3;
double d = 2.0;
int res = power(i,d); // error: trying to convert double to int
בקריאה למתודה power המהדר יגלה אי התאמה בפרמטר השני בי� הטיפוס האקטואלי לבי� הטיפוס הפורמלי: נסיו� להמיר double ל int הוא שגיאה עקב אובד� מידע. לעומת זאת,
הפעולה ההפוכה המרת של� לממשי מותרת, מכיוו� שאי� אובד� של מידע.
ערD מוחזר
הער� המוחזר הוא תוצאת העיבוד במתודה. הטיפוס שלו נקבע בהגדרת כותרת המתודה. בדוגמא הקודמת טיפוס הער� המוחזר של המתודה ()power הוא של� (int), והיא מחזירה את
תוצאת החזקה, המוצבת במתודה הקוראת למשתנה מקומי שלה:
void main()
{
res1 = power (2 ,5);
}
int power ( int base, int n )
{
...
return result;
}
ערD מוחזר
הער� המוחזר מוחזר על ידי ההוראה return. הוראה זו ג� גורמת לסיו� הביצוע של המתודה וחזרה למתודה הקוראת.
במידה ורוצי� להגדיר מתודה שלא מחזירה כלל ער�, מגדירי� את טיפוס הער� המוחזר כ
void. לדוגמא המתודה main בכל התכניות היא מטיפוס void, כלומר לא מחזירה ער� כלשהו.
המרת הערD המוחזר
הער� המוחזר מהמתודה יכול לעבור המרה מרומזת או מפורשת כדי להתאי� את טיפוסו לטיפוס שאליו מציבי� את התוצאה. לדוגמא:
public static float max(float x, float y) {
if(x>y)
return x;
Java 54 על כוס קפה
else
return y;
}
public static void main(String[] args) {
float a=9.4F, b=34.8F;
int i;
i = max(a,b); // error: cannot convert float to int
}
נית�, א� רוצי�, לבצע המרה מפורשת באופ� הבא:
i = (int) max(a,b); // Ok now
משמעות ההמרה המפורשת היא שהמתכנת מודע לפעולת הקיצו& שעלולה להתבצע והוא מוכ� לקבלה. לכ� הפעולה עתה היא חוקית.
main המתודה
main היא מתודה כמו כל מתודה אחרת הנקראת על ידי מכונת Java בתחילת הריצה של
,Functions ,המחלקה שנבחרה בהרצה. לדוגמא, כאשר התכנית האחרונה �, מתו� ש�היישומהודרת ומורצת
javac Functions.java// compile
java Functions // run
המכונה המדומה של Java מתחילה את ריצת היישו� החל מהמתודה ()main הנמצאת במחלקה Functions. א� לא נמצאה מתודה כזו, המוכרזת בדיוק כ�
public static void main(String[] args)
תתקבל הודעת שגיאה.
(Method Overloading) העמסת מתודות
נית� להגדיר במחלקה מספר מתודות בעלות ש� זהה בתנאי שה� מקבלות רשימת פרמטרי� שונה. לדוגמא, נית� להגדיר בתכנית הנ"ל שתי מתודות ()max: אחת המקבלת שני פרמטרי� ומחזירה את המקסימו� מביניה�, והשניה מחזירה את המקסימו� מבי� 3 מספרי� שנתוני� לה
כפרמטרי�:
public class Test {
public static float max(float x, float y) {if(x>y)
return x;
else
return y;
}
public static float max(float x, float y, float z) {return max( max(x,y), z);
פרק 2 : תכנות בסיסי 55
}
public static void main(String[] args) {
float f1=-103.12F , f2=99.9F , f3=113.3F;
System.out.println("max(f1,f2) = " + max(f1,f2));
System.out.println("max(f1,f2,f3) = " + max(f1,f2,f3));
}
}
פלט התכנית :
m a x ( f 1 , f 2 ) = 9 9 . 9
m a x ( f 1 , f 2 , f 3 ) = 1 1 3 . 3
מערכי מערD משמש לאחסו� מספר משתני� מאותו טיפוס בסדרה רצופה בזיכרו�. כל איבר במערD הוא משתנה ללא ש� ההתייחסות אליו היא באמצעות האינדקס שלו, כלומר מיקומו ביחס לתחילת המערD. נית� לקרוא את הער� של כל איבר במער�, לשנות את ערכו, להדפיס אותו, לקלוט לתוכו
ער� מהקלט כלומר נית� לבצע עליו על פעולות כאילו היה משתנה רגיל.
איברי המער� יכולי� להיות מטיפוס בסיסי, כגו�: של�, ממשי, תו. כמו כ� ה� יכולי� להיות מטיפוס מורכב יותר כפי שנראה בהמש�, לדוגמא, טיפוס האיבר יכול להיות מסוג מחרוזת,
.String
תחביר: הגדרת מער� דומה להגדרת משתנה, בתוספת סוגריי� מרובעות כ�:
;[ ] <ש�המערD> <טיפוס�איבר>
או ג� כ�:
; <ש�המערD> [ ] <טיפוס�איבר>
לדוגמא, הגדרת מער� שלמי� :
int integers [] ;
הקצאת איברי המער� מבוצעת על ידי ההוראה new כ�:
int integers [] = new int[5];
כא� ייצרנו את המער� כמער� בגודל של 5 שלמי�.
במער� מגודל n, הערכי� מאוחסני� במער� החל מאינדקס 0 ועד ל n-1. לכ� הגישה לאיברי
המער� integers תהיה על פי התרשי� הבא:
4 3 2 1 0integers[] =
הגישה לאיבר באינדקס i במער� מבוצעת על ידי ש� המער�, בתוספת האינדקס בסוגריי�:
Java 56 על כוס קפה
<Dהמער�ש>[i]
לדוגמא, נציב לאיבר הראשו� (אינדקס 0) ער� 23, ולאיבר האחרו� (אינדקס 4) ער� 11:
integers[0] = 23;
integers[4] = 11;
באופ� דומה, נדפיס את האיבר שבאינדקס 3 (האיבר הרביעי) כ�:
System.out.println("integers[3] = " + integers[3]);
נקד� הער� שבתא האחרו� ב 1:
integers[4]++; // now integers[4] is 12
יש לשי� לב, שבניגוד לשפות ++C/C, ב Java לא נית� להקצות מער� באופ� סטטי על ידי ציו� גדלו זוהי שגיאת קומפילציה:
int int_array[10]; // error!
א� בדומה ל ++C/C נית� להקצותו על ידי אתחול איבריו. דוגמאות:
char char_array[] = {'a', 'ב', 'c'}; // chars array
String str_array[] = {"black", "white", "red", "green"}; // Strings array
נית� להגדיר מער� דו ממדי על ידי שימוש כפול בסימ� "[ ]" כ�:
long array_2D[][] = new long[10][5]; // 2D array of longs
זהו מער� של 10 שורות ו 5 עמודות. למעשה, נית� בצורה זו להגדיר מערכי� רב מימדיי� מכל מימד שהוא.
Dגישה לאיברי המער
פעולות על מערכי� מבוצעות במקרי� רבי� בלולאות. במעבר על איברי המער� בלולאה נוח
להשתמש בתכונה length שלו, לדוגמא:
int [] int_array = new int[10];
for(int i=0; i<int_array.length; i++) {
int_array[i] = i;
}
נית� לייעל את ביצוע הלולאה על ידי קריאת אור� המער� בראשית הלולאה:
int [] int_array = new int[10];
for(int i=0, limit = int_array.length; i< limit; i++) {
int_array[i] = i;
}
כעת, המכונה המדומה (VM) אינה ניגשת לתכונה length בראשית כל איטרציה של הלולאה.
ולהל� דוגמא לביצוע לולאה כפולה על איברי מער� דו ממדי :
long array_2D[][] = new long[10][5]; // 2D array of longs
פרק 2 : תכנות בסיסי 57
for(int i=0; i<array_2D.length; i++) {
for(int j=0; j<array_2D[i].length; j++) {
array_2D[i][j] = i+j;
System.out.print(array_2D[i][j] + "\t");
}
System.out.println();
}
והפלט:
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
5 6 7 8 9
6 7 8 9 1 0
7 8 9 1 0 1 1
8 9 1 0 1 1 1 2
9 1 0 1 1 1 2 1 3
יש לשי� לב לשימוש הכפול שנעשה בתכונה length, פע� כמימד השורות במער� ופע� כמימד העמודות.
Dחריגה מגבולות המער
ב Java, בניגוד ל ++C/C, נבדקות חריגות מגבולות המער� על ידי המכונה הוירטואלית. במידה ויש חריגה כזו, מופעל מנגנו� "זריקת חריגות" (Exceptions) ו"נזרקת" חריגה מתאימה.
לדוגמא, א� הוגדר והוקצה המער� הבא
int [] int_array = new int[10];
נסיו� לכתוב לאיבר באינדקס 10
int_array[10] = 5;
// Runtime exception: ArrayIndexOutOfBoundsException
יגרו� לחריגה כלומר, בזמ� ריצת התכנית מנהל הזכרו� במכונה המדומה יאתר חריגה מגבולות המער�, ויזרוק חריגה מסוג "חריגת אינדקס מגבולות מער�", שתגרו� להפסקת התכנית.
העתקת מערכי
כדי להעתיק מער� בפשטות, נית� לעשות שימוש במתודה arraycopy המוגדרת במחלקה System. לדוגמא:
int [] arr1 = new int[10];
for(int i=0; i< arr1.length; i++) {
arr1[i] = i;
}
int [] arr2 = new int[arr1.length];
Java 58 על כוס קפה
System.arraycopy(arr1, 0, arr2, 0, arr1.length);
הפרמטרי� שמקבלת המתודה arraycopy ה�:
(arr1) מער� המקור �ש −
− אינדקס איבר ראשו� במער� המקור
(arr2) מער� היעד �ש −
− אינדקס איבר ראשו� במער� היעד
− מספר האיברי� להעתקה
לולאת for משופרת (החל מגירסה 5)
לולאת for בעלת תחביר נוח פותחה עבור מערכי� ועבור מחלקות אוס� (שאות� נכיר בפרק 8). היא מהווה תחלי� נוח על פני לולאות for ו while המסורתיות.
כדוגמא, נתבונ� במתודה הבאה, המחשבת את סכו� איברי מער� שלמי� המועבר לה כפרמטר:
int sum(int[] a) {
int result = 0;
for(int i=0; i<a.length; i++)
result += i;
return result;
}
הערה: מתודה המקבלת מער� כפרמטר לא מציינת את גדלו, רק מכריזה עליו.
נית� לרשו� מתודה זו תו� שימוש בלולאת for המשופרת כ�:
int sum(int[] a) {
int result = 0;
for (int i : a)result += i;
return result;
}
תחביר לולאת for המשופרת הוא כלהל�:
for(<type> x : <sequence>)
<use x as the current element>
בכל איטרציה בלולאה, x משמש כמייצג את האלמנט המתאי� בסדרה sequence. זו האחרונה יכולה להיות מער�, או במקרה הכללי מחלקת אוס� כפי שנראה בפרק 11 .
הפרמטרי לתכנית
:main() שבמתודה args כמער� מחרוזות המצויי� על ידי הפרמטר �לתכנית מועברי �הפרמטרי
public static void main (String[] args)
לדוגמא, א� ש� המחלקה הראשית בתכנית הוא Prog, והיא הופעלה משורת הפקודה כ�:
פרק 2 : תכנות בסיסי 59
java Prog hello 23.44 12
אזי args יהיה מער� באור� 3 ויכיל את המחרוזות הבאות כ�:
{ “hello”, “23.44”, “12” }
לדוגמא, התכנית הבאה קוראת את הפרמטרי� המועברי� אליה ומדפיסה אות�:
class Prog {
public static void main (String[] args) {
for(String arg : args)
System.out.println(arg);
}
}
נהדר את התכנית כ�:
javac Prog .java // creates Prog.class
וכעת נרי& אותה, תו� העברת פרמטרי� בשורת הפקודה:
java Prog hello 23.44 12
פלט התכנית:
h e l l o
2 3 . 4 4
1 2
Dמחרוזת כמער
במובני� מסויימי�, מחרוזת ניתנת להפעלה כמעי� סדרה של תווי� כלומר, כמער�. לדוגמא, בהינת� המחרוזת
String abcdef = “abcdef”;
:String של המחלקה �שוני �נית� להפעיל עליה שירותי
• indexOf(ch) מחזירה את האינדקס של תו מסויי� במחרוזת. מוחזר האינדקס של המופע הראשו� של התו שהתגלה בסריקה משמאל לימי�, על בסיס ספירה 0 (בדומה למער�). א� לא
נמצא התו מוחזר הער� 1-.
• substring(i,j) מחזירה תת מחרוזת שמורכב מהתווי� שבאינדקס i על אינדקס j (לא כולל). לדוגמא:
String cd = abcdef.substring(2,4); // cd =“cd”
String b = abcdef.substring(1, 2); // b =“b”
char c = abcdef.charAt(2); // c = “c”
System.out.println(abcdef.indexOf(c)); // print: 2
Java 60 על כוס קפה
סיכו • יישו� בסיסי ב Java כולל מחלקה ראשית המוגדרת כ public והוא יכול לכלול מחלקות
נוספות. המחלקה הראשית חייבת להכיל את המתודה main בעלת הכותרת: public static void main(String args[])
• הטיפוסי� הבסיסיי� ב Java כוללי� ייצוג לשל�, ממשי, לתתי סוגי� שלה� ולתו.
• מחרוזת מיוצגת על ידי מחלקה מובנית ב Java בש� String. מוגדרי� עליה אופרטורי� נוחי� כגו�: הצבה (=), שרשור (+) ובדיקת שוויו� מצביעי� (==). לצור� בדיקת שוויו� של
. equals() שתי מחרוזות יש להשתמש במתודה Hתוכ
• מתודות ה� מנגנו� המאפשר חלוקה של משימה מורכבת למשימות קטנות יותר ועצמאיות. חלוקה של התכנית למתודות מאפשרת פיתוח מודולרי והדרגתי של התכנית.
− אחת המתודות במחלקה הראשית חייבת להיות main זו המתודה שממנה מתחיל ביצוע התכנית.
− המתודה הקוראת מעבירה רשימת פרמטרי (ארגומנטי) למתודה הנקראת. הפרמטרי� המועברי� (פרמטרי� אקטואליי�) משוכפלי� במתודה הנקראת
(פרמטרי� פורמליי�), תו� ביצוע המרה מרומזת או מפורשת במידת הצור�.
− כאשר המתודה הנקראת מסתיימת, היא מעבירה את הערD המוחזר למתודה הקוראת. ג� בקבלת הער� המוחזר תתכ� המרת טיפוס מפורשת או מרומזת.
(new על ידי) בזכרו�. יש להקצות אותו בפירוש �ולא רק סדרת תאי �הוא עצ Java מער� ב • וכ� נית� להשתמש בתכונה length שלו המחזיקה את ארכו.