310 likes | 430 Views
计算器与工程问题解析导论. 第七课 方法 字符串 建构子 this 继承. Java 的方法. 方法是类别间的接口或沟通 提供你的程序可从许多地方来唤起相同的的操作以避免重复的程序代码 对方法的使用者或呼叫者隐藏了执行时的细节 方法中定义的变量对方法的呼叫者而言是不可视的;他们 ( 译者按:方法内的变量 ) 在方法内有局限性的范围 (local scope) 方法同样也看不见在呼叫者的中的变量。两者 ( 译者按:方法与其呼叫者的变量 ) 间有逻辑上的分隔,在于避免变量名称的冲突。. 唤起方法. public class Power1 {
E N D
计算器与工程问题解析导论 第七课 方法 字符串 建构子 this 继承
Java 的方法 • 方法是类别间的接口或沟通 • 提供你的程序可从许多地方来唤起相同的的操作以避免重复的程序代码 • 对方法的使用者或呼叫者隐藏了执行时的细节 • 方法中定义的变量对方法的呼叫者而言是不可视的;他们(译者按:方法内的变量)在方法内有局限性的范围(local scope) • 方法同样也看不见在呼叫者的中的变量。两者(译者按:方法与其呼叫者的变量)间有逻辑上的分隔,在于避免变量名称的冲突。
唤起方法 • public class Power1 { • public static void main(String[] args) { • double a= 10.0, b; • int x= 3; • System.out.println("Main: a= " + a + ", x= " + x); • b= power(a, x); • System.out.println("Main: Result b= " + b); • } • public static double power(double d, int i){ • System.out.println("Power: d= " + d + ", i= " +i); • double x= d; // 这个 x 是不同于 main方法中的 x • for (int j= 1;j < i; j++) • x *= d; // x = x* d; • return x; } • }
传递自变量 只透过自变量沟通, 并传回值 以位置来确认自变量 自变量2 自变量1 传值 假设方法是先被撰写完成的:也就是并不知道main()方法的变量。 //方法暗自复制了 d 和 i
传值呼叫 • Java 在传递自变量到方法时仅支持「传值呼叫」: • 方法会复制每一个自变量 • 然后使用复制的自变量进行运算 • 方法无法改变呼叫它自身的自变量值(变量)
传值呼叫 • 方法只能传回讯息给呼叫者 • 透过回传的值,以及 • 改变传给方法的对象中的数据(稍后会介绍更多) • 回传的值可以是空的,意即没有东西回传。方法main()就回传空的值。 • 另外的机制,像其它语言及C++所支持的,称为传参考地址呼叫,它允许方法改变自变量。
传值呼叫的范例 • public class CallByValue { • public static void main(String[] args) { • int i= 3; • double d= 77.0; • System.out.println("Main 1: i= " + i + ", d= " + d); • triple(i, d); // 没有回传值 • System.out.println("Main 2: i= " + i + ", d= " + d); • // 范例的第二部份: 改变自变量 • triple(i, i); // 好 - Java 转换整数为双精度 • System.out.println("Main 3: i= " + i); • } • public static void triple(int ii, double dd) { • System.out.println(“Triple 1: ii= " +ii+ ", dd= " +dd); • ii *= 3; // ii= ii*3; • dd *= 3.0; • System.out.println(“Triple 2: ii= " +ii+ ", dd= " +dd); • } • }
跟随对象的传值呼叫 • public class CallObjExample { • public static void main(String[] args) { • Demo d= new Demo(3); • int i= 3; • System.out.println("Main1: i= " + i + ", d.a= " + d.a); • triple(i, d); // 无回传值 • System.out.println("Main2: i= " + i + ", d.a= " + d.a); • } • public static void triple(int ii, Demo dd){ • System.out.println("T1: ii= "+ ii + ", dd.a= " + dd.a); • ii *= 3; // ii= ii*3; • dd.a *= 3; • System.out.println("T2: ii= "+ ii + ", dd.a= " + dd.a); • } • }
跟随对象的传值呼叫 class Demo { // 设定为public只为表示传值呼叫 public int a; public Demo(int aa) { a= aa; } }
方法的用法 • 方法的自变量的名录(list)与名称就称为方法的「用法」 • 在类别中,只要有不同的「用法」,方法可以有相同的名称。 • 在类别中,所有相同名称的方法一定会有相同的回传型态。
方法的覆载 • 使用相同的方法但是有不同的「用法」就称为「方法覆载」。 • Java是根据在方法中所引用的自变量数目、型态及顺序来决定哪一个被覆载方法的版本。 • Java会「提升」数字数据型态来「向上」符合用法。
字符串类别 • 是Java系统的一部份 • 字符串类别有特别的连续运算子 • 字符串允许常数的初值,例如 String teststring = “Hello”; String 在建立后就不可修改 – 「永远不变的」
字符串 • public class StringExample { • public static void main(String[] args) { • String first= "George "; • String middle= "H.W. "; • String last= "Bush"; • String full= first + middle + last; • System.out.println(full); • // 测试字符串的相等 (一般的对象) • String full2= "George H.W. Bush"; • if (full.equals(full2)) // 正确的表示 • System.out.println("Strings equal"); • if (full == full2) // 错误的表示 • System.out.println("A miracle!"); • if (first == “George ”) //错误的表示,但是可以作用 System.out.println("Not a miracle!");
字符串 • // 修改字符串一定要用间接的方式才能完成 • // 字符串是常数 • middle = middle.substring(0, 2) + " "; • full= first + middle + last; • System.out.println(full);} • }
「this」 – 对象如何自我参考 • 对象可以被称为参考的变量来存取。 • 假定在对象中撰写程序代码,我们要参考回来这个对象。 • 例如:假定我们要传递一个参考到「自己」就像另一个对象的方法的自变量一样
this • “this”也可当成是对这个类别而言参考到其它的建构子的简述
建构子中的 this • public class SimplePoint { • private double x, y; // 资料成员 • public SimplePoint() { // 建构子 • x= 0.0; • y= 0.0; } • public SimplePoint(int x, int y) { • this.x = x; • this.y = y; } • // 方法 • public double getX() { return x;} • public double getY() { return y;} • public void setX(double xval) { x= xval;} • public void setY(double yval) { y= yval;} • public void move(double deltaX, double deltaY) { • x += deltaX; • y += deltaY; } • } // 类别 SimplePoint 结束
弹簧 压力作用 张力作用 扭力作用 力 = 弹性系数 * 变位
类别弹簧的建构子 • class Spring { • private String material= “steel”; // 初始化 private double length; // 只考虑压缩 private double maxDeflect; • private double k; • public Spring(String m, double len, double md, double k) { • material= m; • length= len; • maxDeflect= md; • this.k= k; // “this” • } • public Spring(double len, double k) { • this("steel", len, 0.25*len, k); // “this” • } • public Spring(double len) { • this(len, 0.5*len); • } • public Spring() { • this(10.0); }
类别弹簧的方法 public String getMaterial() { return material; } public double getLength() { return length; } public double getMaxDef() { return maxDeflect; } public double getK() { return k; } // 不需要 ‘this’ public void setMaterial(String m) {material= m; } public void setLength(double len) {length= Math.abs(len);} public void setMaxDef(double m) {maxDeflect= Math.abs(m);} public void setK(double k) {this.k= k; } // this public double getForce(double deflection) { if (deflect > maxDeflect) deflect= maxDeflect; return k*deflect; } public double getForce() { // 覆载方法 return k*maxDeflect; } }
弹簧的 main() 方法 • public class SpringExample { • public static void main(String[] args) { • Spring one= new Spring("aluminum", 2.0, 1.0, 5.0); • Spring two= new Spring(5.0, 3.0); • Spring three= new Spring(); // 3 个不同的建构子 • double f1= one.getForce(0.5); • double f2= two.getForce(1.5); • double f3= three.getForce(0.1); • System.out.println("f1: " + f1 + "\nf2: " + f2 + • "\nf3: " + f3); • double f4= one.getForce(); // 超载的方法 • double f5= two.getForce(); • double f6= three.getForce(); • System.out.println("f4: " + f4 + "\nf5: " + f5 + • "\nf6: " + f6); • System.exit(0); • } • }
弹簧类别的设计 • 弹簧所有的方法均为公用的 • 任何类别的方法均可呼叫这些方法 • 私用方法可以被使用,但只有这个类别自己可以用来当作帮手或手法 • 弹簧中的数据域位是私用的 • 只有弹簧的方法可以使用它们 • 公用数据字段几乎不可被使用 • 建构子的名称必须与类别名称一致 • 建构子只能用「new」来呼叫 • 建构子不能回传值
弹簧类别的方法 • 为何有这些方法? • 因为方法 Get 只能从其它类别中使用到弹簧的数据 • 如果需要的话,可以让我们重新执行弹簧 • 方法 Set 应该要检查错误 • 我们的方法应该确认:长度要大于0, 最大的变形要小于长度等等。 • 覆载方法时必须有不同的使用(自变量) • 不同的回传型态并不能分辨两个一样的分法 • int getForce(int a) 与 • double getForce(int b) 将无法编译
物件的解构 • 当没有主动的参考到对象时,Java会自动地利用「垃圾收集」将对象所占的内存收回 • C++则需要程序人员以手动方式来做。在C++中你会谨慎地使用「new」是因为必须在使用完后使用「delete」来避免「内存漏失」 • 当对象被销毁时,Java有终结器来清除其它的资源(档案、锁定的设备等) • 非正式的忠告:千万不要使用终结器 • 终结器会唤起任何对象导致垃圾收集器效率低落
梁的练习 撰写一个 Java类别来建构梁的模型以及计算它的最大桡度: w=-PL3/3EI 其中 P=端点载重(1200N) L=梁长(20m) E=弹性模数(30000N/m2) I=惯性力矩(1000m4) w=桡度(m)
梁的练习(续) • 数据域位: • 哪些是梁的特性? • 哪些是外在的? • 撰写两个建构子 • 一个以所有的字段当自变量 • 自变量与字段使用相同的名称 • 一个只用长度为自变量 • 其它的字段用前述的数值做为默认值 • 使用”this”来唤起其它建构子或依赖起始程序 • 在类别中使用起始程序:假定你正在处理许多像范例的梁 • 撰写两种方法来回传桡度值w • 两种都使用相同方法的名称(覆载) • 以个以载重为自变量,第二个将载重与单位(英呎或公尺)当做字符串;转换时1m=3.3ft • 不要撰写任何的get或set方法 • 撰写一个含有main()的类别来建立梁,并计算梁的桡度并打印结果
梁的练习(续) • 选择性的,进阶的: • 加入尺寸分析: • 储存类别中每个变量的单位 • 决定你会如何将它们编码(指数…等等) • 修改建构子接受单位自变量 • 如所需要转换单位(N-lf, m-ft) • 1lbf=4.4N, 1ft=o.3m • 确认在计算中单位相符 • 输出单位时要加上方法结果
梁的类别 • class Beam { • private double L; • private double E= 30000.0; // 初始程序 • private double I= 1000.0; • public Beam(double L, double E, double I) { • this.L= L; // this 来存取资料 • this.E= E; • this.I= I; • } • public Beam(double L) { • this.L= L; // 其它的靠起始程序 • } // 可以使用 this(L, 30000., 1000.); • public double getDeflection(double P) { • return -P*L*L*L/(3.0*E*I);} • public double getDeflection(double P, String u) { • if (u.equals("ft")) // not == • return -3.3*P*L*L*L/(3.0*E*I); • else return -P*L*L*L/(3.0*E*I); • } • }