java学习笔记第二周(二)

目录

一、面向对象三大特征

1、继承

1.1继承的实现:

1.2instanceof运算符

1.3继承使用要点

1.4方法的重写override

1.5final关键字

1.6继承和组合

2、Object类详解

2.1Object类基本特征

2.2toString方法

2.3"=="和equals方法

2.4super关键字

3、封装

3.1封装的作用和含义

3.2封装的实现--使用访问控制符

3.3封装的使用细节以及get,set方法  

4、多态

4.1多态的概念和实现

4.2对象的转型

4.3 父类引用指向子类对象的意义 



一、面向对象三大特征

1、继承

继承是面向对象编程的三大特征之一,它让我们更加容易对于已有类的扩展、更加容易实现对于显现实世界的建模。

继承有两个主要作用:

1、代码复用,更加容易实现类的扩展。

2、方便对事物建模。

1.1继承的实现:

继承让我们更加容易实现类的拓展。比如,我们定义了人类,再定义boy就只需要扩展人类即可。实现了代码的重用。在java中使用extends来实现继承,子类是父类的扩展。在编程中,如果新定义一个Student类,发现已经有Person类包含了我们需要的属性和方法,那么Student类只需要继承Person类即可拥有Person类的属性和方法。

继承的使用举例:

package studyweek2;

class Person{
    String name;
    int height;
    public void rest(){
        System.out.println("休息一会");
    }
}
class Student extends Person{//extend核心代码,把Person类继承到Students
    String major;
    public void study(){
        System.out.println("赶快学习java");
    }
    public Student(String name,int height,String major){
        this.name=name;
        this.height=height;
        this.major=major;
    }
}
public class jicheng{
    public static void main(){
        Student s=new Student("ji",172,"java");
        s.rest();
        s.study();
    }
}

除了构造方法之外的所有的属性和方法都被继承,但是不代表都能使用(比如private)

1.2instanceof运算符

instanceof是二元运算符,左边是对象,右边是类;当对象是右边的类或子类所创建对象时,返回true;否则,返回false。

1.3继承使用要点

单继承:每一个类只能有一个父类(可以有多个子类)。

1.4方法的重写override

子类通过重写的方法,可以用自身的行为替换父亲的行为。方法的重写是实现多态的必要条件。加简而言之就是在子类里重新进行定义实现覆盖。

方法的重写需要符合下面的三个要点:

1、"==":方法名、形参列表相同。

2、"<=":返回值类型和声明异常类型,子类小于等于父亲。

3、">=":访问权限,子类大于等于父类。

1.5final关键字

final关键字的作用:

1、修饰变量:被final修饰的变量不可改变。一旦赋了初值,就不能被重新赋值。例:final int a=100;

2、修饰方法:该方法不可被子类重写,但是可以被重载!     例:final void study(){}

3、修饰类:修饰的类不能被继承。比如Math、String。       例:final class a{}

1.6继承和组合

我们可以通过继承方便的复用已经定义类的代码。还有一种方式也可以方便的实现“代码复用”,那就是:“组合”。

组合不同于继承,更加灵活。

组成的核心就是:将父类对象作为子类的属性,然后子类通过调用这个属性来获得父类的属性和方法。

//组合的例子:
public class study3{
    public static void main(String[] args){
        Taidi c=new Taidi();//new一个Taidi类的对象,而Taidi类里的对象a,而a又是用Dog类new出来的,因此c有Dog类的所有属性。
        c.a.height
        c.a.shout();//不能直接用c.shout!
    }
}
class Taidi{
    Dog a=new Dog();//在Taidi这个类中new一个Dog类,a有了Dog类里的所有属性。
}
class Dog{
    int height;
    public void shout(){
        System.out.println("冲冲冲");
    }
}

2、Object类详解

2.1Object类基本特征

Object类是所有java类的根基类,也就意味着所有的java对象都拥有Object类的属性和方法。如果在类的声明中未使用extend关键字指明其直接父类,则默认继承Object类。

2.2toString方法

Object类中定义有public String toString()方法,其返回值是String类型。Object类中toString方法的源码为:

//重写toString()方法:@override
public String toString(){
    return getClass().getName()+"@"+Integer.toHexString(hashCode())
}


public static void main(String[] args){
    User u1=new User();
    User u2=new User();
    
    System.out.println(u1);
    System.out.println(u2.toString());//与直接输出u2等价
}

 

不难看出,默认会返回类名+@+16进制的hashcode。在打印输出或者用字符串连接对象时,会自动调用该对象的toString()方法。如果要重写toString()方法,在开头加上@override

2.3"=="和equals方法

"="代表比较双方是否相同。如果是基本类型则表示值相等,如果是引用类型则表示地址相等即表示同一个对象。

Object类中定义有:public boolean equals(Object obj)方法,提供定义对象内容相等的逻辑。比如,我们在公安系统中认为id相同的人就是同一个人......

Object的equals方法默认就是比较两个对象的hashcode,是同一个对象的引用时返回true,否则返回false。但是,我们可以根据自己的要求重写equals方法。

System.out.println(u1==u2);//"=="就是判断是不是同一个对象。
System.out.println(u1.equals(u2));//equals判断两个对象的"逻辑上的值是不是一样",比如当两个人id一样我们就认为这两个是同一个对象

//可以使用alt加ins快速创建
//重写equals方法:
public boolean equals(Object obj){
    if(obj==null){return false};
    }
    else{
        if(obj instanceof Person){
            Person c=(Person)obj;
            if(c.id==this.id){retuen true;}
        }
    }
return false;
}

2.4super关键字

super可以看作是直接父类对象的引用,可以通过super来访问父类中被子类覆盖的方法和属性。

使用super调用普通方法,语句没有位置限制,可以在子类中随便调用。

class FatherClass{
    public int value;
    public void f(){
        value=100;
        System.out.println("FatherClass.value"+value);
    }
}
class ChildClass extends FatherClass{
    public int value;
    public void f(){
        super.f();//在子类中调用父类的普通方法,且super只能在子类中使用
        value=200;
        System.out.println("ChildClass.value"+value);
        System.out.println(value);
        System.out.println(super.value);//从这里可以看出重写并不会改变父类的属性和方法,而是会保留。
    }

}
public  class study3{
    public static void main(String[] args){
        new ChildClass().f(); //这种写法相当于下面两行代码的写法,只不过这种写法没有引用。
//        ChildClass a=new ChildClass();
//        a.f();
    }
}

注意:若是构造方法的第一行代码没有显式的调用super()或者this(),那么java默认会调用super(),含义是调用父类的无参数构造方法。这里的super()可以省略。

class FatherClass2{
    public FatherClass2(){
        System.out.println("创建父类");
    }
}
class ChildClass extends FatherClass2{
    public ChildClass(){
//这里相当于加了一行代码: super();//第一句都是super()或者this(),因此都是父类先建好。
        System.out.println("创建子类");
    }
}
public class study3{

    public static void main(String[] args){
        System.out.println("进入程序");
        new ChildClass();
    }
}

注意!!!由于在子类构造器里一定会有super()去调用父类无参数构造方法,而如果此时父类中你已经定义了一个有参数的构造方法,那么父类就没有无参构造方了,编译就无法通过,解决方案有:

1、在子类构造器第一句使用super(参数) ;

2、在父类定义一个无参构造器(建议使用,并且建议只要是父类的都手动添加一个无参构造方法。)

下面是一个转载的资料链接:

父类在继承时一定要有无参构造器原因https://blog.csdn.net/weixin_46751741/article/details/121011395

3、封装

3.1封装的作用和含义

3.2封装的实现--使用访问控制符

 protected使用的两个注意事项:

1、若父类和子类在同一个包中,子类可以访问父类的protected成员,也可以访问父类对象的protected成员。

2、若父类和子类不在同一个包中,子类可访问父类的protected成员,但不可以访问父类对象的protected成员。

3.3封装的使用细节以及get,set方法  

 get、set方法使用例子:

package studyweek2;

public class study4 {
    private int age;
    public String name;
    private boolean flag;

    public int getAge(){
        return age;
    }
    public void setAge(int age){
        this.age=age;
    }
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name=name;
    }
    public boolean isFlag(){//boolean类型不适用get,使用is开头。
        return flag;
    }
    public void setFlag(boolean flag){
        this.flag=flag;
    }
    public static void main(String[] args) {
        study4 a=new study4();
        a.setAge(20);
        a.setName("jlk");
        a.setFlag(true);
        System.out.println(a.getAge());
        System.out.println(a.getName());
        System.out.println(a.isFlag());
    }
}

4、多态

4.1多态的概念和实现

以下是使用多态的案例:

package studyweek2;
//多态
class Animals{
    public void shout(){
        System.out.println("叫了一声");
    }
}
class Dog extends Animals {
    @Override
    public void shout() {
        System.out.println("汪");
    }
}
class Cat extends Animals{
    @Override
    public void shout() {
        System.out.println("喵");
    }
}
public class study5 {
    //有了多态,只需要让增加的这个类继承Animal类就可以了。
    static void animalCry(Animals a){//父类引用可以指向子类对象,而方法参数也是引用,故可以直接用父类作为参数,但是运行的时候使用的是运行类型,也就是后面的Cat和Dog类
        a.shout();
    }
    public static void main(String[] args) {
        Animals a1=new Cat();//父类引用指向子类对象。向上可以自动转型。
        //传的具体是哪一个类就调用哪一个类的方法,大大提高了程序的可扩展性。
        animalCry(a1);//运行类型是Cat,因此调用的时候就是使用Cat类的方法
        Animals a2=new Dog();
        animalCry(a2);

    }
}

 核心语句:父类 变量名=new 子类(),这里使用了父类引用指向了子类对象,由于是向上赋值,因此可以自动转型。具体赋值过程如下:

而如果不使用多态的话

    static void animalCry(Dog a){
        a.shout();
    }
    static void animalCry(Cat a){
        a.shout();
    }
//万一其他程序员再添加一个tiger类,又得重新定义一个参数为Tiger a的方法
    static void animalCry(Tiger a){
        a.shout();
    }

以下说法会更好理解,在运行的时候都是用的时运行类型 

补充事项:如果父类中定义了一个静态方法,子类中是无法对静态方法进行重写,而如果子类未对父类方法进行重写,那么父类引用指向子类对象时,父类引用所能看到的只是属于父类的那一部分属性和方法。如下列例子 : 

 
public class StaticTest
{
    public static void main(String[] args)
    {
        M m = new N();
        m.output();//由于没有重写,运行时就只会按父类来运行,就不会按照子类。
    }
}
 
class M
{
    public static void output()
    {
        System.out.println("M");
    }
}
 
class N extends M
{
    public static void output()//父类含静态方法,而子类是无法重写静态方法的。
    {
        System.out.println("N");
    }
}

 父类引用指向子类对象的方法调用问题https://blog.csdn.net/qq_29163727/article/details/115288394?ops_request_misc=&request_id=&biz_id=102&utm_term=%E7%88%B6%E7%B1%BB%E5%BC%95%E7%94%A8%E6%8C%87%E5%90%91%E5%AD%90%E7%B1%BB%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%96%B9%E6%B3%95%E8%B0%83%E7%94%A8%E9%97%AE%E9%A2%98&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-115288394.first_rank_v2_pc_rank_v29&spm=1018.2226.3001.4187

父类引用指向子类对象的注意点

向上转型:

向下转型: 

4.2对象的转型

在上文中,父类引用指向子类对象的时候使用了对象的转型,因此在此进行详细说明

对象的转型分为向上转型和向下转型 。

 父类引用指向子类对象,我们称之为向上转型,属于自动类型转换。而向上转型后的父类引用变量只能调用它编译类型的方法,不能调用它运行时候类型的方法。这时候,我们就需要进行类型的强制转换,我们称之为向下转型

//其余代码与多态一致,另外假设在Dog类里面有个seeDoor方法,Cat类里面有个catchMouse方法。

Animal a=new Dog();//向上类型转换,自动的。
//a.seeDoor();//这个就会报错,无法调用,编译器只会认为你是Animal类,而不是Dog类。

Dog d2=(Dog) a;//强制类型转换,向下类型转型,把a这个Animal类型转换为Dog类型的d2使用。
d2.seeDoor();//可以运行。d2是Dog类。

//只有父类转为子类可以进行向下类型转换!!!
Cat c3=(Cat) a;//通过编译,但是不能运行,因为a是Dog类不能被强行转为Cat,真实的子类类型是Dog
c3.catchMouse();

4.3 父类引用指向子类对象的意义 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值