- 一、封装
- 1 定义
- 2 this关键字
- 二、继承
- 1 定义
- 2 super关键字
- 3 重载与重写
- 重载
- 重写
- 三、多态
- 1 抽象类
- 2 接口
- 3 类型转换
面向对象三要素:封装、继承、多态
一、封装 1 定义
细节(变量和方法)隐藏,成员变量设置为私有(private),然后提供set和get方法读和取。
通俗的讲,封装就是不允许直接访问成员变量,必须通过set和get方法来访问。
优点:安全,便于重构。
public class ThreeDemo {
private String userName;
//set方法:给私有化变量赋值
public void setUserName(String v) {
userName = v;
}
//get方法:获取私有化变量的值
public String getUserName() {
return userName;
}
}
public class Test {
public static void main(String[] args) {
ThreeDemo td = new ThreeDemo();
td.setUserName("Mike");
//无法直接访问td.userName,故不可以用td.userName = “Mike”赋值
System.out.println(td.getUserName());
}
}
2 this关键字
表示当前类的对象
1 通过 this 关键字可以明确地去访问一个类的成员变量,解决与局部变量名称冲突的问题。
2 通过 this 关键字调用成员方法.
3 可以在一个构造方法中去使用 "this([参数1,参数2…])"的形式去调用其他构造方法。
注意:
1 只能在构造方法中使用this去调用其他构造方法
2 this关键字调用构造方法只能放在第一行,且只出现一次
3 不能在同一个类的两个构造方法中互调,产生编译错误
public class Father {
public String name;
public int age;
public Father() {//无参构造方法
System.out.println("Father");
}
public Father(String name, int age) {//有参构造方法
System.out.println("Father!");
}
}
public class Child extends Father{
public Child() {
this("Mike");
//super()与this()不能同时出现在构造函数中
//因为二者都需要放在构造函数的第一行
//但可以只写this,因为系统会自动使用super()
System.out.println("Child");
}
public Child(String str) {
System.out.println("Child!");
}
public static void main(String[] args) {
Child c = new Child();
}
}
二、继承
1 定义
通过关键字extends来声明子类与父类的继承关系:子类 extends 父类
1 所有类都有父类,即所有类都派生于Object类
2 只能单亲继承,即每个子类只能有一个父类
3 子类可以直接使用继承的变量和方法,不需要再在子类中声明或写出
4 子类只能继承父类的非private修饰的变量和方法
5 如果子类中公有的方法影响到了父类的私有属性,那么私有属性是能够被子类使用的。即通过父类的公有方法访问到父类的私有变量。
public class Father {
public String name;
public int age;
private String hobby;
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
}
public class Child extends Father{
public static void main(String[] args) {
Child c = new Child();
//对于父类的私有属性,虽然不能被继承,即不可通过c.hobby访问
//但可以通过继承的一些公有方法来改变私有属性的值
c.setHobby("basketball");
System.out.println(c.getHobby());
}
}
创建一个子类对象时,首先调用父类的无参构造方法,再调用子类的无参构造方法。
public class Father {
public String name;
public int age;
private String hobby;
public Father() {//无参构造方法
System.out.println("Father");
}
public Father(String name, int age) {//有参构造方法
this.name = name;
this.age = age;
System.out.println("Father!");
}
}
public class Child extends Father{
public Child() {
System.out.println("Child");
}
public static void main(String[] args) {
Child c = new Child();
}
}
Father
Child
//等价于super()
public class Child extends Father{
public Child() {
super();//调用父类的无参构造方法
System.out.println("Child");
}
public static void main(String[] args) {
Child c = new Child();
}
}
若想调用父类的有参构造方法:
public class Child extends Father{
public Child() {
super("Mike", 18);//调用父类的有参构造方法
System.out.println("Child");
}
public static void main(String[] args) {
Child c = new Child();
}
}
2 super关键字Father!
Child
表示当前类的父类对象,可以使用super关键字实现对父类变量和方法的访问
注意:在子类的构造方法中,无论写不写super(),java都会默认使用super()调用父类的构造方法
super调用父类构造方法:
1 在子类中,可以通过super()调用父类的构造方法
2 super()只能调用一次,且必须在子类构造方法的第一行
(如果super仅表示当前类的父类对象,用来访问父类的变量和方法等,则没有此限制)
public class Child extends Father{
public Child() {
super("Mike", 18);//调用父类的无参构造方法
super.age = 20;
super.setAge(10);
}
public static void main(String[] args) {
Child c = new Child();
System.out.println(c.age);
}
}
3 重载与重写 重载Father!
10
重载的是方法的参数列表
1 发生在同一个类中
2 方法名相同
3 参数列表不同(个数,数据类型,顺序)
注:
参数列表不同跟变量名称没关系
返回值的类型是否改变,跟方法是否重载没关系,不能作为重载的依据
public class Father {
//重载
public int study() {
return 1;
}
public void study(String str) {
}
}
重写
子类继承了父类的方法,对父类的方法中的执行代码进行修改以满足子类业务的需要,这就是重写。
1 重写发生在子父类当中
2 方法名、参数列表、返回值类型均相同
3 重写的方法,方法体不同,或者访问控制修饰符不同
4 子类方法的访问权限不能缩小
5 静态方法(static)不能进行重写(因为静态资源只加载一次)
生成的对象,在调用父类方法时,如果方法被子类重写,则调用的是子类重写的方法。
public class Father {
public void study(String str) {
System.out.println("Father!");
}
public static void learn() {//静态方法不能被重写
System.out.println("Learn");
}
public static void main(String[] args) {
Father f = new Father();
f.study(null);
Father.learn();
}
}
Father!
Learn
public class Child extends Father{
// @Override//重写注解,声明该方法是一个重写的方法
// public void study(String str) {
// System.out.println("Child!");
// }
public static void main(String[] args) {
Child c = new Child();
c.study(null);//执行父类的study()
}
}
Father!
public class Child extends Father{
@Override//重写注解,声明该方法是一个重写的方法
public void study(String str) {
System.out.println("Child!");
}
public static void main(String[] args) {
Child c = new Child();
c.study(null);//执行重写后的study()
}
}
三、多态Child!
没有继承就没有多态。代码当中体现多态性: 父类引用指向子类对象->父类 对象名 = new 子类()
1 抽象类抽象类不能被实例化(不能new对象),它的作用是提供给其他类进行继承。
关键字 abstract:
修饰类,类为抽象类,不能被实例化;
修饰方法,方法为抽象方法,只有方法的签名,没有方法体;
抽象类特点:
1 抽象类不能实例化,即抽象类不能创建对象;
2 子类继承抽象类,必须实现该抽象类当中所有的抽象方法;
public abstract class Father {
//抽象方法,只有方法的签名
public abstract String learn();
}
public class Child extends Father{
//子类继承抽象类,必须实现该抽象类当中所有的抽象方法;
@Override
public String learn() {
return "Child";
}
public static void main(String[] args) {
Child c = new Child();
System.out.println(c.learn());
}
}
3 抽象类,可以包含抽象方法和非抽象方法以及变量;
public abstract class Father {
//抽象类的成员变量
private String name;
//抽象方法,只有方法的签名
public abstract String learn();
//非抽象方法
public void study() {
System.out.println("Father-study");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Child extends Father{
//子类继承抽象类,必须实现该抽象类当中所有的抽象方法;
@Override
public String learn() {
return "Child-learn";
}
public static void main(String[] args) {
Father c = new Child();
c.study();//普通方法
System.out.println(c.learn());//重写的抽象类的抽象方法
c.setName("Mike");//对抽象类的成员变量赋值
System.out.println(c.getName());
}
}
Father-study
Child-learn
Mike
4 如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误;
5 抽象类可以有父类,但是父类必须有一个无参的构造函数,否则,抽象类必须声明一个与父类相同的有参构造方法;
接口是方法签名的集合
声明接口关键字 interface
实现接口关键字 implements
接口的特点:
1 用interface关键字声明接口;
2 子类实现接口,并重写接口的所有的签名方法;
3 接口只有方法的签名和变量;
4 接口的变量,会默认用public final static修饰;
5 接口的签名方法,会默认用public abstract修饰;
6 接口不能自身实例化,接口的实现类可以实例化;
7 接口可以实现多个,而父类只有一个(单亲继承),而且必须先继承(extends)父类再实现(implements)接口;
优点:
1 解决Java中的单亲继承问题(继承只能单亲继承,但是一个类可以实现多个接口)
2 接口可以实现并行开发
3 便于重构
public interface MyInterface {
int AGE = 20;//默认用public final static修饰
void study();//默认用public abstract修饰
}
public class MyImplements implements MyInterface{
@Override
public void study() {
System.out.println("重写方法签名");
}
public static void main(String[] args) {
//创建实现类的对象
MyImplements imp1 = new MyImplements();
imp1.study();
System.out.println(imp1.AGE);
//用多态的思想创建实现类
MyInterface imp2 = new MyImplements();
imp2.study();
System.out.println(imp2.AGE);
}
}
3 类型转换重写方法签名
20
重写方法签名
20
-
向上转型:子类对象 向父类转型
1 将一个 父类的引用 指向一个子类对象,称为向上转型;此时自动进行类型转换(即可以理解为创建了一个父类类型的子类对象)
2 通过父类的引用调用的方法,是子类重写或继承父类的方法,而不是父类原本的方法,更不是子类特有的方法;
3 通过父类的引用无法调用子类特有的方法,即向上转型的子类对象只能调用继承自父类的方法,而不能调用子类独有的方法,方法数量缩小,安全 -
向下转型:父类对象 向子类转型
父类对象向子类转换需要强制类型转换;
1 将一个指向子类对象的父类引用赋给一个子类的引用,称为向下转型
2 只有Object有向下转型的可能
Object obj = "123";//Object obj = new String("123")
String str = (String)obj;
System.out.println(str);
123



