Java 面向对象

面向对象java

面向对象方法是一种运用对象, 类, 封装, 继承, 多态和消息等概念来构造, 测试, 重构软件的方法 面向对象方法的主要优势是符合人们一般的思惟方式从分析到设计再到编码采用一致的模型表示 具备高度连续性软件重用性好设计模式

过程和对象在程序中的体现: 过程其实就是函数 对象是将函数等一些内容进行了封装数组

1. 面向对象的特色安全

1> 封装jvm

2> 继承函数

3> 多态 测试

2. 匿名对象使用场景this

1> 当对方法只进行一次调用的时候 可使用匿名对象编码

2> 当对象对成员进行屡次调用时 不能使用匿名对象 必须给对象起名字spa

3. 在类中定义都称之为成员 成员有两种

1> 成员变量 其实对应的就是事物的属性

2> 成员函数 其实对应的就是事物的行为

因此 其实定义类 就是在定义成员变量和成员函数 可是在定义前 必须先要对事物进行属性和行为的分析 才能够用代码来体现

4. private 修饰符

私有的 访问权限最低 只有在本类中的访问有效

注意: 私有仅仅是封装的一种体现形式而已

5. 私有的成员

其余类不能直接建立对象访问 因此只有经过本类对外提供具体的访问方式来完成对私有的访问 能够经过对外提供函数的形式对其进行访问

好处: 能够在函数中加入逻辑判断等操做 对数据进行判断等操做

6. 总结

属性是用于存储数据的 直接被访问 容易出现安全隐患 因此 类中的属性一般被私有化 并对外提供公共的访问方法

这个方法通常有两个 规范写法: 对于属性 age, 可使用setAge() getAge()对其进行操做

7. 类中怎么没有定义主函数?

注意: 主函数的存在 仅为该类是否须要独立运行 若是不须要 主函数是不用定义的

主函数的解释: 保证所在类的独立运行 是程序的入口 jvm调用

8. 成员变量和局部变量的区别

1> 成员变量直接定义在类中, 局部变量定义在方法中 参数上 语句中 

2> 成员变量在这个类中有效, 局部变量只在本身所属的大括号内有效 大括号结束 局部变量失去做用域

3> 成员变量存在于堆内存中 随着对象的产生而存在 消失而消失, 局部变量存在于栈内存中 随着所属区域的运行而存在 结束而释放 

9. 构造函数

1> 用于给对象进行初始化 是给与之对应的对象进行初始化 它具备针对性 函数中的一种

分析事物时 发现具体事物一出现 就具有了一些特征 那就将这些特征定义到构造函数内

2> 特色

a. 该函数的名称和所在类的名称相同

b. 不须要定义返回值类型

c. 该函数没有具体的返回值 

3> 注意

a. 全部对象建立时 都须要初始化才可使用

b. 一个类在定义时 若是没有定义过构造函数 那么该类中会自动生成一个空参数的构造函数 若是在类中自定义了构造函数 那么默认的构造函数就没有了

c. 一个类中 能够有多个构造函数 由于它们的函数名称都相同 因此只能经过参数列表来区分 因此 一个类中若是出现多个构造函数 它们的存在是以重载体现的

10. 构造函数和通常函数的区别

1> 两个函数定义格式不一样

2> 构造函数是在对象建立时 就被调用 用于初始化 并且初始化动做只执行一次, 通常函数 是对象建立后 须要调用才执行 能够被调用屡次

11. 构造代码块和构造函数的区别

构造代码块: 是给全部的对象进行初始化 也就是说 全部的对象都会调用一个代码块 只要对象一创建 就会调用这个代码块

构造函数: 是给与之对应的对象进行初始化 它具备针对性

12. 建立一个对象时的内存变化 (Person p = new Person();)

1> 先将硬盘上指定位置的Person.class文件加载进内存 

2> 执行main方法时 在栈内存中开辟了main方法的空间(压栈-进栈) 而后在main方法的栈区分配了一个变量p

3> 在堆内存中开辟一个实体空间 分配了一个内存首地址值 ---> new

4> 在该实体空间中进行属性的空间分配 并进行了默认初始化

5> 对空间中的属性进行显示初始化

6> 进行实体的构造代码块初始化

7> 调用该实体对应的构造函数 进行构造函数初始化 ---> ()

8> 将首地址赋值给p p变量就引用了该实体 ---> (指向了该对象)

 

封装(面向对象特征之一)

是指隐藏对象的属性和实现细节 仅对外提供公共访问方式

好处: 将变化隔离 便于使用 提升重用性 安全性

封装原则: 将不须要对外提供的内容都隐藏起来 把属性都隐藏 提供公共方法对其访问

1. this

1> 表明对象 就是所在函数所属对象的引用

2> 哪一个对象调用了this所在的函数 this就表明哪一个对象 就是哪一个对象的引用

3> 在定义功能时 若是该功能内部使用到了调用该功能的对象 这时就用this来表示这个对象

4> this 还能够用于构造函数间的调用

调用格式: this(实际参数);

this对象后面跟上 . 调用的是成员属性和成员方法(通常方法)

this对象后面跟上 () 调用的是本类中的对应参数的构造函数

注意: this调用构造函数 必须定义在构造函数的第一行 由于构造函数是用于初始化的 因此初始化动做必定要执行 不然编译失败

2. static

关键字 是一个修饰符 用于修饰成员(成员变量和成员函数)

1> 特色

a. 想要实现对象中的共性数据的对象共享 能够将这个数据进行静态修饰

b. 被静态修饰的成员 能够直接被类名所调用 也就是说 静态的成员多了一种调用方式 类名.静态方式

c. 静态随着类的加载而加载 并且优先于对象存在 

2> 弊端

a. 有些数据是对象特有的数据 是不能够被静态修饰的 由于 特有数据会变成对象的共享数据 这样对事物的描述就出了问题 因此 在定义静态时 必需要明确 这个数据是不是被对象所共享的

b. 静态方法只能访问静态成员 不能够访问非静态成员 由于静态方法加载时 优先于对象存在 因此没有办法访问对象中的成员

c. 静态方法中不能使用this super关键字 由于this表明对象 而静态在时 有可能没有对象 因此this没法使用

d. 主函数是静态的 

3. 何时定义静态成员?

1> 成员变量 (数据共享时静态化)

该成员变量的数据是不是全部对象都同样

若是是 那么该变量须要被静态修饰 由于是共享的数据

若是不是 那么就说这是对象的特有数据 要存储到对象中

2> 成员函数 (方法中没有调用特有数据时就定义成静态)

若是判断成员函数是否须要被静态修饰呢?

只要参考 该函数内是否访问了对象中的特有数据

若是有访问特有数据 那方法不能被静态修饰

若是没有访问过特有数据 那么这个方法须要被静态修饰

4. 成员变量和静态变量的区别

1> 成员变量所属于对象 因此也称为实例变量

静态变量所属于类 因此也称为类变量

2> 成员变量存在于堆内存中

静态变量存在于方法区中

3> 成员变量随着对象建立而存在 随着对象被回收而消失

静态变量随着类的加载而存在 随着类的消失而消失

4> 成员变量只能被对象所调用

静态变量能够被对象调用 也能够被类名调用

因此 成员变量能够称为对象的特有数据 静态变量称为对象的共享数据 

5. 静态的注意

静态的生命周期很长

6. 静态代码块

就是一个有静态关键字标示的一个代码块区域 定义在类中

做用: 能够完成类的初始化 静态代码块随着类的加载而执行 并且只执行一次(new 多个对象就只执行一次) 若是和主函数在同一类中 优先于主函数执行

7. 主函数分析

public: 访问权限最大

static: 不须要对象 直接类名便可

void: 主函数没有返回值

main: 主函数特定的名称

(String[] args): 主函数的参数 是一个字符串数组类型的参数 jvm调用main方法时 传递的实际参数是 new String[0]

jvm默认传递的是长度为0的字符串数组 咱们在运行该类时 也能够指定具体的参数进行传递 能够在控制台 运行该类时 在后面加入参数 参数之间经过空格隔开 jvm会自动将这些字符串参数做为args数组中的元素 进行存储

8. 静态代码块 构造代码块 构造函数同时存在时的执行顺序

静态代码块 ---> 构造代码块 ---> 构造函数

9. 生成Java帮助文档

命令格式: javadoc –d 文件夹名 –auther –version *.java

/**

 类描述

 @author 做者名

 @version 版本号

 */

/**

 方法描述

 @param 参数描述

 @return 返回值描述

 */

10. 设计模式

java中有23种设计模式

解决问题最行之有效的思想 是一套被反复使用, 多数人知晓的, 通过分类编目的, 代码设计经验的总结 使用设计模式是为了可重用代码 让代码更容易被他人理解 保证代码可靠性

11. 单例设计模式

解决的问题: 保证一个类在内存中的对象惟一性

Runtime()方法就是单例设计模式进行设计的 

1> 思想

a. 不让其余程序建立该类对象

b. 在本类中建立一个本类对象

c. 对外提供方法 让其余程序获取这个对象

2> 步骤

a. 由于建立对象都须要构造函数初始化 只要将本类中的构造函数私有化 其余程序就没法再建立该类对象

b. 就在类中建立一个本类的对象

c. 定义一个方法 返回该对象 让其余程序能够经过方法就获得本类对象 (做用: 可控)

3> 代码体现

a. 私有化构造函数

b. 建立私有并静态的本类对象

c. 定义公有并静态的方法 返回该对象

4> 饿汉式

class Single {
    private Single() {} //私有化构造函数
    private static Single s = new Single(); //建立私有并静态的本类对象
    public static Single getInstance() { //定义公有并静态的方法 返回该对象
        return s;
    }
} 

5> 懒汉式 延迟加载方法

class Single2 {
    private Single2() {}
    private static Single2 s;
    public static synchronized Single2 getInstance() {
        if(s==null)
            s = new Single2();
        return s;
    }
} 

6> 第三种格式

class Single {
    private Single() {}
    public static final Single s = new Single(); //final是最终的意思 被final修饰的变量不能够被更改
}

 

继承(面向对象特征之一)

Java只支持单继承 不支持多继承 可是Java支持多重继承

单继承: 一个类只能有一个父类

多继承: 一个类能够有多个父类

多重继承: A继承B B继承C C继承D

1. 好处

1> 提升了代码的复用性

2> 让类与类之间产生了关系 提供了另外一个特征多态的前提

2. 父类的由来

实际上是由多个类不断向上抽取共性内容而来的

java中对于继承 java只支持单继承 java虽然不直接支持多继承 可是保留了这种多继承机制 进行改良

3. 子父类出现后 类中成员的特色

1> 成员变量

当子父类中出现同样的属性时 子类类型的对象 调用该属性 值是子类的属性值

若是想要调用父类中的属性值 须要使用一个关键字 super

this: 表明是本类类型的对象引用

super: 表明是子类所属的父类中的内存空间引用

注意: 子父类中一般是不会出现同名成员变量的 由于父类中只要定义了 子类就不用在定义了 直接继承过来用就能够了

2> 成员函数

当子父类中出现了如出一辙的方法时 创建子类对象会运行子类中的方法 好像父类中的方法被覆盖掉同样 这种状况 是函数的另外一个特性: 覆盖(复写 重写)

当一个类的功能内容须要修改时 能够经过覆盖来实现

3> 构造函数

发现子类构造函数运行时 先运行了父类的构造函数

缘由: 子类的全部构造函数中的第一行 其实都有一条隐身的语句super();

super(); 表示父类的构造函数 并会调用于参数相对应的父类中的构造函数 super();是在调用父类中空参数的构造函数

为何子类对象初始化时 都须要调用父类中的函数? (为何要在子类构造函数的第一行加入这个super();)

由于子类继承父类 会继承到父类中的数据 因此必需要看父类是如何对本身的数据进行初始化的 因此子类在进行对象初始化时 先调用父类的构造函数 这就是子类的实例化过程

4> 注意

a. 子类中全部的构造函数都会默认访问父类中的空参数的构造函数 由于每个子类构造内第一行都有默认的语句super();

若是父类中没有空参数的构造函数 那么子类的构造函数内 必须经过super语句指定要访问的父类中的构造函数

若是子类构造函数中用this来指定调用子类本身的构造函数 那么被调用的构造函数也同样会访问父类中的构造函数

b. super(); this(); 两个语句只能有一个定义在第一行 因此只能出现其中一个

c. super(); 或者 this(); 必定要定义在第一行 由于super();或者this();都是调用构造函数 构造函数用于初始化 因此初始化的动做要先完成 

4. 继承的细节

1> 何时使用继承呢?

当类与类之间存在着所属关系时 才具有了继承的前提 ab中的一种 a继承b 狼是犬科中的一种

英文书中 所属关系: " is a "

注意: 不要仅仅为了获取其余类中的已有成员进行继承

因此判断所属关系 能够简单看 若是继承后 被继承的类中的功能 均可以被该子类所具有 那么继承成立 若是不是 不能够继承

2> 在方法覆盖时 注意两点

a. 子类覆盖父类时 必需要保证 子类方法的权限必须大于等于父类方法权限能够实现继承 不然 编译失败

b. 覆盖时 要么都静态 要么都不静态 (静态只能覆盖静态 或者被静态覆盖)

继承的一个弊端: 打破了封装性 对于一些类 或者类中功能 是须要被继承 或者复写的

可使用关键字 final(最终) 解决这个问题

5. final

1> 这个关键字是一个修饰符 能够修饰类, 方法, 变量

2> final修饰的类是一个最终类 不能够被继承

3> final修饰的方法是一个最终方法 不能够被覆盖

4> final修饰的变量是一个常量 只能赋值一次

不加final修饰也可使用 那么这个值是一个变量 是能够更改的, 加了final 程序更为严谨 常量名称定义时 有规范 全部字母都大写 若是由多个单词组成 中间用 _ 链接 

6. 抽象类 abstract

抽象: 不具体 看不明白 抽象类表象体现

在不断抽取过程当中 将共性内容中的方法声明抽取 可是方法不同 没有抽取 这时抽取到的方法 并不具体 须要被指定关键字abstract所标示 声明为抽象方法

抽象方法所在类必定要标示为抽象类 也就是说该类须要被abstract关键字所修饰

1> 抽象类的特色

a. 抽象方法只能定义在抽象类中 抽象类和抽象方法必须由abstract关键字修饰(能够描述类和方法 不能够描述变量)

b. 抽象方法只定义方法声明 并不定义方法实现

c. 抽象类不能够被建立对象(实例化)

d. 只有经过子类继承抽象类并覆盖了抽象类中的全部抽象方法后 该子类才能够实例化 不然 该子类仍是一个抽象类

2> 抽象类的细节

a. 抽象类中有构造函数 用于给子类对象进行初始化

b. 抽象类中能够定义非抽象方法 抽象类和通常类没有太大的区别 都是在描述事物

c. 抽象关键字abstract final, private, static 不能够共存

d. 抽象类中能够不定义抽象方法 抽象方法目的仅仅为了避免让该类建立对象

3> 模板方法设计模式

解决的问题: 当功能内部一部分实现时肯定 一部分实现是不肯定的 这时能够把不肯定的部分暴露出去 让子类去实现

abstract class GetTime {
    public final void getTime() { //此功能若是不须要复写 可加final限定
        long start = System.currentTimeMillis();
        code(); //不肯定的功能部分 提取出来 经过抽象方法实现
        long end = System.currentTimeMillis();
        System.out.println("毫秒是:"+(end-start));
    }
    public abstract void code(); //抽象不肯定的功能 让子类复写实现
}

class SubDemo extends GetTime {
    public void code() { //子类复写功能方法
        for(int y=0; y<1000; y++) {
            System.out.println("y");
        }
    }
}

7. 接口 interface

1> 是用关键字interface定义的

2> 接口中包含的成员 最多见的有全局常量, 抽象方法

注意: 接口中的成员都有固定的修饰符

成员变量: public static final

成员方法: public abstract

interface Inter{

    public static final int x = 3;

    public abstract void show();

}

3> 接口中有抽象方法 说明接口不能够实例化 接口的子类必须实现了接口中全部的抽象方法后 该子类才能够实例化 不然 该子类仍是一个抽象类

4> 类与类之间存在着继承关系 类与接口中间存在的是实现关系 继承用extends 实现用implements

5> 接口和类不同的地方 就是 接口能够被多实现 这就是多继承改良后的结果 java将多继承机制经过多现实来体现

6> 一个类在继承另外一个类的同时 还能够实现多个接口 因此接口的出现避免了单继承的局限性 还能够将类进行功能的扩展

7> 其实java中是有多继承的 接口与接口之间存在着继承关系 接口能够多继承接口

8> 接口都用于设计上 设计上的特色 (能够理解主板上提供的接口)

a. 接口是对外提供的规则

b. 接口是功能的扩展

c. 接口的出现下降了耦合性

8. 抽象类和接口

抽象类: 通常用于描述一个体系单元 将一组共性内容进行抽取 特色: 能够在类中定义抽象内容让子类实现 能够定义非抽象内容让子类直接使用 它里面定义的都是一些体系中的基本内容

接口: 通常用于定义对象的扩展功能 是在继承以外还需这个对象具有的一些功能

抽象类和接口的共性: 都是不断向上抽取的结果

抽象类和接口的区别:

1> 抽象类只能被继承 并且只能单继承

接口须要被实现 并且能够多实现

2> 抽象类中能够定义非抽象方法 子类能够直接继承使用

接口中都有抽象方法 须要子类去实现

3> 抽象类使用的是 is a 关系

接口使用的 like a 关系

4> 抽象类的成员修饰符能够自定义

接口中的成员修饰符是固定的 全都是public

 

多态(面向对象特征之一)

函数自己就具有多态性 某一种事物有不一样的具体的体现 

1. 体现

父类引用或者接口的引用指向了本身的子类对象 

2. 多态的好处

提升了程序的扩展性

3. 多态的弊端

当父类引用指向子类对象时 虽然提升了扩展性 可是只能访问父类中具有的方法 不能够访问子类中特有的方法 (前期不能使用后期产生的功能 即访问的局限性)

4. 多态的前提

1> 必需要有关系 好比继承 或者实现

2> 一般会有覆盖操做 

5. 多态的出现 思想上的变化

之前是建立对象并指挥对象作事情 有了多态之后 咱们能够找到对象的共性类型 直接操做共性类型作事情便可 这样能够指挥一批对象作事情 即经过操做父类或接口实现

class 黄大仙 {
    void 讲课() {
        System.out.println("企业管理");
    }
    void 钓鱼() {
        System.out.println("钓鱼");
    }
}
 
class 黄祎a extends 黄大仙 {
    void 讲课() {
        System.out.println("岛国文化");
    }
    void 看电影() {
        System.out.println("看电影");
    }
}

class {
    public static void main(String[] args) {
        黄大仙 x = new 黄祎a(); //黄祎a对象被提高为了黄大仙类型
        //x.讲课(); //岛国文化
        //x.看电影(); //错误
        黄祎a y = (黄祎a)x; //将黄大仙类型强制转换成黄祎a类型
        y.看电影(); //在多态中 自始自终都是子类对象在作着类型的变化
    }
}

若是想用子类对象的特有方法 如何判断对象是哪一个具体的子类类型呢?

能够能够经过一个关键字 instanceof //判断对象是否实现了指定的接口或继承了指定的类

格式: <对象 instanceof 类型> 判断一个对象是否所属于指定的类型

Student instanceof Person = true; //student继承了person 

6. 多态在子父类中的成员上的体现的特色

1> 成员变量: 在多态中 子父类成员变量同名

在编译时期: 参考的是引用型变量所属的类中是否有调用的成员 (编译时不产生对象 只检查语法错误)

运行时期: 也是参考引用型变量所属的类中是否有调用的成员

简单一句话: 不管编译和运行 成员变量参考的都是引用变量所属的类中的成员变量

更简单: 成员变量 --- 编译运行都看 = 左边

2> 成员函数

编译时期: 参考引用型变量所属的类中是否有调用的方法

运行事情: 参考的是对象所属的类中是否有调用的方法

由于在子父类中 对于如出一辙的成员函数 有一个特性: 覆盖

简单一句: 成员函数 编译看引用型变量所属的类 运行看对象所属的类

更简单: 成员函数 --- 编译看 = 左边, 运行看 = 右边

3> 静态函数

编译时期: 参考的是引用型变量所属的类中是否有调用的成员

运行时期: 也是参考引用型变量所属的类中是否有调用的成员

由于静态方法 其实不所属于对象 而是所属于该方法所在的类

简单一句: 调用静态的方法引用是哪一个类的引用调用的就是哪一个类中的静态方法

更简单: 静态函数 --- 编译运行都看 = 左边

相关文章
相关标签/搜索