Java笔记之面向对象 中(八)

一、封装

1.基本介绍

封装:是指把抽象出的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作,才能对数据进行操作

2.实现步骤

  1. 将属性进行私有化private
  2. 提供一个公共的set方法,用于对属性判断并赋值
  3. 提供一个公共的get方法,用户获取属性的值

3.快速入门

要求:定义一个Person类,其中有姓名和年龄的属性,使用封装的思想对属性进行设置与查看,并且年龄在1-120,否则给默认年龄18,名字必须是2-6个字符,否则给默认名字“张三”

package com.test;

public class Test {
    public static void main(String[] args) {
        //不使用构造方法
//        Person person = new Person();
//        person.setName("小明");
//        person.setAge(130);
//        person.p();     //name=小明   age=18
//        System.out.println(person.info());  //name=小明   age=18

        //使用构造方法
        Person penson = new Person("小明", 130);
        System.out.println(penson.info());  //name=小明   age=18
    }
}

class Person {
    String name;
    int age;

    //无参构造,如果不写也是存在的,最好写一下
    public Person(){
    }

    //构造方法
    public Person(String name, int age) {
        setName(name);
        setAge(age);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if (name.length() >= 2 && name.length() <= 6) {
            this.name = name;
        } else {
            System.out.println("你设置的姓名超出范围,默认设置为张三");
            this.name = "张三";
        }

    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age >= 1 && age <= 120) {
            this.age = age;
        } else {
            System.out.println("你设置的年龄超出范围,默认设置为18");
            this.age = 18;
        }
    }

    //输出信息
    public void p() {
        System.out.println("name=" + name + "  " + "age=" + age);
    }

    //使用get方法获取信息,并放在string中
    public String info(){
        return "name="+getName()+"  "+"age="+getAge();
    }
}

二、继承

1.基本介绍

继承:可以提高代码的复用性、扩展性和维护性,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中 抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来 声明继承父类即可。

语法格式:
class 子类 extends 父类{

}

  • 子类就会有父类中的属性和方法
  • 父类又叫 超类或基类
  • 子类又叫 派生类

2.快速入门

public class Test {
    public static void main(String[] args) {
        //子类man的对象
        Person man = new man();
        man.name= "小明";
        man.age = 20;
        man.setSex('男'); //可以调用父类中的方法
        man.p();

        //子类woman的对象
        Person woman = new man();
        woman.name= "小明";
        woman.age = 20;
        woman.setSex('女'); //可以调用父类中的方法
        woman.p();
    }
}

//父类
class Person {
    //共同属性
    String name;
    int age;
    char sex;

    //共同方法
    public void setSex(char sex) {
        this.sex = sex;
    }

    //输出信息
    public void p() {
        System.out.println("name=" + name + "  " + "age=" + age+"  "+"sex="+sex);
    }
}

//子类
class man extends Person{
    public void test(){
        //这里的name就是继承它的父类Person中的name
        System.out.println("man的姓名:"+name);
    }
}

//子类
class woman extends Person{
    public void test(){
        //这里的name就是继承它的父类Person中的name
        System.out.println("woman的姓名:"+name);
    }
}

3.注意事项和使用细节

  1. 子类继承父类所有的属性和方法,非私有的属性和方法可以直接访问, 但是私有属性和方法不能直接访 问,要通过父类提供公共的方法去访问
//父类
class Person {
    //共同属性
    public String name = "张三";
    private int age = 18;
	
	//获取私有属性
    public int get(){
        return age;
    }
}

//子类
class man extends Person{
    public void test(){
        System.out.println("姓名:"+name);

        //因为父类中的age是私有的所以访问不了
        //System.out.println("年龄:"+age);

        //如果想访问父类中私有的属性,则可以利用父类的公共方法
        System.out.println("年龄:"+get());
    }
}
  1. 子类创建对象时必须调用父类的构造器,完成父类的初始化(因为子类构造方法的第一行中有一个隐藏的super())
public class Test {
    public static void main(String[] args) {
        //子类man的对象
        man man = new man();	//父类的无参构造被调用! 子类的无参构造被调用!
    }
}

//父类
class Person {
    //Person无参构造方法
    public Person(){
        System.out.println("父类的无参构造被调用!");
    }
}

//子类
class man extends Person{
    //man无参构造方法
    public man(){
        System.out.println("子类的无参构造被调用!");
    }
}
  1. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不通过
public class Test {
    public static void main(String[] args) {
        //当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器
        man man = new man();    //输出:父类的无参构造被调用!  子类的无参构造被调用!
        man man1 = new man(2);  //输出:父类的无参构造被调用!   子类的有参构造被调用!
    }
}

//父类
class Person {
    //Person无参构造方法
    public Person(){
        System.out.println("父类的无参构造被调用!");
    }
}

//子类
class man extends Person{
    //man无参构造方法
    public man(){
        System.out.println("子类的无参构造被调用!");
    }
    //man有参构造
    public man(int x){
        System.out.println("子类的有参构造被调用!");
    }
}
public class Test {
    public static void main(String[] args) {
        //如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作
        man man = new man();    //输出:父类的有参构造被调用!  子类的无参构造被调用!
    }
}

//父类
class Person {
    String name;
    int age;

    //Person的有参构造方法,无参的构造方法则会默认被覆盖
    public Person(String name,int age){
        System.out.println("父类的有参构造被调用!");
    }
}

//子类
class man extends Person{
    //man无参构造方法
    public man(){
        //因为找不到默认的构造器,则会报错,则需要使用super()指定父类中的构造器
        super("张三",18);
        System.out.println("子类的无参构造被调用!");
    }
}
  1. 如果希望指定去调用父类的某个构造器,则需要显式的调用 : super(参数列表)
public class Test {
    public static void main(String[] args) {
        man man = new man();    //输出:父类的有参构造被调用!  子类的无参构造被调用!
    }
}

//父类
class Person {
    String name;
    int age;

    //无参构造方法
    public Person(){
        System.out.println("父类的无参构造被调用!");
    }

    //有参构造方法
    public Person(String name,int age){
        System.out.println("父类的有参构造被调用!");
    }
}

//子类
class man extends Person{
    //子类无参构造方法
    public man(){
        //super()调用父类的无参构造,或者不写默认调用父类的无参构造
        //super();

        //调用父类的有参构造,注意只能有一个super
        super("张三",18);
        System.out.println("子类的无参构造被调用!");
    }
}

  1. super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)
  2. super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
  3. java中所有类都是 Object 类的子类, Object 是所有类的基类(父类)
  4. 父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)
  5. 子类最多只能直接继承一个父类,但可以间接继承多个类 如:A即想继承B又想继承C,可以让B继承C然后A再继承B
  6. 不能滥用继承,子类和父类之间必须满足一定的的逻辑关系,如 动物和狗
  7. super在构造器中是默认存在,虽然看不见,但是确实存在
public class Test {
    public static void main(String[] args) {
        C c = new C();
        /*
        我是A类
        123我是父类有参构造
        hello我是子类的有参构造
        我是子类的无参构造
         */
    }
}

//爷爷类
class A{
    public A(){
        System.out.println("我是爷爷类");
    }
}

//父类
class B extends A{
    public B(){
        System.out.println("我是父类无参构造");
    }

    public B(String name){
        //默认有个super
        System.out.println(name+"我是父类有参构造");
    }
}

//子类
class C extends B{
    //子类无参构造方法
    public C(){
        this("hello");
        System.out.println("我是子类的无参构造");
    }

    public C(String name){
        super("123");
        System.out.println(name+"我是子类的有参构造");
    }
}

三、super的使用

1.基本介绍

super代表父类的引用,用于访问父类的属性,方法,构造器

2.基本语法

1.访问父类的属性,但不能访问private私有属性

super.属性名;

2.访问父类的方法,但不能访问private私有方法

super.方法;

3.访问父类的构造器(只能放在构造器的第一句)

super.(参数);

3.使用细节

1.当子类中有和父类中的属性和方法重名时,为访问父类的成员,必须通过super。如果没有重名,则可以使用super、this直接访问,效果是一样的

public class Test {
    public static void main(String[] args) {
        C c = new C();
        c.sum();    //sum方法
    }
}

class B{
    public void sum(){
        System.out.println("sum方法");
    }
}

//子类
class C extends B{
    public void p(){
        System.out.println("p方法");
    }

    public void cal(){
        /*
        1.首先找本类中有没有sum方法,如果有,则调用
        2.如果没有,则去父类找,如果有,则调用,没有继续往上找,直到Object,如果object也没有就会报错
        注意:如果找到sum方法,则需要注意访问修饰符,如果不能访问也会报错
        3.sum()和this.sum()两者等价
        4.super.sum()表示跳过本类,直接去父类中找sum(),后面逻辑和上面一样
         */
        //sum();
        super.sum();
    }
}

2.如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个父类中都有同名的成员,使用super访问遵循就近原则(注意:其中也跟访问修饰符有关)

public class Test {
    public static void main(String[] args) {
        C c = new C();
        c.sum();    //就近原则:B类中的sum方法
    }
}

class A{
    public void sum(){
        System.out.println("A类中的sum方法");
    }
}

class B extends A{
    public void sum(){
        System.out.println("B类中的sum方法");
    }
}

//子类
class C extends B{
    public void p(){
        System.out.println("p方法");
    }

    public void cal(){
        //不考虑访问修饰符的话,则就近原则
        sum();
    }
}

4.this和super的区别

No.区别点thissuper
1访问属性访问本类中的属性,如果本类没有此属性则从父类中继续查找从父类开始查找属性
2调用方法访问本类中的方法,如果本类没有此方法则从父类继续查找从父类开始查找方法
3调用构造器调用本类构造器,必须放在构造器的首行调用父类构造器,必须放在子类构造器的首行
4特殊表示当前对象子类中访问父类对象

四、方法的重写

1.基本介绍

就是说子类中的方法和父类(包括父类的父类)中方法的方法名、返回值类型、参数都一样,其中返回值类型可以不一样,那么就是子类中的方法重写了父类中的方法

2.快速入门

class A{
    public void p(){
        System.out.println("A类中的sum方法");
    }
}

class B extends A{
    public void p(){
        //方法名、返回值类型、参数列表都一样,说明子类重写父类的p方法
        System.out.println("B类中的sum方法");
    }
}

3.注意事项

1.如果方法重写,子类方法的返回值类型可以和父类不一样,但要求子类方法的返回值类型必须是父类方法返回值类型的子类 如:父类方法的返回值类型是object 而子类是string,这种情况是可以的,也是重写

//案例一
class A{
    public Object p(){
        return 1;
    }
}

class B extends A{
    public String p(){
        //方法名、参数列表都一样,返回值类型不一样,也可以说明子类重写父类的p方法
        return "bbb";
    }
}
//案例二
class A{
    public C p(){
        return null;
    }
}

class B extends A{
    //p方法的重写,因为D是C的子类也是可以的,这里的返回值类型是引用类型
    public D p(){
        return null;
    }
}

class C{ }
class D extends C{ }

2.子类方法不能缩小父类方法的访问权限(访问修饰符),反之可以

class A{
    public void p(){
    }
}

class B extends A{
    //子类的访问修饰符不能缩小了父类访问修饰符的范围,所以会报错,反之是可以的
    protected void p(){		//错误
    }
}
class A{
    protected void p(){
    }
}

class B extends A{
    //子类可以扩大父类重写方法的范围
    public void p(){	//正确
    }
}

五、方法重写和重载的区别

名称范围方法名形参列表返回类型修饰符
重载本类必须一样类型、个数、顺序、至少有一个不同无要求无要求
重写父子类必须一样相同子类方法返回值类型和父类一样,或者是其子类子类方法不能缩小父类方法的访问范围
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王博1999

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值