1.封装
概述
面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改。封装可以认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。要访问该类的数据,必须通过指定的方法。适当的封装可以让代码更容易理解与维护,也可以增强代码的安全性。
原则
将属性隐藏起来,若需要访问某个属性,提供公共方法对其访问。
1.1 封装的操作–private关键字
private的含义
- private是一个权限修饰符,代表最小权限
- 可以修饰成员变量和成员方法
- 被private修饰后的成员变量和成员方法,只在本类中才能访问
private的使用格式
private 数据类型 变量名;
- 使用 private 修饰成员变量,代码如下:
public class Student{
private String name;
private int age;
}
-
提供 getXxx 方法 / setXxx 方法,可以访问成员变量,代码如下:
public class Student { private String name; private int age; public void setName(String n) { name = n; } public String getName() { return name; } public void setAge(int a) { age = a; } public int getAge() { return age; } }
1.2 封装优化1–this关键字
this的含义
this代表所在类的当前对象的引用(地址值),即对象自己的引用
注意:方法被哪个对象调用,方法的this就代表那个对象,即谁在调用this就代表谁
this使用格式
this.成员变量名;
1.3 封装优化2–构造方法
当一个对象被创建的时候,构造方法用来初始化该对象,给对象的成员变量赋初始值。
注意:无论是否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个无参构造方法,一旦自己定义了一个构造方法,Java自动提供的默认无参数构造方法就会失效。
构造方法的定义格式
修饰符 构造方法名(参数列表){
//方法体
}
构造方法的写法上,方法名与它所在类名相同。没有返回值,不需要返回值类型,甚至不需要void。使用构造方法后,代码如下 :
public class Student {
private String name;
private int age;
// 无参数构造方法
public Student() {}
// 有参数构造方法
public Student(String name,int age) {
this.name = name;
this.age = age;
}
}
注意事项
- 如果不提供构造方法,系统会给出无参构造方法
- 如果提供了构造方法,系统将不再给出无参构造方法
- 构造方法可以重载,既可以定义参数,也可以不定义参数
2.继承
2.1 继承的实现
-
继承的概念
- 继承也是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及追加属性和方法。
-
实现继承的格式
- 继承通过extends实现
- 格式:class 子类 extends 分类{ }
- 举例:class Son extends Father{ }
-
继承的好处
- 继承可以使类与类之间产生关系,字父类关系,子类可以使用父类中非私有的成员
-
代码示例
public class Fu { public void show() { System.out.println("show方法被调用"); } } public class Zi extends Fu { public void method() { System.out.println("method方法被调用"); } } public class Demo { public static void main(String[] args) { //创建对象,调用方法 Fu f = new Fu(); f.show(); Zi z = new Zi(); z.method(); z.show(); } }
2.2 继承的好处和弊端
-
继承好处
- 提高代码的复用性(多个相同的成员可以放到同一个类中)
- 提高了代码的维护性(如果方法的代码需要修改,修改一处即可)
-
继承弊端
- 继承让类与类之间产生了关系,类的耦合性增强了,当父类发生变化时子类实现也不得不跟着变化,削 弱了子类的独立性
-
继承的应用场景
- 使用继承,需要考虑类与类之间是否存在is…a的关系,不能盲目使用继承
- is…a的关系:谁是谁的一种,例如:老师和学生是人的一种,那人就是父类,学生和老师就是子类
- 使用继承,需要考虑类与类之间是否存在is…a的关系,不能盲目使用继承
2.3 Java继承的特点
- Java中继承的特点
- Java中类只支持单继承,不支持多继承
- 错误范例:class A extends B, C { }
- Java中类支持多层继承
- Java中类只支持单继承,不支持多继承
2.4 继承中成员变量访问特点
2.4.1 继承中变量的访问特点
在子类方法中访问一个变量,采用的是就近原则。
- 子类局部范围找
- 子类成员范围找
- 父类成员范围找
- 如果都没有就报错(不考虑父类的父类)
-
代码示例
-
class Fu { int num = 10; } class Zi { int num = 20; public void show(){ int num = 30; System.out.println(num); } } public class Demo1 { public static void main(String[] args) { Zi z = new Zi(); z.show(); // 输出show方法中的局部变量30 } }
2.4.2 super关键字
-
this&super关键字:
- this:代表本类对象的引用
- super:代表父类存储空间的标识(可以理解为父类对象引用)
-
this和super的使用分别
-
成员变量:
-
this.成员变量 - 访问本类成员变量
-
super.成员变量 - 访问父类成员变量
-
-
成员方法:
- this.成员方法 - 访问本类成员方法
- super.成员方法 - 访问父类成员方法
-
-
构造方法:
- this(…) - 访问本类构造方法
- super(…) - 访问父类构造方法
2.4.3 继承中构造方法的访问特点
注意:子类中所有的构造方法默认都会访问父类中无参的构造方法
子类会继承父类中的数据,可能还会使用父类的数据。所有,子类初始化前,一定要先完成父类数据的初始化,原因在于,每一个子类构造方法的第一条语句默认都是:super()
问题:如果父类中没有无参构造方法,只有带参构造,解决方案:
- 通过使用super关键字去显示的调用父类的带参构造方法
- 子类通过this关键字去调用本类的其他构造方法,本类的其他构造方法再通过super去手动调用父类的带参的构造方法
注意:this(…)super(…)必须放在构造方法的第一行有效语句,且二者不能共存
2.4.4 继承中成员方法的访问特点
通过子类对象访问一个方法
- 子类成员范围找
- 父类成员范围找
- 如果都没有就报错(不考虑父类的父类)
3.多态
3.1 概述
多态是继封装、继承之后,面向对象的第三大特性。
生活中,比如跑得动作,不同动物具体是不一样的…可见同一行为,通过不同的事物,可以体现出来不同的形态,多态,描述的就是这样的状态。
定义
- 多态:是指同一行为,具有多个不同表现形式。
前提
- 继承或者实现 【二选一】
- 方法的重写【必须重写,否则无意义】
- 父类引用指向子类对象 【格式体现】
3.2 多态的体现
多态体现的格式:
父类类型 变量名=new 子类对象;
变量名.方法名();
父类类型:指子类对象继承的父类类型,或者实现父类接口类型
代码表示如下:
Father f=new Son();
f.method();
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写后方法。
代码如下:
定义父类:
public abstract class Animal{
public abstract void eat();
}
定义子类:
class cat extends Animal{
public void eat(){
sout("eat fish");
}
}
class Dog extends Animal{
public void eat9){
sout("eat shit");
}
}
定义测试类
public class Test{
public Static void main(String [] args){
//多态创建对象
Animal a1=new Cat();
//调用的是Cat的eat
a1.eat();
//多态创建对象
Animal a2=new Dog();
//调用的是Dog的eat
a2.eat();
}
}
3.3 多态的好处
在实际开发过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展性与便利
3.4 引用类型转换
多态的转型分为向上转型与向下转型:
向上转型
- 向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。
当父类引用指向一个子类对象时,就是向上转型
格式:
父类类型 变量名 = new 子类类型();
Animal a = new Dog();
向下转型
- 向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。
一个已经向上转型的子类对象,将父类引用转化为子类引用可以使用强制类型转换的格式,就是向下转型。
使用格式:
子类类型 变量名=(子类类型)父类变量名;
Dog d = (Dog) a;
instanceof 关键字
当两个类型没有任何继承关系,不符合类型转换定义时,会报出ClassCastException
,类型转换异常。为了避免ClassCastException
的发生,Java提供了 instanceof
关键字,给引用变量做类型的校验,格式如下:
变量名 instanceof 数据类型
如果变量属于该数据类型,返回true
如果变量不属于该数据类型,返回false
代码示例如下:
public class Test{
puclic static void main(String [] args){
//向上转型
Animal a=new Cat();
a.eat();//调用Cat的eat
//向下转型
if(a.instanceof Cat){
Cat c=(Cat) a;
c.catchMouse();//调用的是Cat的catchMouse
}else if(a instanceof Dog){
Dog d=(Dog)a;
d.watchHouse();//调用Dog的watchHouse
}
}
}