文章目录

  • 访问修饰符
  • 面向对象的三大特征
  • 封装
  • 继承
  • 多态
  • 多态的成员访问的特点
  • 多态的好处和弊端
  • 多态中的转型


访问修饰符

类型

权限

public

在任何人地方都可以正常访问

protected

同包,同类,子类

默认(缺省)|不写

同包,同类

private

同类

注意:protected、private不能修饰类

面向对象的三大特征

封装

封装(Encapsulation)指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。

从广义上来说,封装就是将物品,保管起来、封存起来

面向对象上说的封装,是一种特指:

将类的属性私有化(不再为外界提供直接访问属性的方式),提供对应的getter和setter方法来访问和设置属性

For example

java 如何使用prod java prompt_多态


封装的目的:数据的安全性和私密性

1、隐藏类的实现细节;
2、让使用者只能通过事先预定的方法来访问数据,从而可以在该方法里加入控制逻辑,限制对成员变量的不合理访问;
3、便于修改,提高代码的可维护性。


POJO(Plain Ordinary Java Object):经典java类

POJO有一些private的参数作为对象的属性。然后针对每个参数定义了get和set方法作为访问的接口

For example

public class User {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

toString方法

在JDk中提供一个Object类,它是所有类的父类,即每个类都直接或间接的继承自该类

......截取JDK中Object类的同String方法

public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }  
......

1)getClass().getName() 代表返回对象所属类的包名.类名com.openlab.day011.User 2)@对应@;
3)Integer.toHexString(hashCode())代表将对象的哈希值用16进制表示,其中hashCode()代表返回该对象的哈希值。

For example

public static void main(String[] args) {
        User us1 = new User();
		// 对象直接调用toString()方法
        System.out.println(us1.toString());
        // 输出:com.openlab.day011.User@7c30a502
    }

继承

java中,如果一个类,继承了另一个类,则把这种现象叫做继承,此时这个类就会继承父类(被继承的类)中的能够被继承的类成员(重点方法)

在java,如果有继承存在,被继承的类,叫做父类(超类、基类),继承的类,叫做子类(派生类)

java使用extend关键字实现继承


子类能够继承的父类中的属性或者方法

子类会继承父类中的东西

  • 如果父类和子类在同包中,只要不是private修饰的都能继承
  • 如果父类和子类在不同包中,只能继承public、protected修饰的

继承到底是干什么的?

继承的出现提高了代码的复用性,提高软件开发效率。

继承的出现让类与类之间产生了关系,提供了多态的前提。


覆盖(override) | 重写 (overwrite)

当一个子类继承父类后,发现某个方法没法满足自己使用的时候,重写(覆盖)该方法,实现能够满足自己使用的方法

在java中,重写父类方法,直接在子类中定义相同名称的方法即可

从jdk1.5开始,引入@Override这个注解

For example

===User.java
package com.openlab.day011.extend;

public class User {
    public void say() {
        System.out.println("hello");
    }
}
===

===TestUser.java
package com.openlab.day011.extend;

public class TestUser extends User {
	// 重写父类方法
    @Override
    public void say() {
        System.out.println("你好");
    }

    public static void main(String[] args) {
        TestUser us1 = new TestUser();
        us1.say();
    }
}
---
输出:你好
===

Annotation(注解),jdk5.0引入的新特性

super关键字

super作为函数调用时,代表父类的构造函数

super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类

继承链

Java典型单继承机制。一个类只能有一个父类!!!

Java类,存在一个根类(root class),object类!

instanceof 关键字

用来判断对象是否是某个类的实例

===Animal.java
package com.openlab.day011.extend;

public class Animal {

    public void  say() {
        System.out.println("我是一个动物,我也不知道我怎么叫");
    }
}
===

===Dog.java
package com.openlab.day011.extend;

public class Dog extends Animal {
    public static void main(String[] args) {
        Dog dog1 = new Dog();
        // instanceof 用来判断对象是否是某个类的实例
        System.out.println(dog1 instanceof Dog);
    }
}
===
输出:true
===

final关键字

final修饰变量,该变量就会称为常量,不能够再被修改(runtime)

final可以修饰类,一但final修饰类,该类就是最终类,不允许再被继承

final可以修饰方法,该方法为最终方法,该方法不允许重写(overrride),但可以被子类继承

面试题:

为什么String类会涉及为final修饰

  • 因为String类的不可变性,才能使得JVM可以实现字符串常量池;字符串常量池可以在程序运行时节约很多内存空间,因为不同的字符串变量指向相同的字面量时,都是指向字符串常量池中的同一个对象。这样一方面能够节约内存,另一方面也提升了性能。
  • 因为String类的不可变性,从而保证了字符串对象在多线程环境下是线程安全的。如果String类是可变的,那么会引起很严重的安全问题。我们在很多情况下都是直接通过字符串传递数据,比如数据库的用户名密码、网络编程中的ip和端口,因为字符串是不可变的,所以它的值不能被修改,如果字符串是可变的,那么可以通过改变引用地址指向的值去修改字符串的值,从而导致安全漏洞

多态

同一个对象在不同时刻表现出来的不同状态

举 :猫
猫是猫: 猫 cat = new 猫();
猫是动物: 动物 cat = new 猫();
猫在不同时刻体现出来了不同状态,这个就是多态

多态的前提和体现
1.有继承/实现关系
2.有方法重写
3.有父类引用指向子类对象

For example

定义三个类
Animal
Cat
AnimalDemo	// 测试类
package com.study_01;
public class Animal {
    public void eat() {
        System.out.println("动物吃东西");
    }
}
-----
package com.study_01;
// 多态前提第一步  继承关系
public class cat extends Animal{
    // 第二步  eat()方法重写
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
-----
package com.study_01;
public class AnimalDemo {
    public static void main(String[] args) {
        // 第三步 有父类引用指向子类对象
        Animal a = new cat();
        a.eat(); // 猫吃鱼
    }
}

多态的成员访问的特点

成员变量:编译看左边,执行看左边
成员方法:编译看左边,执行看右边

Question:为什么成员变量和成员方法的访问不一样呢?
因为成员方法有重写,而成员变量没有

For example

定义三个类
Animal
Cat
AnimalDemo	// 测试类
package com.study_02;

public class Animal {
	// 父类的成员变量
    public int age = 40;

    public void eat() {
        System.out.println("动物吃东西");
    }
}
-----
package com.study_02;
// 有继承
public class Cat extends Animal{

    public int age = 20;
    public int weight = 10;
	// 有方法重写
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    public void playGame() {
        System.out.println("猫捉迷藏");
    }
}
-----
package com.study_02;

public class AnimalDemo {

    public static void main(String[] args) {
        // 有父类引用指向子类对象
        Animal a  = new Cat();

        System.out.println(a.age); // 40
        // 成员变量  编译看左边,运行看左边
        // 最终呈现的其实是动物类里面age变量的值
//        System.out.println(a.weight); // 编译看左边,动物类里面并没有weight变量,所以报错

        a.eat(); // 猫吃鱼
        // 成员方法  编译看左边,运行看右边
//        a.playGame;
		// 编译看左边,动物里面没有playGame()方法,该方法时Cat类特有的
    }
}

多态的好处和弊端

好处:提高了程序的扩展性

具体体现:定义方法的时候,使用父类类型作为参数,将来在使用的时候,使用具体的子类型参与操作

弊端:不能使用子类的特有功能

For example

定义五个类
Animal
Cat
Dog
AnimalOperateor  // 操作类
AnimalDemo	// 测试类
package com.study_03;
public class Animal {
    public void eat() {
        System.out.println("动物吃东西");
    }
}
-----
package com.study_03;
// 继承父类
public class Cat extends Animal {
	// 重写父类方法
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
-----
package com.study_03;
public class Dog extends Animal{
	// 重写父类方法
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

    public void lookDoor() {
        System.out.println("狗看门");
    }
}
------
package com.study_03;
/*
    动物操作类
*/
public class AnimalOperator {
   /* 
   // 这样写较为复杂
   public void useAnimal(Cat c) { // Cat c = new Cat();
        c.eat();
    }
    
    public void useAnimal(Dog d) {
        d.eat();
    }*/
	
	// 这样写毕竟好
    public void useAnimal(Animal a) {
        // Animal a = new Cat();
        // Animal a = new Dog();

        a.eat();
        // 不能使用子类的特有功能
//         a.lookDoor();
    }
}
-----
package com.study_03;
public class AnimalDemo {
    public static void main(String[] args) {
        // 创建动物操作类的对象,调用方法
        AnimalOperator ao =new AnimalOperator();
        Cat c = new Cat();
        ao.useAnimal(c);

        Dog d = new Dog();
        ao.useAnimal(d);
    }
}

多态中的转型

向上转型

  • 从子到父
  • 父类引用指向子类对象

向下转型

  • 从父到子
  • 父类引用转为子类对象

For example

定义三个类
Animal
Cat
AnimalDemo	// 测试类
package com.study_04;
public class Animal {
    public void eat() {
        System.out.println("动物吃东西");
    }
}
-----
package com.study_04;
public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    public void playGame() {
        System.out.println("猫捉迷藏");
    }
}
-----
package com.study_04;
public class AnimalDemo {
    public static void main(String[] args) {
        // 多态
        Animal a  = new Cat(); // 向上转型
        a.eat();
//        a.playGame(); // 编译看左边,Animal中没有playGame()这个方法

        /*Cat c = new Cat();
        c.eat();
        c.playGame();*/

        // 向下转型,这样就可以调用Cat类里面特有的方法了
        Cat c = (Cat) a;
        c.eat();
        c.playGame();
    }
}