一、对象是对问题领域中事物的抽象,对象具有以下特性:
1. 万事皆为对象。问题领域中的实体和概念都可以抽象为对象。例如:在学校领域,对象包括学生、成绩单、教师、课程,教室等。在太阳系领域,对象包括太阳、月亮、地球、火星和木星等。在用java语言创建的图形用户界面中,窗口、滚动面板、按钮、列表、菜单和文本框等也都是对象。
2. 每个对象都是唯一的。对象的唯一性来自于真实世界中事物的唯一性。世上不存在两片一模一样的叶子。例如:学校领域的学生小张,学生小王,这些都是唯一的对象。在java虚拟机提供的运行时环境中,保证每个对象的唯一性的手段是为它在内存中分配唯一的地址。
3. 对象具有属性和行为。例如:一部手机:牌子是摩托罗拉,价格是2000元,黑色,能够拍照,打电话和收短信等。这部手机的属性包括品牌类型(type),价格(price)和颜色(color),行为包括拍照(takePhoto()),打电话(call()),收短信(receiveMessage())和发短信(sendMessage())。对象的行为包括具有的功能及具体的实现。
4. 对象具有状态。状态是指某个瞬间对象的各个属性的取值。
5. 对象都属于某个类。每个对象都是某个类的实例。如:中国和美国都属于国家类,中文和英文都属于语言类。类是具有属性和行为的对象的集合。
同一个类的所有实例具有相同属性,但是属性的取值不一定相同。
二、类是一组具有相同属性和行为的对象的抽象。即是同类型对象的定义书,规范。
三、使用class定义类
在面向对象设计中,对象并不会凭空产生,你必须识别出问题中的对象,在java中,用“类”来定义出对象的规范,再根据类来构建出一个个的对象,然后通过对象所提供的方法来与程序互动。
四、对象提供的服务是由对象的方法来实现的,因此发送消息实际上就是调用一个对象的方法。
五、封装:对于OOP(面向对象编程)而言就是将属性和方法一起包装到一个程序单元中,并隐藏方法的实现过程。
六、抽象:是指从特定角度出发,从已经存在的一些事物中抽取我们所关注的特性,形成一个新的事物的过程。
抽象是一种由具体到抽象、由复杂到简洁的思维方式。在面向对象的开发过程中,抽象体现在以下几个方面:
1. 从问题领域的事物到软件模型中对象的抽象。
2. 从对象到类的抽象。
3. 从子类到父类的抽象。如下图:
七、封装一个类,就是根据具体的应用从同一类型对象中抽象出相关的属性和方法:
1.定义类的语法:
[访问修饰符] class 类名 {
//这里放属性和方法的声明。
}
2.声明属性的语法:
[访问修饰符] 数据类型 属性名[=初始值];
3.定义方法的语法:
[访问修饰符] 返回值类型 方法名(参数类型 参数名1,…){
//这里放方法的具体实现语句
}
例:
public class CellPhone {
private String type; private String color; private double price;
public void takePhoto(){ ... } public void call(){ ... } public void sendMessage(){ ... } public void receiveMessage(){ ... }
} |
八、构造方法
1.怎么根据设计好的类来创建一个对象?
利用new关键词调用类的构造方法(类的一种特殊方法)就可创建该类的一个对象。
2.构造方法的名字和类名相同,并且没有返回值。
3.构造方法的作用在于构造并初始化对象。
4.两种构造方法
(1).参数化构造方法:
访问修饰符 类名(参数类型 参数名,…){
...
}
如上例可写:
public CellPhone(String t, String c, double p){ type = t; color = c; price = p; } |
(2).默认(隐式)构造方法:即无参数的构造方法。
Public CellPhone(){ …… } |
5.注意:如果类中有一个自己编写的构造方法时,编译器就不会为我们再提供那个默认构造方法。此时又希望使用你的类的用户还可以用默认构造方法来创建类的实例时,那你就必须在类中添加一个默认构造方法。
九、关于源文件:一个源文件中可以定义多个类,但只能有一个公有类,且文件名必须跟公有类的类名相同。
十、this关键词
1.每个类的每个非静态方法(没有被static修饰)都会隐含一个this引用名称,它指向调用这个方法的对象。
2.当在方法中使用本类的属性时,都会隐含地使用this名称,当然也可以明确指定。
3.this用法一:当类中某个非静态方法的参数名(或局部变量名)跟类的某个属性(成员变量)名相同时,为了避免参数的作用范围覆盖了类属性的作用范围,必须明确地使用this名称来指定。如:
public CellPhone(String type, String color, double price){ this.type = type; this.color = color; this.price = price; } |
5.this用法二:如果某个构造方法的第一条语句具有形式this(...),那么这个构造方法将调用同一类中的其他构造方法。
十一、理解调用一个构造方法创建一个对象的执行过程:
1.初始化所有属性为默认值(0,0.0,false或null)。
2.按照在类声明中出现的次序依次执行所有属性的初始化语句和初始化块。
3.如果构造方法的第一行代码调用了另一个构造方法,则执行被调用的构造方法主体。
4.执行本构造方法的主体。
十二、包:为了便于管理大型软件系统中数目众多的类,解决类命名冲突的问题,Java引入了包(package)。
1.在使用许多类时,类和方法的名称很难决定。有时需要使用与其他类相同的名称。包基本上隐藏了类并避免了名称上的冲突。
2.用package来声明包,package语句必须是文件中的第一条语句。
3.包对应着文件系统的目录层次结构。
4.在package语句中,用“.”来指明包(目录)的层次。
5.在当前目录下生成包
javac -d . CellPhone.java
在指定目录下生成包
javac -d E:/JavaLesson CellPhone.java
6.运行时:
java 包名.类名
7.用import来导入你想用的包中的类。
十三、继承:是复用代码的有力手段,当多个类之间存在相同的属性和方法时,可从这些类中抽象出父类(超类)。在父类中定义这些相同的属性和方法,所有子类无须重新定义这些属性和方法,而只要通过extends语句来声明继承父类。这样子类就自动拥有在父类中定义的属性和方法了。
1.继承的优点
(1).代码的可重用性
(2).超类的属性和方法可用于子类
(3).设计应用程序变得更加简单
(4).可以轻松地自定义子类
class Employee{ private String name; //姓名 private int age; //年龄 private boolean sex; //性别 private String department; //部门 private double salary; //薪水
public Employee(String name, int age, boolean sex, String department,double salary){ this.name = name; this.age = age; this.sex = sex; this.department = department; this.salary = salary; }
public Employee(){}
//计算个人所得税 public double getTax(){ if(salary < 1600){ return 0.0; }else{ return (salary - 1600) * 0.05; } }
public double getSalary(){ return salary; }
}
class Manager extends Employee{ private String job; //职务 private double fundses; //奖金
public Manager(String name, int age, boolean sex, String department, double salary, String job, double fundses){ super(name, age, sex, department, salary);
this.job = job; this.fundses = fundses;
}
//重写父类的计算个人所得税的方法 public double getTax(){ double sa = getSalary(); if(sa < 1600){ return (fundses * 0.1); }else{ return ((sa - 1600) * 0.05 + (fundses * 0.1)); } } }
public class ManagerTest{ public static void main(String[] args){ //Employee em = new Employee("张三", 23, true, "研发", 3000.0); //em.getTax(); Manager ma = new Manager("张四", 25, true, "研发", 6000.0, "技术经理", 2000.0); System.out.println(ma.getTax()); } } |
2.关于构造方法:
(1).调用子类构造方法构造一个对象时,先调用超类构造方法对超类的属性进行初始化,然后才调用自己的构造方法对自己的属性都进行初始化。
(2).如果子类构造方法没有显式调用超类构造方法,那么超类会使用默认构造方法。
(3).如果超类没有默认构造方法,而且子类构造方法又没有显示调用其它的超类构造方法,那么编译将报错。
(4).若要在子类构造方法中调用超类构造方法,则在子类构造方法的第一条语句用关键字 super来调用。
(5).语法为:super() 或 super(参数列表) ;
(6).super的第二用法:super还可用来调用超类的非私有属性、普通方法。
语法:super.方法名(参数列表);
十四、多态:不同的实例对象以不同的方式对相同的信息作出不同的表现
1.Java中,对象变量是多态的。超类变量既可以指向自己类型的对象,还可以指向它的任何子类的对象。如上例中:(子类和父类是“is-a”的关系)
Employee em = new Employee("张三", 23, true, "研发", 3000.0); Employee ma = new Manager("张四", 25, true, "研发", 6000.0, "技术经理", 2000.0); |
即:对于对象变量,编译器按照它声明的类型处理,而运行时Java虚拟机按照它实际引用的对象处理。
2.方法重载(Overload):一个类中有两个或多个方法的方法名相同,但参数列表不同,那就构成了方法的重载。
(1).方法重载构成的条件:
A. 一个类中有多个方法名相同;
B. 参数列表必须不同;(指参数的类型,个数或顺序不同)
C. 注意:返回值的类型可以不同;可见性(访问修饰符)也可以不同.
3.方法重写(Override):如果在子类中定义的一个方法,其名称、参数列表和返回类型与父类中某个方法的一样。那么就可以说,子类的方法覆盖了父类的方法。
(1).方法重写构成的条件:
A. 子类中的方法的名称,参数列表和返回值类型必须跟父类的一致
B. 可见性不能变窄。
C. 异常的范围不能被扩大。
十五、访问修饰符:适用于类,类的成员(成员变量,成员方法,构造方法),不能用于局部变量
1.public 公有的:对一切皆可见。
2.private 私有的:只对本类可见。
3.protected 受保护的:对所有子类和本包可见
4.默认:对本包可见。
十六、static 修饰符:
1.static修饰符可用于修饰变量,方法或代码块。
2.static修饰符的变量叫静态变量,类的所有实例共享这一个静态变量,应该用类名称来调用静态变量。
(1). 静态变量和实例变量(类的属性)的区别:
A.类的静态变量在内存中只有一个,Java虚拟机在加载类的过程中为静态变量分配内存。静态变量的生命周期取决于类的生命周期,当Java虚拟机加载类的时候,静态变量被创建并分配内存,当卸载类的时候,静态变量被销毁并撤消所占内存。
B. 类的每个实例都有相应的实例变量。每创建一个类的实例,Java虚拟机就会为实例变量分配一次内存。实例变量的生命周期取决于实例的生命周期,当创建实例的时候,实例变量被创建并分配内存,当销毁实例的时候,实例变量被销毁并撤消所占的内存。
3.static修饰符的方法叫静态方法,该方法独立于类的实例,使用类去访问,而不是类实例,所以也叫类方法,静态方法中不能使用 super 或 this 关键字
十七、final 修饰符:可用于修饰类,方法和变量
1.final修饰的变量就像是常量,声明时必须将其初始化 ,它的值不能更改。Final修饰的变量的名称用大写。
如: final int RED = 1;
final int GREE = 2;
2.final 修饰符修饰方法时,表示该方法不能被重写,修饰类时表示该类不能被继承。
3.final 修饰对象时,对该对象的引用不能更改。
十八、abstract 修饰符:
1.用abstract修饰的方法表示抽象方法,抽象方法没有方法体。抽象方法用来描述系统具有什么功能,但不提供具体的实现。
语法: [访问修饰符] abstract 返回类型 方法名(参数列表);
2.构造方法 和 static 方法不能是抽象的。
3.用abstract 修饰的类表示抽象类:
语法: [访问修饰符] abstract class 类名{…… }
4.具有一个或多个抽象方法的类必须声明为抽象类。
5.抽象方法如同方法占位符,这些方法会在子类中实现。扩展抽象类时,有两种选择。一是:实现抽象类中所有的抽象方法。二是:不实现所有的抽象方法,但这时子类也必须声明为抽象类。
6.抽象类不能被实例化,也就是说,如果一个类被声明为abstract,就不能构建这个类的任何对象。
7.注意:可以创建抽象类的对象变量,只是这个变量必须指向它的非抽象子类的对象。
/** 形状类--抽象类 */ abstract class Shape {
/** 存储任何形状的长. */ private double length;
/** 存储任何形状的宽. */ private double width;
/** 构造方法 */ Shape(final double num , final double num1) { /** 初始化变量. */ length = num; width = num1; }
/** 计算面积--抽象方法 */ public abstract double getArea(); }
/** 矩形 */ class Rectangle extends Shape {
/** 构造方法 */ Rectangle(final double num, final double num1) { super(num, num1); }
/** 计算矩形的面积—实现父类的计算面积的方法 */ public double getArea() { System.out.println("矩形的面积为:" ); return length * width; } }
/** 三角形 */ class Triangle extends Shape {
/** 构造方法 */ Triangle(final double num, final double num1) { super(num, num1); }
/** 计算三角形的面积--实现父类的方法 */ public double getArea() { System.out.println("三角形的面积为:" ); return (0.5 * length * width); } }
/** 测试类 */ public class CalculateArea {
public static void main(final String[] arg) { Shape shape1 = new Rectangle(10 , 20); Shape shape2 = new Triangle(12 , 8); System.out.println(shape1.getArea()); System.out.println(shape2.getArea()); } } |
十九、接口:
1. 接口就是某个事物对外提供的一些功能的申明,但是不包含具体的实现。
2. 可以利用接口实现多态,同时接口也弥补了Java单一继承的弱点
3. 使用interface关键字定义接口
4. 一般使用接口声明方法或常量,接口中的方法只能是声明,不能是具体的实现。
5. 接口中的任何方法都自动置为public的,属性也总是public static final的,接口没有构造方法,不能被实例化。
6. 用关键字 implements 实现接口,例如:
class Demo implements MyInterface
7. 每个类只能有一个超类,但可以实现多个接口。如果一个类实现了一个以上接口,则用逗号隔开接口名称,如下所示:
class Demo implements Mycalc, Mycount
8. 一个类实现了一个接口,它必须实现接口中定义的所有方法,否则该类必须声明为抽象类。
9. 可以声明接口变量,但它必须指向一个实现了该接口的类的对象。