文章目录
深入面向对象
访问权限控制
public/private/protected/(不写)
包
用文件夹对代码进行管理
•Java 使用包这种机制是为了防止命名冲突,访问控制,提供搜索和定位类、接口、枚举和注解等,它把不同的 java 程序分类保存,更方便的被其他 java 程序调用。
命名规则
- 小写
- 公司域名反写
package
使用package将源代码放入包中
package com.etcxm.www;
import
使用import导入其他包中的类
//import com.etcxm.www.entity.Bike; //类的引用
import com.etcxm.www.entity.*; //包下所有类的引用,*代表所有
javac -d
使用javac -d命令行,对java源程序进行编译
类的访问控制符
- default(不写):在同包中可用
- public(公用):在项目中都可用
成员访问控制符
- 成员变量
- 方法
public、private、protected、default(不写)
同一个类中 | 同一个包中 | 不同包子类 | 不同包非子类 | |
---|---|---|---|---|
private | √ | |||
default | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
封装
package com.etcxm.www;
//封装小例子
public class MaMa {
private String apple="Apple";
private String water="Water";
public String eat() {
return water+" "+apple;
}
public static void main(String[] args) {
System.out.println(new MaMa().eat());
}
}
封装是将对象的信息隐藏在对象内部,禁止外部程序直接访问对象内部的属性和方法,java封装类通过三个步骤实现:
-
修改属性的可见性,限制访问权限
-
设置属性的读取方法
-
在读取属性的方法中,添加对属性读取的限制
继承
实现继承
儿子继承了父亲的遗产,遗产可以重用。
面向,继承了一个类,那么就可以使用被继承类的所有可访问的属性和方法。
继承是为了在原有类的基础上创建新的类,继承原有类的功能。
- extends
- 基类(父类)-派生类(子类)
- 单根继承
- 子类可以使用父类的属性和方法(权限问题)
- 子类可以拥有自己新的方法
- 子类可以改写父类的方法 override
Human(父类)
package com.etcxm.www;
public class Human {
private String name;
private String sex;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void say() {
System.out.println("人类正在说话!");
}
}
Husband(子类)
package com.etcxm.www;
public class Husband extends Human {
public void showAge() {
System.out.println(getAge());
}
public static void main(String[] args) {
Husband husband = new Husband();
husband.setName("武大郎");
husband.setAge(40);
husband.setSex("男");
husband.showAge();
husband.say();
}
public void playTableTennis() {
System.out.println("善于打乒乓球!");
}
@Override //重写注解,这个注解会对父类进行一个方法校验,校验这个方法在父类中是否存在
public void say() {
// super.say();
System.out.println("丈夫正在说话!");
}
}
Wife
package com.etcxm.www;
public class Wife extends Human{
public void showSex() {
System.out.println(getSex());
}
}
多根引用
package com.etcxm.www;
public class Son { //Java只支持单根继承
private Father father;
private Mother mother;
public Son(Father father,Mother mother) {
this.father=father;
this.mother=mother;
}
public static void main(String[] args) {
Son son = new Son(new Father(), new Mother());
son.father.fight();
son.mother.sing();
}
}
is-a -> use a
Object
Java中所有的类都是从根Object()继承而来。
构造方法无法继承
构造方法无法继承,在构造子类之前,一定会先构造父类,如果父类构造失败,那么子类也不能构造。
如果父类没有默认的空的构造方法的时候,应该使用super来指定使用哪个父类构造方法
super
指代父类
- 指代父类的属性 super.name
- 指代父类的方法 super.say()
- 指代父类的构造方法 super()
执行顺序
- 父类初始化构造方法(static)——只做1次
- 子类初始化构造方法(static)——只做1次
- 父类实例构造方法({})
- 父类构造方法
- 子类实例构造方法
- 子类构造方法
3.4.5.6——重复n次
多态
不同的类对同一个消息作出响应
F1->word/excel/eclipse
USB->keyboard/mouse/ssd
向上造型
父类引用 = 子类实例
Object o=new String();
编译期类型、运行期类型
Bird bird=new Ostrich();
- Bird:编译期类型
- Ostrich:运行期类型
静态绑定、动态绑定
- 静态绑定(不能实现多态)
- 成员变量
- final、static、private、构造方法
- 动态绑定:所有其他方法(实现多态)
instanceof
if(bird instanceof Penguin) {
System.out.println("bird是一只企鹅");
Penguin penguin=(Penguin)bird;
System.out.println(penguin.getPenguin());
}else if(bird instanceof Ostrich) {
System.out.println("bird是一只鸵鸟");
}
用来检测是否是某个类的实例
习题:
- 要求编写程序如下:
- 提示用户输入1(早上)2(下午)3(晚上)
- 根据用户的输入,实现good morning、good afternoon、good night。
- 要求采用多态、简单工厂模式。
抽象类(abstract)
- 抽象方法:只有定义没有实现的方法。
- 抽象类:包含抽象方法的类就叫做抽象类。
- 抽象类中可以包含成员变量(属性)和具体方法
- 抽象类中final,static,构造方法都不能被抽象。
- 子类如果继承了抽象类,那么一定要实现里面的抽象方法。
Lock
package com.etcxm.www;
/*
* 抽象类Lock(锁)
*/
public abstract class Lock {
public abstract void open(); //开锁
public abstract void lock(); //锁
}
LockKey
package com.etcxm.www;
public class LockKey extends Lock{
@Override
public void open() {
System.out.println("使用钥匙开了锁");
}
@Override
public void lock() {
System.out.println("使用钥匙挂了门");
}
}
LockPassword
package com.etcxm.www;
public class LockPassword extends Lock{
@Override
public void open() {
System.out.println("使用密码开了锁");
}
@Override
public void lock() {
System.out.println("使用密码关了门");
}
}
LockFactory(本例使用了简单工厂模式)
package com.etcxm.www;
public class LockFactory {
public static Lock getLock(int i) {
Lock lock=null;
switch (i) {
case 1:
lock = new LockKey();
break;
case 2:
lock = new LockPassword();
break;
default:
break;
}
return lock;
}
}
LockMain
package com.etcxm.www;
import java.util.Scanner;
public class LockMain {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请使用门禁开门,1(钥匙)2(密码)");
int i = scanner.nextInt();
Lock lock = LockFactory.getLock(i);
lock.open();
}
}
final
变量
该变量不能再被赋值
方法
该方法不能再被重写
类
该类无法被继承
package com.etcxm.www;
public final class FinalDemo {
public final int i=0; //不可修改
public final int getInt() { //不允许被重写override
return i;
}
public final int getInt(int i) { //允许重载
return i+1;
}
public static void main(String[] args) {
FinalDemo finalDemo = new FinalDemo();
// finalDemo.i=5;
}
}
//不能被继承
//class FinalDemoSon extends FinalDemo{
//不能被重写
// public final int getInt() {
// return i;
// }
//}
static
静态:针对同一个类的共性的属性和方法,我们称为static静态的。
static静态的属性我们存储于方法区中,并不会放在堆中。
package com.etcxm.www;
import static java.lang.Math.abs; //静态引用,可以省略类的名字。
public class StaticDemo {
public static String type = "类人猿科"; // 静态的成员变量。存在方法区
public static String getType() { // 静态的方法。
// this.i; //this指实例后的自己,static的时候还没有实例,所以不能使用this。
int i1=0;
abs(1.0d); //绝对值
return type;
}
public int i; //实例变量,不能使用在static方法中
public static final String APP_NAME = "Static小例子"; // 常量,命名全大写,蛇形,也常用来替代enum
public static final int ORDER_CONFIRM = 0; //已下单
public static final int ORDER_SEND = 1; //已发货
public String getString2() { //成员方法,必须实例才能调用
return getType(); //可以直接调用static的方法和变量。
}
public static void main(String[] args) {
/*
* 调用static的成员变量和方法 1. 类名.静态方法/静态变量
*/
System.out.println(StaticDemo.type);
System.out.println(StaticDemo.getType());
// 实例
StaticDemo staticDemo = new StaticDemo();
/*
* 2. 实例名.静态方法/静态的变量
*/
System.out.println(staticDemo.type);
System.out.println(staticDemo.getType());
}
}
接口(interface)
- 接口可以多重实现
- 子类实现了接口,就必须完成接口中定义的方法
public interface 接口名称{
//静态的公开的常量定义
public static final String APP_NAME="interface demo";
...
//接口方法定义
public void move(){
}
}
和抽象类的区别
abstract class | interface | |
---|---|---|
属性 | 无限制 | public 静态常量 |
构造方法 | 可有可无 | 没有 |
方法 | 可以有具体方法 | 只有公开的方法定义 |
继承 | 单一继承 | 多重实现 |
implements
[public] class 类名 extends 父类名 implements 接口1,接口2,接口3...{
}
接口继承
接口可以实现多重继承
package com.etcxm.www;
//接口可以实现多重继承
public interface ITank extends Move,Fire{
}
接口的默认方法
JDK8开始,给接口加了一个默认方法,方便接口的升级。
以前的类,如果使用了新的接口,不会发生错误,会自动调用接口的默认方法。
public default
package com.etcxm.www;
//接口可以实现多重继承
public interface ITank extends Move,Fire{
public default void addOil() {
System.out.println("使用默认的方法进行加油!");
}
}
枚举
用来表示特定领域的状态值
package com.etcxm.www;
public interface Entity {
public static final int VEDIO = 1;
public static final int AUDIO = 2;
public static final int TEXT = 3;
public static final int IMAGE = 4;
}
package com.etcxm.www;
public class GoWest implements Entity{
private int type = VEDIO;
}
- 可读性差,易用性差
- 可扩展性差
- 不安全
枚举定义
public enum Type{
VIDEO,AUDIO,TEXT,IMAGE
}
使用switch
package com.etcxm.www;
public class GoWest implements Entity {
private TypeEnum type = TypeEnum.VIDEO;
public void test() {
System.out.println(type);
switch (type) {
case VIDEO:
System.out.println("西游记是一个电视剧");
break;
case AUDIO:
System.out.println("西游记是一段广播剧");
break;
case TEXT:
System.out.println("西游记是一本小说");
break;
case IMAGE:
System.out.println("西游记是一本漫画");
break;
default:
break;
}
}
public static void main(String[] args) {
new GoWest().test();
}
}
依赖和关联关系
package com.etcxm.www;
//关联 use-a
//依赖 has-a
public class Person {
DrivingLicense drivingLicense; // 一对一的关联关系
CertificatorOfHonor[] certificatorOfHonors; // 一对多的关联关系
House myHouse; // 聚合的关联关系
Heart myHeart; // 组合的关联关系
public void breath(Air air) { //依赖 use-air
}
}
class DrivingLicense { // 驾照
Person person;
}
class CertificatorOfHonor { // 荣誉证书
}
class House { //房子
}
class Heart { //心脏
}
class Air{ //空气
}
依赖<关联<聚合<组合
内部类
在一个类的内部定义一个类