今日内容
1.作业
2.访问修饰符
3.static
4.多态
零、复习
私有化的单词: private
继承的关键词: extends
属性的封装
- 将属性私有,private
- 提供一对儿set,get
继承的特性:(自己的话说明)
- 继承目的是减少重复代码,父类代码子类自己使用
- A extends B
- 关于属性: 子类可以使用父类非私有的属性
- 关于方法: 子类可以使用父类非私有的方法,
- 如果父类方法不适用,就要重写方法
- 关于构造: 子类构造方法内有super()可以调用父类构造方法
this能干什么
- this调用属性,调用方法,调用构造方法
super能干什么
- 调用父类属性,调用父类方法,调用父类构造方法
重写的语法
- 子类和父类的访问修饰符,返回值类型,方法名,参数列表完全一样
一、作业
作业1: 详见项目day09/src/com/qf/homework/pdf6_t19
主要考察:属性封装,类继承,和方法重写
这是UML类体. 实线箭头代表继承关系
作业2: 详见项目day09/src/com/qf/homework/pdf6_t24
主要考察:属性封装,类继承,和方法重写以及super的使用,还有基本的代码逻辑(如何算工资)
二、访问修饰符
访问修饰符又叫 访问
权限
符,访问控制
符就是用来
限制属性和方法的使用范围的
,即类中的属性和方法在什么地方可以使用 什么地方不可以使用所以就有了两个研究方向
- 有哪些修饰符?
- 都有哪些地方?
当前类中 | 同一包下其他类 | 其他包子类内 | 其他包非子类 | |
---|---|---|---|---|
public(公开公共) | √ | √ | 自己能用,子对象能用 | √ |
protected(受保护) | √ | √ | 自己不能用,子类对象能用 | × |
缺省(默认)(不写) | √ | √ | × | × |
private(私有) | √ | × | × | × |
总结: 访问修饰符有访问大小范围:
public > protected > package > private
延伸: 子类重写父类方法,子类的访问修饰符 >= 父类访问修饰符
三、static
3.1 介绍
static 修饰符, 意思是静态的, 静态的一旦设置值就可以被所有对象使用
- 修饰属性
- 修饰方法
- 修饰内部类(了解)
作用:
- 被static修饰的属性或者方法在内存只有一个
- 被static修饰的属性或者方法,就会被所有对象共享
- 会随着类(class字节码文件)加载而初始化
回忆以前(没有static时)
- 一个类创建的多个对象和对象的关系? 相互独立互不影响
- 对象和属性和方法的关系, 每次创建一个对象,对象都有属于自己的属性和方法
static特性
- 凡是被static修饰的属性和方法,会随着class文件加载到内存而初始化
- 其他的普通成员变量是随着创建对象,在堆中出现初始化
- 静态的属性和方法会先出现,即没有创建对象时可以被使用了
- 有静态修饰的属性和方法时 不一定有对象
- 凡是被static修饰的属性和方法,在内存只有一份,被该类的所有对象共享
总结
- 不加静态的属性和方法通过对象调用
- 加了静态的属性和方法都通过类名调用
- 静态方法可以直接调用静态的方法和属性
- 静态方法不能直接调用非静态方法
- 非静态方法能调用静态属性和方法
- 静态方法内不能使用this
3.2 演示
黄牛卖演唱会票,假设100张票,多个黄牛在卖
public class Huangniu {
/**
* 属性不加static,那就是成员变量,又叫对象属性
* 叫对象属性是因为,每次创建对象,每个对象都有该属性
* 成员变量/对象属性是在内存堆中
* -----------------------------------------
* 但是加上static,不再是对象属性,即不属于每个对象,也不存在于堆中
* 而是在
*/
static int ticket = 100;
String name;
// 卖票
public void sellTicket(){
System.out.println("黄牛卖票" );
ticket--;
}
}
public class TestHuangniu {
public static void main(String[] args) {
// 找到黄牛
Huangniu niu1 = new Huangniu( );
// 先看有多少张票
// System.out.println(niu1.ticket );
// 静态的属性建议使用类名调用
System.out.println(Huangniu.ticket );
// 卖一张
niu1.sellTicket();
// 再看一眼余票
System.out.println( niu1.ticket);
System.out.println("----------------" );
// 再找到黄牛,卖票
Huangniu niu2 = new Huangniu( );
// 查看余票
System.out.println(niu2.ticket );
System.out.println("------------------" );
// toString就是静态方法,类名直接调用
Arrays.toString(new int[]{1});
// PI就是静态属性,类名直接调用
System.out.println(Math.PI );
}
}
3.3 应用场景
- 将一些方法或者属性定义成静态,方便调用,因为类名直接调用
例如: Arrays.toString, Math.PI- 当有些时候确实需要某个数据被共享时,就加上静态
例如: 火车票
四、多态
4.1 介绍
多态: 同一种东西多种形态
面向对象中的多态: 特指某个方法,运行得到不同的结果 (同一个对象调用同一个方法结果却不一样)
如何做?要同时满足三个条件
- 继承
- 重写
- 父类引用指向子类对象(向上转型)(把子类包装成父类)
为什么要多态?有什么好处?
- 提高代码扩展性
- 兼容性
- 降低耦合性
4.2 演示
4.3 关于多态的应用场景
- 方法的参数列表是父类,传参数传入子类对象,让该方法展现多态
public class TestPoly {
public static void main(String[] args) {
// 父类引用指向父类对象(自己引用指向自己对象)
// Animal animal = new Animal( );
// 子类引用指向子类对象(自己引用指向自己对象)
// Dog dog = new Dog( );
// 父类引用 指向 子类对象(向上转型)(将子类包装成父类)
// Animal animal = new Dog( );
// System.out.println(animal );
Animal animal = new Cat();
// eat方法就会出现多态
animal.eat();
System.out.println("-------------------" );
dogShow(new Dog());
catShow(new Cat());
System.out.println("-------------------" );
// 使用多态调用方法
animalShow(new Dog());// 向上转型
animalShow(new Cat());
animalShow(new Pig());
}
/**
* 设计方法,展示每个动物吃的东西
*/
public static void dogShow(Dog dog){
dog.eat();
}
public static void catShow(Cat cat){
cat.eat();
}
// 如果再加动物,这里就需要再重新定义好多方法
// 有了多态就可以解决这些问题
// 将方法参数列表设计父类,传参数时传入子类对象(向上转型)
// 这样就可以提高代码扩展性,大大减少了耦合性
public static void animalShow(Animal animal){
animal.eat();
}
}
- 方法的返回值是父类,允许返回子类对象
class Animal {
}
class Dog extends Animal {
}
class Cat extends Animal {
}
public class TestAnimal {
public static Animal getAnimal() {
//1
// return null; // ok
// return new Animal(); // ok
return new Cat(); // ok
//return new Dog(); // ok
}
public static void main(String args[]) {
Animal animal = getAnimal( );
System.out.println(animal );
}
}
- 利用多态性,设计父类类型的数组,存储子类对象
public class TestShape {
public static void main(String[] args) {
// 创建父类类型数组
// 数据类型[] 数组名 = new 数据类型[长度];
Shape[] shapes = new Shape[3];
// 存储的是子类对象
Circle circle = new Circle( );
circle.setR(10);
shapes[0] = circle;// 相当于向上转型
// 子类对象circle赋值给父类类型shape的引用
Rect rect = new Rect( );
rect.setLength(10);
rect.setWidth(5);
shapes[1] = rect;
Square square = new Square( );
square.setL(10);
shapes[2] = square;
for (int i = 0; i < shapes.length; i++) {
Shape shape = shapes[i];// 取值
// 运行看子类
double area = shape.area( );// 该方法会展现多态性
double girth = shape.girth( );// 该方法会展现多态性
System.out.println("面积:" + area );
System.out.println("周长:" + girth );
System.out.println("----------" );
}
}
}
4.4 注意事项
多态方法运行的注意事项
- 父类引用调用的方法如果子父类都有,那么就是展示子类的(运行看子类)
- 父类引用调用的方法父类有,子类没有 ----> 允许(编译看父类)
- 编译看父类,运行看子类
- 父类引用调用的方法,父类得有该方法,父类没有的话编译就报错
- 父类引用调用的方法,子类中有,那么就运行子类的
- 子类中没有该方法,就运行父类的
五、总结
关于访问修饰符 ,见到认识,知道什么效果即可
static,见到认识,知道类名可以直接调用静态方法和属性
重点还是多态,重点在于使用多态(参数,返回值,数组),重点在于题
写题口诀
多态前提: 继承,重写,向上转型
编译看父类,运行看子类
六、作业
t22
t25