文章目录
- 访问修饰符
- 面向对象的三大特征
- 封装
- 继承
- 多态
- 多态的成员访问的特点
- 多态的好处和弊端
- 多态中的转型
访问修饰符
类型 | 权限 |
public | 在任何人地方都可以正常访问 |
protected | 同包,同类,子类 |
默认(缺省)|不写 | 同包,同类 |
private | 同类 |
注意:protected、private不能修饰类
面向对象的三大特征
封装
封装(Encapsulation)指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。
从广义上来说,封装就是将物品,保管起来、封存起来
面向对象上说的封装,是一种特指:
将类的属性私有化(不再为外界提供直接访问属性的方式),提供对应的getter和setter方法来访问和设置属性
For example
封装的目的:数据的安全性和私密性
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();
}
}