属性私有,提供set/get方法 所有对对象的访问都应该通过方法调用来完成
访问修饰符
private 私有 只能在类的内部访问
public 公开
class Employee{
//属性
private String name;
private int age;
//为每个属性 添加set/get方法
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
}
1. is a关系
a).继承就是两个类之间形成 一种 一般-->特殊 。 满足 is a 关系时,就可以发生继承关系。 如: Dog is a Animal
b).构造方法不能继承
2.父类中的属性被private修饰
父类的哪些属性或方法能继承给子类? <== 等价于 ==> 子类能访问父类的哪些属性或方法
父类中的属性是private修饰时
1.可以说成子类没有继承父类的这个属性
2.也可以说,子类无法突破父类private的封装防线,无法访问,就像没有一样。
可以看到, Dog对象的内部,包含了一个 Animal对象。因此,在这个 Dog对象中,有两块数据区域,用来保存 Animal对象的 age属性。
3. 4种访问修饰符
按private ---> default ---> protected ---> public 的顺序,访问权限依次变宽
修饰符 | 访问范围 | 能否被子类继承 |
---|---|---|
private | 本类内部 | 不能 |
(default) | 本类内部+同包的其他类 | 能被同包的子类继承 |
protected | 本类内部+同包的其他类+非同包子类 | 能 |
public | 公开,被所有类访问 | 能 |
4种访问修饰符: 可以修饰属性,方法,构造方法
类的访问修饰符: default 只有同包的其他类可以访问
public 公开
4.方法的覆盖
子类用自己的方法实现替换掉父类继承给它的方法实现
语法要求: 访问修饰符相同或更宽,返回值类型相同,方法名相同,参数表相同,不能比父类抛出更多的异常
class Animal{
private void sleep(){//当父类的方法被private修饰时,子类继承不到,所以子类写什么方法都行
System.out.println("sleep 8 hours");
}
}
class Dog extends Animal{
public void sleep(){
System.out.println("sleep 6 hours");
}
}
5.对象的创建过程【重点】
1) 分配空间 2) 构造父类对象 3) 初始化本类属性 4) 调用本类构造方法
A <---- B <---- C
创建C对象
分配空间
初始化A属性
调用A构造方法
初始化B属性
调用B构造方法
初始化C属性
调用C构造方法
6.super关键字
作用1.引用 父类对象 用来调用父类被覆盖的方法
class Animal{
public Animal(){}
public void sleep(){
System.out.println("sleep 8 hours");
}
}
class Dog extends Animal{
public Dog(){}
public void sleep(){
super.sleep();//用来调用父类被覆盖的方法
System.out.println("sleep 6 hours");
}
}
作用2.用在构造方法中,指明调用父类哪个构造方法 必须出现在构造方法的第一行
class A{
public A(){
System.out.println("A()");
}
public A(String s){
System.out.println("A(String)");
}
}
class B extends A{
public B(){
//super(); //如果不写,编译器会自动添加一个无参构造方法
System.out.println("B()");
}
public B(String s){
super("abc");//指明调用父类哪个构造方法 必须出现在构造方法的第一行
System.out.println("B(String)");
}
}
一个构造方法的第一行必须是 super() :
1) 构造方法的第一行是super()或super(...)
2) 如果构造方法的第一行不是super(...) 也不是this(...) 默认为 super();
3) this(...) ----> super(),如下图
7.单继承
java是单继承,一个类只能有一个直接父类 这样,类之间会形成简单的树状结构
1.引用类型和对象类型
子类对象可以赋值给父类引用(父类引用指向子类对象)
public class TestPolymorphism{
public static void main(String[] args){
Animal a = new Dog();//父类引用指向子类对象
}
}
class Animal{}
class Dog extends Animal{}
2.多态的语法特性【重要】
a).只能对引用调用其引用类型中声明的方法
b).运行时根据对象实际类型调用子类覆盖之后的方法
*JVM 会根据引用中所存储的对象类型,去调用对象类型中覆盖之后的方法
c).对象类型不变(基本数据类型强转后,可能改变数据;引用之间强转改变不了数据类型!比如,不可能把一个Dog类型的 引用变成Cat类型)
public class TestPolymorphism{
public static void main(String[] args){
Animal a = new Dog();
a.eat();
a.sleep();//结果:sleep 6 hours ---> 运行时根据对象实际类型调用子类覆盖之后的方法
//a.shout(); error! a)只能对引用调用其引用类型中声明的方法
}
}
class Animal{
public void eat(){
System.out.println("Animal eat");
}
public void sleep(){
System.out.println("sleep 8 hours");
}
}
class Dog extends Animal{
public void shout(){
System.out.println("WangWang");
}
public void sleep(){
System.out.println("sleep 6 hours");
}
}
3.强制类型转换
Animal a Dog d Person p
a).子类引用赋值给父类引用 可以直接赋值 a = d
b).父类引用赋值给子类引用 需要强制类型转换 d = (Dog)a
c).没有继承关系的类的引用之间赋值 不可以 d = (Dog)p
*没有继承关系的强转失败是因为java是单继承,你不可能让Dog同时继承Animal和Person,因为Dog类已经继承了 Animal类,你再让一个Person类强转成Dog是不可能成功的,编译器会直接报错。
4.instanceof 关键字
使用:引用 instanceof 类名 可以翻译成" 是不是"
判断引用中的对象和 类名 是否兼容,用在强制类型转换之前,避免类型转换异常
if (a instanceof Dog){
Dog d =(Dog)a;
d.shout();
}
5.软件生命周期
开发 ---> 修改 ---> 改无可改 ---> 消亡
6.开闭原则:
软件产品对修改关闭, 对扩展开放
7.多态应用
利用多态,可以使代码针对父类展开编程,使得代码更通用
多态的两种常见应用场景:
1.把多态应用在方法的参数上 m(A a): m方法可以接收A类或A的某个子类对象作为实参
2.把多态应用在方法的返回值上
public class TestPoly2{
public static void main(String[] args){
feed(new Dog()); // Animal a = new Dog();
feed(new Cat()); // Animal a = new Cat();
Animal a = getAnimal(); // Animal a = new Cat();
}
//1.把多态应用在方法的参数上
static void feed(Animal a){
a.eat();
}
//2.把多态用用在方法的返回值上
static Animal getAnimal(){
return new Cat();
}
}
class Animal{
public void eat(){}
}
class Dog extends Animal{
public void eat(){
System.out.println("Dog eat bone");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("Cat eat fish");
}
}