面向对象
面向对象的三大特征
Ø封装
Ø继承
Ø多态
基本元素:类和元素
类(Class)和对象(Object)是面向对象的核心概念。
类是对一类事物的描述,是抽象的、概念上的定义
对象是实际存在的该类事物的每个个体,因而也称为实例(instance)。
属 性:对应类中的成员变量
行 为:对应类中的成员方法
Field = 属性 = 成员变量,Method = (成员)方法 = 函数
类的访问机制:
Ø在一个类中的访问机制:类中的方法可以直接访问类中的成员变量。
(例外:static方法访问非static,编译不通过。)
Ø在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中
定义的成员。
对象的创建和使用:内存解析
对象的创建和使用:匿名对象
我们也可以不定义对象的句柄,而直接调用这个对象的方法。这
样的对象叫做匿名对象。
如:new Person().shout();
在方法体外,类体内声明的变量称为成员变量。l在方法体内部声明的变量称为局部变量。
类的成员之一:属性
举例:
public class Person{
private int age; //声明private变量 age
public String name = “Lila”; //声明public变量 name
}
变量的分类:成员变量与局部变量
在方法体外,类体内声明的变量称为成员变量。
在方法体内部声明的变量称为局部变量。
注意:二者在初始化值方面的异同:
同:都有生命周期
异:局部变量除形参外,均需显式初始化。
类的成员之二:方 法(method)
举例:
public class Person{
private int age;
public int getAge() { //声明方法getAge()
return age;
}
public void setAge(int i) { //声明方法setAge
age = i;
//将参数i的值赋给类的成员变量age
}
}
方法的重载(overload)
重载的概念
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数
类型不同即可。
重载的特点:
(构造器也可以重载)
与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类
型)。调用时,根据方法参数列表的不同来区别。
重载示例:
//返回两个整数的和
int add(int x,int y){return x+y;}
//返回三个整数的和
int add(int x,int y,int z){return x+y+z;}
//返回两个小数的和
double add(double x,double y){return x+y;}
关于变量的赋值:
如果变量是基本数据类型:此时赋值的是变所保存的数据值。
如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
方法参数的值传递机制
l方法,必须由其所在类或对象调用才有意义。若方法含有参数:
Ø形参:方法声明时的参数
Ø实参:方法调用时实际传给形参的参数值
l Java的实参值如何传入方法呢?
Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本
(复制品)传入方法内,而参数本身不受影响。
Ø形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
Ø形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参
面向对象特征之一:封装和隐藏
Java中通过将数据声明为私有的(private),再提供公共的(public)
方法:getXxx()和setXxx()实现对该属性的操作,
class Animal {
private int
legs;// 将属性legs定义为private,只能被Animal类内部访问
public void setLegs(int i) { // 在这里定义方法 eat() 和 move()
if (i != 0 && i != 2 && i != 4) {
System.out.println("Wrong number of legs!");
return;
}
legs = i;
}
public int getLegs() {
return legs;
}
}
public class Zoo {
public static void main(String args[]) {
Animal xb = new Animal();
xb.setLegs(4); // xb.setLegs(-1000);
//xb.legs = -1000; // 非法
System.out.println(xb.getLegs());
}
}
类的成员之三:构造器(构造方法)
l构造器的特征
Ø它具有与类相同的名称
Ø它不声明返回值类型。(与声明为void不同)
Ø不能被static、final、synchronized、abstract、native修饰,不能有
return语句返回值
l构造器的作用:创建对象;给对象进行初始化
Ø如:Order o = new Order(); Person p = new Person(“Peter”,15);
注 意:
ØJava语言中,每个类都至少有一个构造器
Ø默认构造器的修饰符与所属类的修饰符一致
Ø一旦显式定义了构造器,则系统不再提供默认构造器
Ø一个类可以创建多个重载的构造器
Ø父类的构造器不可被子类继承
关键字—this
在Java中,this关键字比较难理解,它的作用和其词义很接近。
Ø
它在方法内部使用,即这个方法所属对象的引用;
Ø
它在构造器内部使用,表示该构造器正在初始化的对象。
l
this 可以调用类的属性、方法和构造器
l
什么时候使用this关键字呢?
Ø 当在方法内需要用到调用该方法的对象时,就用this。
具体的:我们可以用this来区分属性和局部变量。
比如:this.name = name;
* this关键字的使用:
* 1.this可以用来修饰、调用:属性、方法、构造器
*
* 2.this修饰属性和方法:
* this理解为:当前对象 或 当前正在创建的对象
*
* 2.1 在类的方法中,我们可以使用"this.属性"或"this.方法"的方式,调用当前对象属性或方法。但是,
* 通常情况下,我们都选择省略"this."。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式
* 的使用"this.变量"的方式,表明此变量是属性,而非形参。
*
* 2.2 在类的构造器中,我们可以使用"this.属性"或"this.方法"的方式,调用当前正在创建的对象属性或方法。
* 但是,通常情况下,我们都选择省略"this."。特殊情况下,如果构造器的形参和类的属性同名时,我们必须显式
* 的使用"this.变量"的方式,表明此变量是属性,而非形参。
*
* 3. this调用构造器
* ① 我们在类的构造器中,可以显式的使用"this(形参列表)"方式,调用本类中指定的其他构造器
* ② 构造器中不能通过"this(形参列表)"方式调用自己
* ③ 如果一个类中有n个构造器,则最多有 n - 1构造器中使用了"this(形参列表)"
* ④ 规定:"this(形参列表)"必须声明在当前构造器的首行
* ⑤ 构造器内部,最多只能声明一个"this(形参列表)",用来调用其他的构造器
注意:
"this(形参列表)"必须声明在类的构造器的首行!
Ø
在类的一个构造器中,最多只能声明一个"this(形参列表)"
关键字:
package import了解
JavaBean是指符合如下的java类
类是公共的,有一个无参的公共的构造器,有属性且有对应的get和set方法。
面向对象特征之二:继承性
子类继承了父类,就继承了父类的方法和属性。
l
在子类中,可以使用父类中定义的方法和属性,也可以创建新的数据和
方法。
l
在Java 中,继承的关键字用的是“extends”,即子类不是父类的子集,
而是对父类的“扩展”。
关于继承的规则:
子类不能直接访问父类中私有的(private)的成员变量和方法
Java只支持单继承和多层继承,不允许多重继承
一个子类只能有一个父类 Ø
一个父类可以派生出多个子类 ü
class SubDemo extends Demo{ } //ok ü
class SubDemo extends Demo1,Demo2...//error
方法的重写(override/overwrite)
(构造器不可以重载)
定义:在子类中可以根据需要对从父类中继承来的方法进行改造,也称
为方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。
l要求:
1. 子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
2. 子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型
3. 子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限
Ø子类不能重写父类中声明为private权限的方法
4. 子类方法抛出的异常不能大于父类被重写方法的异常
l 注意: 子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为
static的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法。
重写与重载之间的区别
方法重载:(不表现为多态性)
1、同一个类中
2、方法名相同,参数列表不同(参数顺序、个数、类型)
3、方法返回值、访问修饰符任意
4、与方法的参数名无关
方法重写:(表现为多态性)
1、有继承关系的子类中
2、方法名相同,参数列表相同(参数顺序、个数、类型),方法返回值相同
3、访问修饰符,访问范围需要大于等于父类的访问范围
4、与方法的参数名无关
关键字—super
在Java类中使用super来调用父类中的指定操作:
1,在子类的方法或构造器 中,通过使用“super.属性”或“super.方法”的方式,显式得到调用父类中声明的属性或方法。但是,通常情况下,我们习惯省略“super.”。
- 特殊,当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的使用“super.属性”的方式,表明调用的是父类中声明的属性。
- 特殊情况,当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的使用“super.方法”的方法,表明调用的是父类中被重写的方法。
4,
A:我们在子类的构造器中显式的使用“super(形参列表)”的方式,调用父类中声明的指定的构造器
B:“super(形参列表)”的使用,,必须声明在子类构造器的首行!
C:我们在类的构造器中,针对于“this(形参列表)”或”super(形参列表)”只能二选一,不能同时出现
D:在构造器的首行,没有显示的声明“this(形参列表)”或“super(形参列表)”则默认调用的是父类中空参的构造器,super()
E:在类的多个构造器中,至少有一个类的构造器中使用了“super(形参列表)”,调用父类中的构造器。
关键字super举例
class Person {
protected
String name = "张三";
protected int age;
public String getInfo() {
return "Name: " + name + "\nage: " + age;
}
}
class Student extends Person {
protected String name = "李四";
private String school = "New Oriental";
public String getSchool() {
return school;
}
public String getInfo() {
return super.getInfo() + "\nschool: " + school;
}
}
public class StudentTest {
public static void main(String[] args) {
Student st = new Student();
System.out.println(st.getInfo());
}
}
调用父类的构造器
l子类中所有的构造器默认都会访问父类中空参数的构造器
l 当父类中没有空参数的构造器时,子类的构造器必须通过this(参
数列表)或者super(参数列表)语句指定调用本类或者父类中相应的
构造器。同时,只能”二选一”,且必须放在构造器的首行
l如果子类构造器中既未显式调用父类或本类的构造器,且父类中又
没有无参的构造器,则编译出错
调用父类构造器举例
public class Person {
private String name;
private int age;
private Date birthDate;
public Person(String name, int age, Date d) {
this.name = name;
this.age = age;
this.birthDate = d;
}
public Person(String name, int ge) {
this(name, age, null);
}
public Person(String name, Date d) {
this(name, 30, d);
}
public Person(String name) {
this(name, 30);
}
}
调用父类构造器举例
public class Student extends Person {
private String school;
public Student(String name, int age, String s) {
super(name, age);
school = s;
}
public Student(String name, String s) {
super(name);
school = s;
}
// 编译出错: no super(),系统将调用父类无参数的构造器。
public Student(String s) {
school = s;
}
}
This(形参列表):本来重载的其他的构造器;
Super(形参列表):调用父类中指定的构造器
子类对象实例化的全过程
1. 从结果上来看:(继承性)
子类继承父类以后,就获取了父类中声明的属性或方法。
创建子类的对象,在堆空间中,就会加载所有父类中声明的属性。
2. 从过程上来看:
当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的父类的构造器,...
直到调用了java.lang.Object类中空参的构造器为止。正因为加载过所有的父类的结构,所以才可以看到内存中有
父类中的结构,子类对象才可以考虑进行调用。
明确:虽然创建子类对象时,调用了父类的构造器,但是自始至终就创建过一个对象,即为new的子类对象。
多态
什么是多态性,什么是虚拟方法调用?
父类的引用指向子类的对象(子类的对象赋值给父类的引用)
Person p = new Man();
P.eat();(当我们重写父类的方法时,运行的时候是子类重写之后的方法,既虚拟方法调用)
前提:
Ø 需要存在继承或者实现关系
Ø 有方法的重写
l
成员方法:
Ø 编译时:要查看引用变量所声明的类中是否有所调用的方法。
Ø 运行时:调用实际new的对象所属的类中的重写方法。
子类能获取父类private权限的属性或方法。
成员变量: 不具备多态的这种说法.
补充:
* 面向对象特征之三:多态性
*
* 1.理解多态性:可以理解为一个事物的多种形态。
* 2.何为多态性:
* 对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
*
* 3. 多态的使用:虚拟方法调用
* 有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
* 总结:编译,看左边;运行,看右边。
*
* 4.多态性的使用前提: ① 类的继承关系 ② 方法的重写
*
* 5.对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)