1 / 97

Java 程序设计系列讲座- 2 面向对象程序设计

Java 程序设计系列讲座- 2 面向对象程序设计. 黄绍辉 厦门大学计算机科学系 E-mail: hsh@xmu.edu.cn. 面向对象程序设计( OOP )基本思想. 对象的基本概念 对象是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。一个对象由 一组属性 和对这组属性进行操作的 一组服务 组成。 对象是问题域或实现域中某些事物的一个抽象,它反映该事物在系统中需要保存的信息和发挥的作用;它是一组属性和有权对这些属性进行操作的一组服务的封装体。 客观世界是由对象和 对象之间的联系组成。. 类的基本概念.

shen
Download Presentation

Java 程序设计系列讲座- 2 面向对象程序设计

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Java程序设计系列讲座-2面向对象程序设计 黄绍辉 厦门大学计算机科学系 E-mail: hsh@xmu.edu.cn

  2. 面向对象程序设计(OOP)基本思想 • 对象的基本概念 • 对象是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。一个对象由一组属性和对这组属性进行操作的一组服务组成。 • 对象是问题域或实现域中某些事物的一个抽象,它反映该事物在系统中需要保存的信息和发挥的作用;它是一组属性和有权对这些属性进行操作的一组服务的封装体。 • 客观世界是由对象和对象之间的联系组成。

  3. 类的基本概念 • 类是具有相同属性和服务的一组对象的集合。分类的原则是抽象。 • 在面向对象的编程语言中,类是一个独立的程序单位,它应该有一个类名并包括属性说明和服务说明两个主要部分。 • 例如图上的三种车,可以做成一个类。具体到某一辆车子,就是一个具体对象。

  4. 面向对象的基本特征 • 封装性 • 把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节。 • 继承性 • 从一个已有的类来构造新类,除了保留原有的类的特性,还增加了一些新特性。已有的类称为父类superclass,新类称为子类subclass。 • 多态性 • 在父类中定义的属性或服务被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为。

  5. 面向对象程序设计的框架 • 用对象的思想来组织程序模块。每一个程序至少有一个对象(class); • 对象与对象之间一般是并列关系,也可以有包含关系; • 对象可以拥有两种东西:属性和服务。属性是一堆的变量,服务是一堆的函数。它们都是对象的成员,所以又叫成员变量、成员函数; • 面向对象的程序设计分两步:一是先独立创建各种对象,好好设计每个对象的属性和服务;二是在main函数中使用各个对象,让对象按照设计的流程发挥各自的作用。

  6. 先来学习怎么使用类 数组专题

  7. 数组 • Java的数组是用纯正OOP的方法设计的,所有专门有一个类,叫Array,用来实现数组的功能。 • 尽管我们刚刚知道,类和对象还是不同的,但是今后我们不太区分这两个词汇;如果要细究,可以自己结合上下文理解。 • 下面我们来学习如果使用人家做好的类,等有感觉了再来做自己的类。

  8. 数组入门-1 • 1 声明一个数组 • 数据类型[] 数组名; • or • 数据类型 数组名[]; • 例如:double[] myList;int a[]; • 2 创建一个数组 • 数组名 = new 数据类型[数组长度]; • 如:myList = new double[10];

  9. 数组入门-2 • 合并前两步,声明并创建一个数组 • 数据类型[] 数组名 = new 数据类型[数组长度]; • or • 数据类型 数组名[] = new 数据类型[数组长度]; • 例如:double[] myList = new double[10];int a[] = new int[10]; • 友情提醒:要使用一个对象,都需要先声明,再创建,然后才能使用,两步缺一不可;当然这两步可以合并,例如上面的例子。 • 声明的作用仅仅是弄出一个空对象(null)。

  10. 数组入门-3 • 数组在创建(new)之后,Java才会为这个数组自动分配空间。(注意声明数组的时候并没有分配数组元素的空间,因为那时候不知道数组多大,所以只是一个空数组,无法容纳任何元素)

  11. 数组入门-4 • 任何一个数组,都可以通过属性length得到数组的长度。如: myList.length • 数组创建的时候会自动赋零值,对于数值型的,就是0或者0.0或者'\0',对于布尔型的,就是false • 任何一个数组,其元素的最小下标是0,最大下标是length-1 • 数组下标越界会引发异常

  12. 数组入门-5 • 数组元素的引用使用[ ],以下两个方法等价,都可以打印出数组myList的每一个元素值: for (int i = 0; i < myList.length; i++) { System.out.print(" "+myList[i]); } 或者(JDK1.5及以上版本才支持的) for (int val : myList) { System.out.print(" "+val); }

  13. 数组入门-6 • 数组在创建的时候可以顺便初始化,如: • double[] myList = {1.9, 2.9, 3.4, 3.5}; • 它相当于: • double[] myList = new double[4]; • myList[0] = 1.9; • myList[1] = 2.9; • myList[2] = 3.4; • myList[3] = 3.5;

  14. 数组例程-1/3 • 用100以内随机数初始化数组 for (int i = 0; i < myList.length; i++) { myList[i] = Math.random() * 100; }

  15. 数组例程-2/3 • 数组求和 double total = 0; for (int i = 0; i < myList.length; i++) { total += myList[i]; }

  16. 数组例程-3/3 • 求数组中的最大值 double max = myList[0]; for (int i = 1; i < myList.length; i++) { if (myList[i] > max) max = myList[i]; }

  17. 复制数组-1 • 假设list1和list2都是数组,执行语句:list2 = list1 • 上述语句并不能将list1全部复制给list2,而是仅仅让list2变成list1的引用。换言之,此时list2和list1表示同一个数组,原先list2数组的元素就全被抛弃在内存的某一处,找不回来了!

  18. 复制数组-2 • 为了复制一个数组到另一个数组,可以自己写一个循环,一个一个复制。例如,有两个数组: int[] sourceArray = {2, 3, 1, 5, 10}; int[] targetArray = new int[sourceArray.length]; • 一个一个搬的例子 for (int i = 0; i < sourceArray.length; i++) { targetArray[i] = sourceArray[i]; }

  19. 总结一下 • 假设Student是一个类,要使用这个类,必须这样: • Student a, b; //先声明 • a = new Student(); b = new Student(); //再创建 • //下面可以随意折腾a和b了,它们是两个对象 • 对象之间不能通过=完成复制,例如在上面代码的基础上,使用a=b,不是把b的内容给a,而是让a和b共享b的对象;原先a的内容就被a抛弃了。

  20. 数组作为函数参数-1 • 对象(包括数组)作为参数,Java采用的是引用传递方式,基本数据类型(int,char等)作为参数,采用值传递方式。 • 简单一点说,引用传递方式,实际参数和形式参数,操作的其实是同一个对象;值传递方式,实际参数和形式参数,仅仅是值相等而已。 • Java中,所有被用作参数的对象,都采用引用方式传递以提高效率(类似于C中的地址传递,因为Java的对象实在太大只了,所有成员都复制一遍不划算,复制对象起始地址就好)

  21. 数组作为函数参数-2 public class Test { public static void main(String[] args) { int x = 1; // x represents an int value int[] y = new int[10]; // y represents an array of int values m(x, y); // Invoke m with arguments x and y System.out.println("x is " + x);// x值不变,还是1 System.out.println("y[0] is " + y[0]);// y[0]值已改变,本来是0的 } public static void m(int number, int[] numbers) { number = 1001; // Assign a new value to number numbers[0] = 5555; // Assign a new value to numbers[0] } }

  22. 数组作为函数参数-3 1 public class TestPassArray { 2 /** Main method */ 3 public static void main(String[] args) { 4 int[] a = {1, 2}; 5 6 // Swap elements using the swap method 7 System.out.println("Before invoking swap"); 8 System.out.println("array is {" + a[0] + ", " + a[1] + "}"); 9 swap(a[0], a[1]);//值传递,返回后不改变原值 10 System.out.println("After invoking swap"); 11 System.out.println("array is {" + a[0] + ", " + a[1] + "}"); 12 13 // Swap elements using the swapFirstTwoInArray method 14 System.out.println("Before invoking swapFirstTwoInArray"); 15 System.out.println("array is {" + a[0] + ", " + a[1] + "}"); 16 swapFirstTwoInArray(a);//引用传递,返回后原值可能改变 17 System.out.println("After invoking swapFirstTwoInArray"); 18 System.out.println("array is {" + a[0] + ", " + a[1] + "}"); 19 }

  23. 数组作为函数参数-4 20//值传递,返回后不改变原值 21 /** Swap two variables */ 22 public static void swap(int n1, int n2) { 23 int temp = n1; 24 n1 = n2; 25 n2 = temp; 26 } 27//引用传递,返回后原值可能改变 28 /** Swap the first two elements in the array */ 29 public static void swapFirstTwoInArray(int[] array) { 30 int temp = array[0]; 31 array[0] = array[1]; 32 array[1] = temp; 33 } 34 }

  24. 再来一个例子 class ClassA { int a = 1; } publicclass Main { staticvoid f1(int a) { a++; } staticvoid f2(ClassA c) { c.a++; } publicstaticvoid main(String[] args) { ClassA c = new ClassA(); System.out.println(“a=”+c.a); //输出a=1 f1(c.a); //基本数据类型做参数,c.a不变 System.out.println("a="+c.a); //输出a=1 f2(c); //引用数据类型做参数,c改变 System.out.println("a="+c.a); //输出a=2 } }

  25. 数组作为函数返回值 • 函数的返回值是通过return带回来的,每次return可以带回一个基本类型的值(char、int等),也可以带回一个对象(例如数组)

  26. 一个例子:计算字符出现的次数 • 解题思路: • 随机生成100个小写字母,放在数组chars中;显然,这个数组的大小应该是100; • 利用counts数组存储字符出现的次数,下标0,1,2,...分别存储'a','b','c',...的次数;显然,这个数组的大小应该是26。 • 生成随机小写字母可以借助于Math.random()

  27. 关键代码-1/5 20 /** Create an array of characters */ 21 public static char[] createArray() { 22 // Declare an array of characters and create it 23 char[] chars = new char[100]; 24 25 // Create lowercase letters randomly and assign 26 // them to the array 27 for (int i = 0; i < chars.length; i++) 28 chars[i] = RandomCharacter.getRandomLowerCaseLetter(); 29 30 // Return the array 31 return chars; 32 }

  28. 关键代码-2/5 34 /** Display the array of characters */ 35 public static void displayArray(char[] chars) { 36 37 for (int i = 0; i < chars.length; i++) { 38 if ((i + 1) % 20 == 0) 39 System.out.println(chars[i] + " "); 40 else 41 System.out.print(chars[i] + " "); 42 } 43 }

  29. 关键代码-3/5 45 /** Count the occurrences of each letter */ 46 public static int[] countLetters(char[] chars) { 47 // Declare and create an array of 26 int 48 int[] counts = new int[26]; 49 50 // For each lowercase letter in the array, count it 51 for (int i = 0; i < chars.length; i++) 52 counts[chars[i] - 'a']++; 53 54 return counts; 55 }

  30. 关键代码-4/5 57 /** Display counts */ 58 public static void displayCounts(int[] counts) { 59 for (int i = 0; i < counts.length; i++) { 60 if ((i + 1) % 10 == 0) 61 System.out.println(counts[i] + " " + (char)(i + 'a')); 62 else 63 System.out.print(counts[i] + " " + (char)(i + 'a') + " "); 64 } 65 }

  31. 关键代码-5/5 3 public static void main(String args[]) { 4 // Declare and create an array 5 char[] chars = createArray(); 6 7 // Display the array 8 System.out.println("The lowercase letters are:"); 9 displayArray(chars); 10 11 // Count the occurrences of each letter 12 int[] counts = countLetters(chars); 13 14 // Display counts 15 System.out.println(); 16 System.out.println("The occurrences of each letter are:"); 17 displayCounts(counts); 18 }

  32. 多维数组-1 • 二维数组的定义 • 数据类型[][] 数组名; • or • 数据类型 数组名[][]; • 例如: • int[][] matrix; • 或 int matrix[][]; • 注意,这里仅仅说明matrix是一个二维数组,但是这个数组目前是null,所以还不能存储元素。

  33. 多维数组-2 • 二维数组有行和列的概念,如:

  34. 多维数组-3 • 二维数组可以在声明的时候赋初值,也可以在new之后再一个一个慢慢赋值。 • 其实二维数组行和行之间是相互独立的,每一行都相当于一个一维数组。

  35. 多维数组-4 • 由于二维数组的每一行是一个一维数组,所以这些一维数组的大小不必相等,如: • 此时: triangleArray.length = 5, //因为数组有5行 triangleArray[0].length = 5, triangleArray[1].length = 4, triangleArray[2].length = 3, triangleArray[3].length = 2, triangleArray[4].length = 1.

  36. 二维数组例程-1 • 随机数填充 for (int row = 0; row < matrix.length; row++) { for (int column = 0; column < matrix[row].length; column++) { matrix[row][column] = (int)(Math.random() * 100); } } • 这里matrix是二维数组。过一遍二维数组必须用两层的循环,一般用i循环行,j循环列;如果英文好一点,可以用row循环行,column或者col循环列。

  37. 二维数组例程-2 • 打印数组元素 for (int row = 0; row < matrix.length; row++) { for (int column = 0; column < matrix[row].length; column++) { System.out.print(matrix[row][column] + " "); } System.out.println(); }

  38. 二维数组例程-3 • 数组求和 int total = 0; for (int row = 0; row < matrix.length; row++) { for (int column = 0; column < matrix[row].length; column++) { total += matrix[row][column]; } }

  39. 一个例子:试卷评分 • 假设让计算机改卷,8张试卷和标准答案如下:

  40. 关键代码 • 学生的试卷存储在answers二维数组中,答案在keys一维数组中,则评分的代码是: 18 // Grade all answers 19 for (int i = 0; i < answers.length ; i++) { 20 // Grade one student 21 int correctCount = 0; 22 for (int j = 0; j < answers[i].length ; j++) { 23 if (answers[i][j] == keys[j]) 24 correctCount++; 25 } 26 27 System.out.println("Student " + i + "'s correct count is " + 28 correctCount); 29 }

  41. 再来学习怎么使用类 字符串专题

  42. 字符串类-1 • 字符串是Java另一个常用类。 • 创建一个字符串(三种方法均可) • String message = new String("Welcome to Java"); • String message = "Welcome to Java"; • char[] charArray = {'G', 'o', 'o', 'd'}; String message = new String(charArray);

  43. 字符串类-2 • 字符串的内容是常量,一旦创建就无法修改。 • String s = "Java"; • s = “HTML”;//友情提醒:这句是对的。但是这不是串复制,只是一个s抛弃了“Java”字符串的故事。 • 以上第2行代码仅仅修改了s的指向,但是没有改动到"Java"这个字符串本身,如图:

  44. 字符串类-3 • 正宗的字符串内容判等函数,是equals,不是==(这个符号相当于比较对象地址是否相等) • String s1 = new String("Welcome to Java"); • String s2 = "Welcome to Java"; • System.out.println("s1 == s2 is " + (s1 == s2)); • System.out.println("s1.equals(s2) is " + (s1.equals(s2))); • 字符串内容比较函数,用compareTo • s1.compareTo(s2),其返回值相当于s1-s2,相等为0

  45. 字符串类-4 • 字符串长度函数length() • String message = new String("Welcome to Java"); • int len = message.length(); • 注意:数组也有长度的概念,但是数组的长度被设计为数组的属性而不是函数。 • int[] arr = new int[5]; • int len = arr.length; • 取字符串的单个字符charAt() • message.charAt(index) 下标范围是0..s.length()–1

  46. 字符串类-5 • 字符串拼接concat()或者+ • String s3 = s1.concat(s2); • 等价于:String s3 = s1 + s2; • 截取子串substring • String message = "Welcome to Java".substring(0, 11) + "HTML"; //相当于从0开始,到11为止的子串(不包括11) • 如果没有提供endIndex,相当于截取到串尾

  47. 字符串类-6 • 字符串转换 • "Welcome". toLowerCase() //返回welcome • "Welcome". toUpperCase() //返回WELCOME • " Welcome". trim() //返回Welcome • "Welcome". replace('e', 'A') //返回WAlcomA • "Welcome". replaceFirst("e", "A") //返回WAlcome • "Welcome". replaceAll("e", "A") //返回WAlcomA

  48. 字符串类-7 • 查找指定的字符或者子串 • indexOf(char ch) //查找指定字符,返回下标 • lastIndexOf(char ch) //同上,但是逆向查找 • indexOf(int ch, int fromIndex) 从下标fromIndex开始查找指定字符 • lastIndexOf(int ch, int endIndex) 同上,但是从下标endIndex开始逆向查找 • 以上函数都有字符串版本,把参数换成String就可以了。如果查找失败,返回值都是-1。因为这是个无效的下标。

  49. 字符串类-8 • "Welcome to Java".indexOf('W') returns 0. • "Welcome to Java".indexOf('o') returns 4. • "Welcome to Java".indexOf('o', 5) returns 9. • "Welcome to Java".indexOf("come") returns 3. • "Welcome to Java".indexOf("Java", 5) returns 11. • "Welcome to Java".indexOf("java", 5) returns -1. • "Welcome to Java".lastIndexOf('W') returns 0. • "Welcome to Java".lastIndexOf('o') returns 9. • "Welcome to Java".lastIndexOf('o', 5) returns 4. • "Welcome to Java".lastIndexOf("come") returns 3. • "Welcome to Java".lastIndexOf("Java", 5) returns -1. • "Welcome to Java".lastIndexOf("java", 5) returns -1.

  50. 字符串类-9 • 字符串分拆到字符数组toCharArray • char[] chars = "Java".toCharArray(); • 用字符串的子串去填充数组getChars • char[] dst = {'J', 'A', 'V', 'A', '1', '3', '0', '1'}; • "CS3720".getChars(2, 6, dst, 4); • 头两个参数取子串,后面是填充目标数组和起始位置 • 字符数组拼成字符串String或valueOf • String str = new String(new char[]{'J', 'a', 'v', 'a'}); • String str = String.valueOf(new char[]{'J', 'a', 'v', 'a'});

More Related