6.8 static关键字
当我们在设计类的时候 发现多个对象中有共享数据的时候 我们就可以把这个共享的数据 定义为静态的
name age虽然每个对象都有 但是值不一定一样 对象的特有数据->成员变量
country虽然每个对象也都有 但是值一样 对象的共有数据-> 静态变量
也就是说:共有的数据存在于一个特定的空间 静态方法区
那么静态变量是如何定义的呢
成员函数+static=静态函数; 我们当前的成员函数如果不访问任何成员变量的情况下 这个函数就可以定义为静态的,这就意味着 静态函数不能直接调用当前类中的成员变量 无法从静态上下文中引用非静态,原因就是静态的生命周期要长与对象,所以静态是优先于对象存在的,静态也称之为是类的成员,我们可以直接通过类去调用(类.静态成员)
那么为什么主函数是静态的呢?
主函数是程序的入口,优于其它运行
假设主函数是非静态的 那么必须先创建对象 才能调用主函数
怎么去创建对象呢?是不是需要写代码?这段代码咋运行呢?
6.9 类的分类
实体类:
就是为了描述一个事物 Person Point
类中内容基本上都是成员函数/成员变量
也会而存在一个静态成员
工具类
提供一些已经被实现好的功能 向外部供应
所以工具类中基本上全都是静态函数
类.Xxx 类.Xxx() Math Arrays
为啥工具类中都是静态?
1.共有的
2.长时间存在
3.加载一次 后期随便使用
一个道理:
当我们钉一个钉子的时候 找榔头
你是造一个榔头 还是用已存在的榔头?
如果工具类可以被创建对象 是不是就想用的时候去创建
效率较低
主类/测试类
主要用于运行/测试代码
这个类中会有主函数的存在
实体类是可以存在主函数的 但是不推荐
工具类一般不会存在主函数
6.9 对象的内存图解III
1.javac 将Java源代码进行编译 生成字节码文件
2.java 将字节码文件加载进虚拟机中 开始运行程序
字节码具体被加载在方法区里面
方法区可以大致分为 非静态方法区/静态方法区
所有非静态的代码(二进制)内容加载进非静态去
所有静态的代码(二进制)内容加载进静态区
JVM接下来会根据参数(java 字节码文件名(类名)) 去静态区找主函数
将主函数代码加载进虚拟机栈 开始运行
3.后面的和之前一样
6.10 静态变量与成员变量的区别
1.生命周期
成员变量随着对象的创建而创建 随着对象的消亡而消亡
静态变量随着类的加载而创建 随着程序结束而消失
2.调用方式
成员变量必须先创建对象 在通过对象去调用
静态变量可以被对象调用 也可以直接用类调用
3.存储位置
成员变量存在于堆内存中对象的所属空间里
静态变量存在于静态方法区中类的所属空间里
4.命名
成员变量-对象的特有属性
静态变量-对象的共有属性 类成员
6.11 代码块
代码块 { ... }
局部代码块:存在于函数当中(包括函数) for(){...} if(){...}
构造代码块:直接在类中出现的{...}
当对象创建一次 构造代码块执行一次
作用等同于构造函数静态代码块:直接在类中出现的static{...}
当类被加载的时候 仅且只执行一次
作用于 对类进行一些初始化操作 JDBC
6.12 单例模式
设计模式:就是我们的前辈们总结出来的一些编码技巧
它并不是随着Java的诞生而诞生的
它是由Java的广大使用者总结出来的一套编码经验
常见26种单例模式:使用场景是 某一个类只能创建一个对象
比如某一个朝代的皇帝 只能是唯一的
1.既然只能创建一个对象的话 就得不能让外界去创建对象
限制使用new不现实
只能从对象的创建流程中考虑 只要有一个步骤不行 对象就创建不出来
开辟空间分配地址 是由计算机底层决定 我们也控制不了
构造函数执行 只需要将构造函数私有化即可
2.既然外界不能创建对象 我们还得保证对象的创建
所以我们只能在类内部创建对象
Single s=new Single();
能否写成 成员变量的形式?
所以private static
3.内部创建出对象 还得向外界提供
因为private 外界不能直接访问
所以见解 向外界提供一个函数 外界通过调用函数获取对象
6.13 继承
继承由来是什么:当我们在定义若干个类的时候,发现某一些类中具有相同的属性和行为
那么,我们就可以将这些相同的部分进行抽取,独立生成另外一个类,那么这个生成出来
的类我们称之为是父类,其他的被抽取内容的类称之为子类
子类与父类之间就是所谓的继承关系 用 extends来表示
那么在现实生活中,父与子之间的一对多 还是多对多的关系?
所以 在Java当中 继承是单继承(一个子类只能有一个父类,但是一个父类可以有若干个子类)
当然,在C++中,继承是多继承的,不太符合实际的社会问题,所以Java更加符合现实编程
(不代表Java当中就没有多继承的时候!如果是类与类之间 必须是单继承;如果是接口与接口之间,可以是多继承)
既然有了继承,那么在Java当中就有了继承体系
(既然有了父子关系,是不是就产生出了族谱这个东西)
先说一点:我们常用的继承体系 异常体系 集合体系 IO体系 网络体系 多线程体系
C->B->A->?->?->龙的传人/炎黄子孙
C就是B的儿子,那么A就是C的爷爷在Java继承体系当中,所有类的最终父类都是Object!Object就不存在爸爸了
如果我们在定义一个类的时候,没有显著声明父类的时候 那么该类的父类默认是Object注意一点:在分析设计继承的时候 一定要符合社会常识问题
子类 和 父类 之间 必须是 is a 关系 子类必须父类的一种 同一系列的
she is a Girl ; he is a boy ; he is a ladyboy ; 旺财 is a Dog
所以,千万不要为了获取某一个类的功能而把这个类叫爸爸!子父类中成员变量/静态变量的特点:
如果只有子类有且非私有 那么就调用子类的
如果只有父类有且非私有 那么就调用父类的
如果子父类都有且非私有 那么就调用子类的
(成员变量之间 是不存在重写关系的!!!)
子类.属性 顺序:子类对象成员->子类静态->父类成员->父类静态
子类成员函数在内部调用变量时 局部变量->子类对象成员->子类静态->父类成员->父类静态子父类中构造函数的特点:
现象:子类的构造函数在调用运行的时候 先执行父类的构造函数
在子类的构造函数当中,有一句默认的super(...)隐藏了,而且这句代码必须是在第一行
对super的调用必须是构造器中的第一个
为什么?道理很简单 儿子向老爸要钱,那么老爸是不是得先准备一下钱
既然子类继承自父类 那么必然会继承到父类当中的一些数据
所以,在子类构造函数之中,必须先让父类把这些数据进行一些初始化才能继承给子类
注意:父类的构造函数被调用,但不代表父类就被创建对象了!
所以this是当前对象的引用,而super不是父类对象的引用,而是父类空间的引用
并且注意super(...) 如果父类没有默认无参构造函数 那么子类构造函数中super()失效了
所以在调用父类构造函数时,一定要注意父类构造函数的参数情况!适时修改super(...)this(...)是当前类中 本类构造函数调用本类构造函数的方式
super(...)是本类构造函数调用父类构造函数的方式
都必须在第一行 那么这两冲突不?
如果本类构造函数当中不存在调用关系 那么每一个本类构造函数第一句都是super(...)
如果本类构造函数当中存在调用关系,那么最后被调用的那个构造函数第一句绝对是super(...)
this(...)的调用是单向的还是递归的?是单向的,那么最后被调用的第一句绝对就是super(...)
子父类中成员函数的特点:
如果只有子类有且非私有 那么就调用子类的
如果只有父类有且非私有 那么就调用父类的
如果子父类都有且非私有 那么就调用子类的(函数重写)
函数重写:在子父类中,同名函数
函数有什么组成:函数声明(权限 类型 返回值类型 函数名 参数列表)+函数体({}里面的内容)
重写的意义在于哪?在于子类继承了父类的函数声明(功能),但是子类可以将该函数的具体实现进行优化或更改
郭德纲会说相声 郭麒麟也会说相声
子承父业!
1.保留父类的功能声明 子类可以进一步优化
2.保留父类的功能声明 子类可以重新定义
重写当中应该注意到的一些细节:
1.函数重名 但是参数列表不同 不构成重写关系
2.函数重名 参数列表相同 构成重写关系 返回值类型也必须是一样的
3.子类重写父类函数时,权限>=父类权限
4.当然 如果父类函数权限为private 子类压根就继承不到 何谈重写
6.14 抽象类
抽象类:模糊不清的类 不具体的类
当我们在抽取一个父类的时候,发现子类当中的一些共同方法在父类中无法进行具体的实现
并且这些方法只能在子类中具体实现时,父类当中的这些函数就只保留函数声明即可,不必写函数体
那么此时这个函数就是 抽象函数! 有抽象函数的类 就是抽象类!
特点:
1.抽象类能否创建对象?不能 对象本身是一个具体的东西 而抽象类中含有不具体的内容
2.抽象类必须作为父类存在吗?必须 抽象类就等着被继承呢!
3.抽象类和一般类有什么区别?就是一般类的特殊情况
唯一的区别只在于抽象类中有抽象函数!
4.抽象类中必须有抽象函数吗?不一定 AWT界面开发
5.abstract这个关键字不能和那些关键字共存?
private 抽象函数就等着被子类重写实现呢!
static 静态是优先于对象存在的,在加载静态数据的时候 肯定是具体的数据
类名.抽象函数 很尴尬!
如果抽象函数可以被静态 那么我们还需要对象干什么?
6.17 多态
多种状态:就是指一个对象可以有多种状态(他在继承体系中的位置变化)
D->C->B->A->Animal
位置的变化只能是向上变 但不能低于自身
对于C而言 可以当做B来看 也可以当做A来看 也可以当成Animal
小明 男人 人 动物
小明的学校开家长会 小明不想让他爸爸去 他让大明去 大明就是小明他哥
大明冒充Dad去参加家长会的话,那么所表现出来的行为 是不是应该符合他爸行为
不同的视角 不同的角色
无论是在哪个视角场合 对象本身变了没有?只不过我们需要对象在不同的场合表现出相对应的行为
在Java当中 多态代码表现 就是 父类引用指向子类的对象
多态的前提:继承 重写
多态的好处:对代码的功能进行了可扩展性
子类对象可以当做父类对象去使用 但是有限制 只能调用父类函数或重写的函数
不能使用子类特有的行为
多态当中 成员变量的特点:只能访问父类中的成员变量
多态当中 成员函数的特点:
如果子类没有重写 且父类中有 调用父类的
如果子类有重写 调用子类重写的
如果不存在重写 父类没有 那就报错了!