语句块 (也叫复合语句) 。
语句块中定义的变量只能用于自己,外部不能使用。
//(即语句块可以使用外部的变量,而外部不能使用语句块的变量)public class Test19 { public static void main(String[ ] args) { int n; int a; { int k; int n;//编译错误: 不能重复定义变量 n } //变量 k 的作用域到此为止 }}
方法方法(method):一段用来完成特定功能的代码片段, 类似于其它语言的函数(function)。
方法的重载(overload)方法用于定义该类或该类的实例的行为特征和功能实现。
面向过程中, 函数是最基本单位, 整个程序由一个个函数调用组成。面向对象中, 整个程序的基本单位是类, 方法是从属于类和对象的。
重载: 一个类中可以定义多个名称相同, 但形式参数列表不同的方法。(重载的方法实际是完全不同的方法,只是名称相同而已)
构成方法重载的条件:
形参列表不同的含义: 形参类型、形参个数、形参顺序不同只有返回值不同不构成方法的重载 如: int a(String str){}与 void a(String str){}不构成方法重载只有形参的名称不同, 不构成方法的重载 如: int a(String str){}与 int a(String s){}不构成方法重载
【示例】方法重载
public class Test21 { public static void main(String[ ] args) { System.out.println(add(3, 5));// 8 System.out.println(add(3, 5, 10));// 18 System.out.println(add(3.0, 5));// 8.0 System.out.println(add(3, 5.0));// 8.0// 我们已经见过的方法的重载 System.out.println();// 0 个参数 System.out.println(1);// 参数是 1 个 int System.out.println(3.0);// 参数是 1 个 double } public static int add(int n1, int n2) { int sum = n1 + n2; return sum; } // 方法名相同, 参数个数不同, 构成重载 public static int add(int n1, int n2, int n3) { int sum = n1 + n2 + n3; return sum; } // 方法名相同, 参数类型不同, 构成重载 public static double add(double n1, int n2) { double sum = n1 + n2; return sum; }// 方法名相同, 参数顺序不同, 构成重载public static double add(int n1, double n2) { double sum = n1 + n2; return sum;} //编译错误: 只有返回值不同, 不构成方法的重载 public static double add(int n1, int n2) { double sum = n1 + n2; return sum; } //编译错误: 只有参数名称不同, 不构成方法的重载 public static int add(int n2, int n1) { double sum = n1 + n2; return sum; }}
practice:
定义一个方法处理公司的迟到问题:
(1) 输入: 迟到时间, 月薪。
(2) 处理逻辑:
1 迟到 1-10 分钟, 警告。
2 迟到 11-20 分钟, 罚款 100 元。
3 迟到 21 分钟-30 分钟, 罚款 200 元。
4 迟到 30 分钟以上, 扣除半日工资。
5 迟到 1 小时以上, 按照旷工计算, 扣除 3 日工资。
(3) 输出: 罚款金额
public class TestMethod2 { public static int late(int lateMinute,double salary){ int fakuan = 0; //罚款 if(lateMinute<11){ System.out.println("警告! !不能迟到!!"); }else if(lateMinute<21){ fakuan = 100; }else if(lateMinute<31){ fakuan = 200; }else if(lateMinute<61){ fakuan = (int)(salary/(21.75*2)); //21.75 指的是:月平均工作日 }else{ fakuan = (int)(salary*3/(21.75)); } System.out.println("迟到时间:"+lateMinute+",罚款: "+fakuan); return fakuan; } public static void main(String[] args) { late(45,42000); }}
递归结构递归的基本思想就是“自己调用自己”。像深度优先搜索 ( DFS:Depth First Search) 等很多算法里都有用到。
递归结构包括两个部分:
口 定义递归头。 解决: 什么时候不调用自身方法。如果没有头, 将陷入死循环, 也就 是递归的结束条件。
口 递归体。 解决: 什么时候需要调用自身方法。
【示例】使用递归求 n!
public class Test22 { public static void main(String[ ] args) { long d1 = System.curentTimeMilis(); factorial(10); long d2 = System.curentTimeMilis(); System.out.printf("递归费时:" +(d2-d1)); //耗时: 32ms } static long factorial(int n){ if(n==1){//递归头 return 1; }else{//递归体 return n*factorial(n-1);//n! = n * (n-1)! } }}
【示例】使用循环求 n!
public class Test23 { public static void main(String[ ] args) { long d3 = System.curentTimeMilis(); int a = 10; int result = 1; while (a > 1) { result *= a * (a - 1); a -= 2; } long d4 = System.curentTimeMilis(); System.out.println(result); System.out.printf("普通循环费时: " + (d4 - d3)); }}
面向对象编程(Object Oriented Programing) 表格结构和类结构递归的缺陷
算法简单是递归的优点之一。
但是递归调用会占用大量的系统堆栈,内存耗用多,在递归调用层次多时速度要比循环慢的多,所以在使用递归时要慎重。
上面示例中递归和循环的运行结果对比
雇员类和雇员表的结构完全一样。只不过,雇员类增加了数据的类型而已。
在面向对象编程中,下面三句话记住:
表结构对应:类结构一行数据对应:一个对象表中所有数据对应:这个类的所有对象
//下面的四行数据,我们使用四个对象就需要这样表示(假设有对应的构造方法, 如下代码是示意,非真实代码):emp1 = new Employee(ID:1001, name:"高小一", job:"程序员", baseSalary:20000, salary2:0, hiredate:"9 月 1 日", address:"北京"); emp2 = new Employee(ID:1002, name:"高小二", job:"前台", baseSalary:5000, salary2:0, hiredate:"9 月 2 日", address:"北京"); emp3 = new Employee(ID:1003, name:"高小三", job:"销售员", baseSalary:3000, salary2:15000, hiredate:"9 月 1 日", address:"郑 州");emp4 = new Employee(ID:1004, name:"高小四", job:"财务", baseSalary:5000, salary2:0, hiredate:"9 月 2 日", address:"上海");
面向过程和面向对象思想 面向过程适合简单、不需要协作的事务,重点关注如何执行。
面向对象可以帮助我们从宏观上把握、从整体上分析整个系统。【面向对象(Oriented-Object)思想更契合人的思维模式。我们首先思考的是“怎么设计这个事物?”但具体到实现部分的微观操作(就是一个个方法),仍然需要面向过程的思路去处理。】
面向对象是“设计者思维”·面向对象和面向过程思想的总结
都是解决问题的思维方式,都是代码组织的方式。
面向过程是一种“执行者思维”,解决简单问题可以使用面向过程。
面向对象是一种“设计者思维”,解决复杂、需要协作的问题可以使用面向对象。
面向对象离不开面向过程:
宏观上:通过面向对象进行整体设计
微观上:执行和处理数据,仍然是面向过程。
面向对象是一种“设计者思维”。
设计时,先从问题中找名词,然后确立这些名词哪些可以作为类,再根据问题需求确定的类的属性和方法,确定类之间的关系。
先从场景中找出名词,以使用表格来表示。
分析完上面这些 Object 后,我们需要进行组合。把这些 Object 融合到一个场景。
写小说本质上和设计软件是一样的,根据想要表达的内容,设计不同的场景、设计不同 的任务。
设计完成后,作者再按照一章一章的完成写作(执行阶段)。
以短篇小说《茶馆》为例,简单分析“面向对象设计方式写小说”的过程
明确小说主要内容和目标
人物设计分析
整体事件设计
-对象和类的详解总结
对象说白了也是一种数据结构(对数据的管理模式),将数据和数据的行为放到了一起。
在内存上,对象就是一个内存块,存放了相关的数据集合!
对象的本质就一种数据的组织方式!
类:class。
对象:Object,instance(实例)。(以后我们说某个类的对象,某个类的实例,是一样的意思)
类的定义 类可以看成一类对象的模板,对象可以看成该类的一个具体实例。
类是用于描述同一类型的对象的一个抽象概念,类中定义了这一类对象所应具有的共同的属性、方法。
【示例】类的定义方式
// 每一个源文件必须有且只有一个public class,并且类名和文件名保持一致!public class Car { }class Tyre { // 一个Java文件可以同时定义多个class }class Engine {}class Seat { }
对于一个类来说,有三种成员:属性 field、方法 method、构造器 constructor。
属性用于定义该类或该类对象包含的数据或者说静态特征。属性作用范围是整个类体。 在定义成员变量时可以对其初始化,如果不对其初始化,Java 使用默认的值对其初始化。
属性定义格式:
[修饰符] 属性类型 属性名 = [默认值] ;
-方法方法用于定义该类或该类实例的行为特征和功能实现。方法是类和对象行为特征的抽象。面向对象中,整个程序的基本单位是类,方法是从属于类和对象的。
[修饰符] 方法返回值类型 方法名(形参列表) { // n 条语句}
【示例】编写简单的学生类
public class SxtStu { //属性(成员变量) int id; String sname; int age; //方法 void study(){ System.out.println("我正在学习!"); }//构造方法 SxtStu(){ } }
简单内存分析(帮助理解面向对象) -构造方法(构造器 constructor) 构造器用于对象的初始化,而不是创建对象【构造方法是负责初始化(装修),不是建房子】
声明格式:
[修饰符] 类名(形参列表){//n 条语句 }
构造器 4 个要点:
构造器通过 new 关键字调用!!
构造器虽然有返回值,但是不能定义返回值类型(返回值的类型肯定是本类),不能在构造器里使用return 返回某个值。
如果我们没有定义构造器,则编译器会自动定义一个无参的构造方法。如果已定义 则编译器不会自动添加!
构造器的方法名必须和类名一致!
practice:
定义一个“点”(Point)类用来表示二维空间中的点(有两个坐标)。要求如下:
可以生成具有特定坐标的点对象。
提供可以计算该“点”距另外一点距离的方法
class Point { double x, y; public Point(double _x, double _y) { x = _x; y = _y; } public double getDistance(Point p) { return Math.sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y)); } public static void main(String[ ] args) { Point p1 = new Point(3.0, 4.0); Point origin = new Point(0.0, 0.0); System.out.println(p1.getDistance(origin)); } }
构造方法的重载 构造方法也是方法。与普通方法一样,构造方法也可以重载
【示例 】构造方法重载(创建不同用户对象)
public class User { int id; // id String name; // 账户名 String pwd; // 密码 public User() { } public User(int id, String name) {//如果方法构造中形参名与属性名相同时,需要使用 this 关键字区分属性与形参。 this.id 表示属性 id;id 表示形参 id this.id = id; this.name = name; } public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } public static void main(String[ ] args) { User u1 = new User(); User u2 = new User(101, "大嗲嗲"); User u3 = new User(100, "小嗲嗲", "123456"); }}