Java基础知识:面向对象
一,八种基本数据类型
千锋教育二,方法
方法就是具有特定功能的代码块,增加代码的复用性,减少代码冗余
方法重载(overloading method)
在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义;返回值不能作为重载的条件。
如:
public void method(int a){}
public void method(char c){}
三,数组
1. 数组是一种线性数据存储的结构,具有存取效率高,内存空间连续的特点,数组必须具有固定长度,是最常用的数据结构之一。
2. 数组内存结构分析:数组是引用类型,会存放在堆内存中。
栈:大小固定,存储局部,临时变量(即基本数据类型),和引用变量的地址
堆:大小不固定,存储真实数据
千锋教育3. 冒泡排序
一组数列,第一个和第二个比较,如果第一个比第二个大就交换位置,第二个和第三个比较,第二个比第三个大就交换,以此类推。相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法
心法:N个数字来排队,两两相比小靠前;外层循环N-1,内层循环N-1-i
千锋教育3. 选择排序
每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好顺序的数列的最后,直到全部待排序的数据元素排完。选择排序是不稳定的排序方法
选择算法是必记的基础算法,数据规模越小越好,好处是不占用额外的内存空间
千锋教育4. 直接插入排序算法
基本思想:每步将一个待排序的记录,按其顺序码大小插入到前面已经排序的子序列的合适位置。(从后往前找到合适位置后),直到全部插入排序完为止。
四,面向对象
面向过程:一步一步的完成某一个具体事情
面向对象:通过调度组合不同的对象来完成某一件事
1. 什么是面向对象
1). 面向对象是一种编程思想
2). 面向对象是一种思考问题的思维方式
2. 建立面向对象的思维方式
1). 先整体,再局部
2). 先抽象,再具体
3). 能做什么,再怎么做
3. 如何学习面向对象
1). 掌握一门面向对象语言的语法
2). 熟悉面向对象的设计规则
3). 熟悉面向对象的设计模式
4. 类与对象
什么是类?
1). 类是:分类,类别
2). 通过分类:我们可以区分不同的事物种类,在日常生活中,我们常常这样做,所以,类是一组具有相同特性(属性)与行为(方法)的事物集合
5. 类与对象的关系
1). 类表示一个共性的产物,是一个综合特征,而对象,是一个个性的产物,是一个个体的特征
2). 类由属性和方法组成
* 属性:就相当于一个个的特征
* 方法:就相当于一个个的行为:例如:说话,吃饭,唱歌,睡觉
6. 类与对象小结
1). new关键字,表示向内存申请空间,也表示实例化一个对象,创建一个对象
2). 一个对象在内存中的大小,由该对象的所有属性所占的内存大小的总和(引用类型变量在32位系统上占4个字节,在64位系统上占8个字节),加上额外的对象隐性数据所占的大小
3). 相同的类型才可以赋值
4). 不同的引用,指向同一个对象,任何一个引用改变对象的值,其他引用都会反映出来
5). 编程时要注意的问题,在确定不使用对象时,要尽早释放对象:引用=null
6). 当一个堆中的对象没有被任何引用变量所指向时,该对象会被JVM的GC程序认为是垃圾对象,从而被回收
7. 封装性
* 封装性是面向对象三大特性之一,封装的本质是隐藏细节,仅对外提供统一访问接口,一个个封装的东西又组成了另一个东西.
8. 封装属性的类
private关键字:访问权限操作符,public表示公有的,private表示私有的属性和方法,只能在本类中访问。
公有的属性和方法,可以被类外部的其他类访问,想要在类外部访问私有属性,我们需要提供公有的方法来间接访问。通常在一个类中,属性都私有化,并对外提供getter and getter方法
9. 成员变量和局部变量
1). 在类中的位置不同
* 成员变量:在类中定义
* 局部变量:在方法中定义或者方法的参数
2). 在内存中的位置不同
* 成员变量:在堆内存(成员变量属于对象,对象进堆内存)
* 局部变量:在栈内存(局部变量属于方法,方法进栈内存)
3). 生命周期不同
* 成员变量:随着对象的创建而存在,随着对象的销毁而消失
* 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
4). 初始化值不同
* 成员变量:有默认初始化值,引用类型默认为null
* 局部变量:没有默认初始化值,必须定义赋值,然后才能使用
注意:
* 局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则
总结:成员变量属于类,局部变量在方法
10. 构造方法
构造方法是在类中定义的,构造方法的定义格式:方法名称与类名相同,无返回值类型的声明
1). 构造方法就是类构造对象时调用的方法,用于对象的初始化工作
2). 构造方法是实例化一个类的对象时,也就是new的时候,最先调用的方法
* 构造方法小结:
1). 构造方法名称与类名相同,没有返回值声明(包括void)
2). 构造方法用于初始化数据(属性)
3). 每一个类中都会有一个默认的无参的构造方法
4). 如果类中有显示的构造方法,那么默认的构造方法将无效
5). 如果类中有显示的构造方法,还想保留默认构造方法,需要显示的写出来
6). 构造方法可以有多个,但参数不一样,称为构造方法的重载
7). 在构造方法中调用另一个构造方法,使用this(...),该句代码必须在第一句
8). 构造方法之间的调用,必须要有出口(否则会死循环)
9). 给对象初始化数据可以使用构造方法或setter方法,通常情况下,两者都会保留
10). 一个好的编程习惯时保留默认的构造方法。(为了方便一些框架代码使用反射来创造对象)
11). private Dog(){}, 构造方法私有化,当我们的需求时为了保证该类只有一个对象时。(不能new)
什么时候一个类只需要一个对象?比如:工具类(没有属性的类,只有行为)并且该工具类对象被频繁使用。权衡只用一个对象与产生多个对象的内存使用,来确定该类是否要定义为只需要一个对象。
11. this关键字
1). 调用类中的属性
2). 调用类中的方法或构造方法
3). 表示当前对象:在方法被调用的过程中 ,哪个对象调用了方法,在方法内中的this就代表哪个对象
12. 对象的一对一关系
* 双向一对一
* 单向一对一
* 表达对象的一对一关系,其实就是把对象类型作为属性定义
* 对象内存分析
千锋教育 千锋教育在开发中,定义静态数据需要充分考虑数据的生命周期,如果静态数据太多,必然会占用更多的内存空间
13. static关键字
1). 使用static关键字修饰一个属性
声明为static的变量实质上就是全局变量
2). 使用static关键字修饰一个方法
通常,在一个类中定义一个方法为static, 那就是说无需类的对象即可调用该方法。
声明static的方法有一下几条限制
* 它们仅能调用其他的static方法
* 它们只能访问static数据
* 它们不能以任何方式引用this或super
3). 使用static修饰一个类(内部类)
什么时候使用static?
所有对象共同的属性或方法,那么我们可以定义为静态的
static作用大,内存只有独一份,同类对象都共享,三种用法各不同,谨记静态初始化,它与对象创建没关系。
14. 静态(static)
1). 静态变量或方法不属于对象,依赖类
2). 静态变量是全局变量,生命周期从类被加载后一直到程序结束
3). 静态变量只存一份,在静态方法区中存储
4). 静态变量是本类所有对象共享一份
5). 建议不要使用对象名去调用静态数据,建议使用类名调用
6). static修饰一个方法,那么该方法属于类,不属于对象,直接用类名调用
7). 静态方法不能访问非静态的属性和方法,只能访问静态的
15. 代码块
1). 普通代码块:在方法中写的代码块
2). 构造代码块:在类中定义的代码块,在创建对象时被调用,优于构造方法执行(一般用的不多)
3). 静态代码块:在类中使用static声明的代码块称为静态代码块
* 在第一次使用的时候被调用(创建对象),只会执行一次,优于构造块执行
* 我们在项目开发中通常会使用静态代码块来初始化只调用一次的数据,比如说程序一启动就想将配置信息取出来,放在内存中
4). 同步代码块(多线程)
* 小结:项目中重点会使用的是静态代码块>普通代码块>同步代码块>构造代码块
理解代码块的作用以及初始化的过程,注意,静态代码块可在未来开发中,用来作启动项目时需要初始化数据的工作
test16. 单例模式
单例设计模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点
1). 构造方法私有化
2). 声明一个本类对象
3). 给外部提供一个静态方法获取对象实例
* 两种实现方法
1). 饿汉式:在类被加载后,对象被创建,到程序结束后释放。占用内存的时间长,提高效率。
test2). 懒汉式:在第一次调用getInstance方法时,对象被创建,到程序结束后释放。占用内存的时间短,效率低。多线程访问会有安全问题
test在项目中为什么要使用单例,单例有什么好处?
* 1). 在设计一些工具类的时候(通常工具类,只有功能方法,没有属性)
* 2). 工具类可能会频繁调用
目的是为了节省重复创建对象所带来的内存消耗,从而提供效率
能不能使用构造方法私有化+静态方法来替代单例?
* 从内存上看:私有单例会有个入栈的过程,构造方法私有化+静态方法是程序一开始就加载到内存里
17. 对象数组
对象数组就是数组里的每个元素都是类的对象赋值时先定义对象,然后将对象直接赋值给数组
* 动态数组
* 1). 数组是一种线性数据结构
* 2). 数组不适合做删除插入等操作,适合添加,查找,遍历
test18. 继承
继承:从已有的类创建新类的过程
1). 继承是面向对象三大特征之一
2). 被继承的类称为父类(超类),继承父类的类称为子类(派生类)
3). 继承是指一个对象直接使用另一个对象的属性和方法
4). 通过继承可以实现代码重用
继承无处不再,继承不仅是代码复用,精髓之处在于抽象思维编写代码,以达到程序更强的可扩展性
* 继承一个父类,只能继承非私有的数据(属性和方法)
* protected:访问权限修饰符,在继承关系中使用,在父类中使用protected修饰的属性或方法可以被子类继承
继承的限制约定:
1). Java只能实现单继承,也就是一个类只能有一个父类
2). 允许多层继承,即:一个子类可以有一个父类,一个父类还可以有其他的父类
3). 继承只能继承非私有的属性和方法
4). 构造函数不能被继承
创建子类对象时,父类的构造方法也会被调用。为什么?
* 因为子类要使用父类的数据,那么就要通过父类的构造方法来初始化数据
继承小结:
1). 继承是发生在多个类之间
2). 继承使用关键字extends
3). JAVA只能单继承,允许多继承
4). 被继承的类叫父类(超类),继承父类的类叫子类(派生类)
5). 在父类中的非私有属性和方法可以被子类继承
6). protected(受保护的访问权限修饰符),修饰的属性或方法可以被子类继承
7). 构造方法不能被继承
8). 创建对象会调用构造方法,调用构造方法不一定就是创建对象
9). 实例化子类对象,会先调用父类的构造方法,如果父类中没有默认的构造方法,那么子类必须显示的通过super(...)来调用父类的带参构造方法,super也只能在子类构造方法中的第一句。
* 继承的好处
* 1). 提高代码的复用性
* 2). 提高代码的维护性
* 3). 让类与类之间产生关系,是多态的前提
* 继承的缺点
* 1). 增强了类与类之间的耦合性
子类的实例化过程:
* 子类实例化时先调用父类的构造方法
* 如果父类中没有默认的构造方法,在子类的构造方法中必须显示的调用父类的构造方法
* 结论:
* 构造方法只是用于初始化类中的字段以及执行一些初始化代码
* 调用构造方法并不代表生成对象
19. 方法的重写
在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法,但有时子类并不想原封不动地继承父类的方法,而是想做一定的修改,这就需要采用方法的重写,方法重写又称方法覆盖。
在子类和父类中,重写方法后,在调用时,以创建的对象类型为准,会调用谁的方法。
* 关于方法重写的一些特性
* 1). 发生在子父类中,方法重写的两个方法返回值,方法名,参数列表必须完全一致(子类重写父类的方法)
* 2). 子类抛出的异常不能超过父类相应方法排除的异常(子类异常不能大于父类异常)
* 3). 子类方法的访问级别不能低于父类相应方法的访问级别(public protected private)
* 4). 父类中的方法若使用private, static, final任意修饰符修饰,那么,不能被子类重写
* 为什么要重写方法?或者方法重写的目的是什么?
* 1). 若子类从父类中继承过来的方法,不能满足子类特有的需求时,子类就需要重写父类中相应的方法。
* 2). 方法的重写也是程序扩展的体现。
面试题:overloading与overriding的区别?
* overloading: 方法的重载,发生在同一个类中,方法名相同,参数列表不同,返回值无关
* overriding: 方法的重写,发生在子父类中,方法名相同,参数列表相同,返回值相同。子类的访问修饰符要大于或等于父类的访问修饰符。子类的异常声明必须小于或等于父类的异常声明。如果方法被private, static, final修饰,那么不能被重写。
20. super
super可以完成以下的操作
1). 使用super调用父类中的属性,可以从父类实例处获得信息
2). 使用super调用父类中的方法,可以委托父类对象帮助完成某件事情
3). 使用super调用父类中的构造方法(super(实参列表)),必须在子类构造方法的第一条语句, 调用父类中相应的构造方法,若不显示的写出来,默认调用父类的无参构造方法,比如:super()
* this与super的区别
* this表示当前对象
* 使用super来调用父类的属性,方法和构造方法
21. final关键字
使用final关键字完成以下的操作:
1). 使用final关键字声明一个常量,常量的命名规则建议使用全大写。修饰属性或者修饰局部变量(最终变量),也称为常量。
2). 使用final关键字声明一个方法
该方法为最终方法,且只能被子类继承,但是不能被子类重写。
3). 使用final关键字声明一个类
该类就转变为最终类,没有子类的类,final修饰的类无法继承。
4). 在方法参数中使用final,在该方法内部不能修改参数的值(在内部类中详解)
* 常用类(工具类):在实际项目开发中,常量类通常用于定义项目中一些公共的,不变的。
22. 抽象类
定义一个抽象类
* 抽象类:abstract关键字声明的类称为抽象类
类与抽象类:
* 很多具有相同特征和行为的对象可以抽象为一个类
* 很多具有相同特征和行为的类可以抽象为一个抽象类
抽象类的特点:
1). 抽象类可以没有抽象方法,又抽象方法的类必须是抽象类
2). 非抽象类继承抽象类必须实现所有抽象方法
3). 抽象类可以继承抽象类,可以不实现父类抽象方法
4). 抽象类可以有方法实现和属性
5). 抽象类不能被实例化
6). 抽象类不能声明为final
7). 抽象类可以有构造方法
23. 接口
1). 接口是标准的规范:比如合同,法律,校规等
2). 接口的定义格式:
interface 接口名称{
全局常量;
抽象方法;
}
3). 接口的使用原则:
* 1. 定义一个接口,使用interface关键字
* 2. 在一个接口中,只能定义常量,抽象方法,JDK1.8可以定义默认的实现方法
* 3. 接口可以继承多个接口:extends xxxx,xxxx
* 4. 一个具体类实现接口使用implements关键字
* 5. 一个类可以实现多个接口
* 6. 抽象类实现接口可以不实现接口的方法
* 7. 在接口中定义的方法没有声明访问修饰符,默认为public
* 8. 接口不能有构造方法
* 9. 接口不能被实例化
* 10. 实现接口的类,可以实现多个接口,具体类实现接口,必须实现接口给的所有方法
24. 多态
多态是面向对象三大特性之一
* 什么是多态性?
* 对象在运行过程中的多种形态
多态我们大概可以分为两类
1). 方法的重载和重写
2). 对象的多态性
* 例如:
* 用父类的引用指向子类对象(用大的类型去接受小的类型,向上转型,自动转换)
* 结论:在编程时针对抽象类型的编写代码,称为面向对象编程(或面向接口编程)
* 父类通常都定义为抽象类,接口
对象的多态性:对象多态性是从继承关系中的多个类而来
1). 向上转型:将子类实例转为父类引用
* 格式:父类 父类对象 = 子类实例; (自动转换)
以基本数据类型操作为例:int i = 'a'; (因为char的容量比int小,所以可以自动完成)
2). 向下转型:将父类实例转为子类实例
* 格式:子类 子类对象 = (子类)父类实例; (强制转换)
以基本数据类型操作为例:char c = (char)97; (因为整型是4个字节,比char2个字节要大,所以需要强制完成)
多态性小结:
1). 方法的重载与重写就是方法的多态性的表现
2). 多个子类就是父类中的多种形态
3). 父类引用可以指向子类对象,自动转换
4). 子类对象指向父类引用需要强制转换(注意:类型不对会报异常)
5). 在实际开发中尽量使用父类引用(更利于扩展)
* 多态时面向对象三大特性之一,是面向对象编程思维的精髓所在,用抽象的思维写代码。在运行过程中再传入具体的对象,同面向接口编程如出一辙。
25. instanceof
instanceof 是用于检查对象是否为指定的类型,通常把父类引用强制转换为子类引用时要使用,以避免发生类型转换异常(ClassCastException)
* 语法格式如下:
对象 instanceof 类型 //返回boolean类型值
该语句一般用于判断一个对象是否为某个类的实例,是返回 true, 否返回false
* 父类的设计法则
通过instanceof关键字,我们可以很方便的检查对象的类型,但如果一个父类的子类过多,这样的判断还是显得很繁琐,那么如何去设计一个父类呢?
* 1). 通常情况下,父类都设计为抽象类或接口类,其中优先考虑接口,如接口不能满足才考虑抽象类
* 2). (推荐)一个具体的类尽可能不去继承另一个具体类,这样的好处是无需检查对象是否为父类的对象
* 模板方法模式(Template Method):定义一个操作中的算法的骨架,而将一些可变部分的实现延迟到子类中。
模板方法模式使得子类可以不改变一个算法的结构即可以重新定义该算法的某些特定的步骤
26. 策略模式(Strategy Pattern)
定义了一系列算法,将每一种算法封装起来并可以互相替换使用。 策略模式让算法独立于使用它的客户应用,而独立变化。
把可变的行为抽象出来,这样的好处是这些行为可以在真正使用时相互替换。策略模式是非常常用的,一个接口有多个实现,不同的实现独立封装,可以按运行时需求相互替换,可维护性就强了,新增接口也不会影响其他实现其他类。
27. Object类
Object类是类层次结构的根类,每个类都使用Object作为超类,所有对象(包括数组)都实现这个类的方法。所有类都是Object类的子类。
*例如
*1). public String toString()方法:返回该对象的字符串表示
通常,toString方法返回一个“以文本方式表示”此对象的字符串,结果应是一个简明易于读懂的信息表法式(建议所有子类都重写此方法)。
*2). public boolean equals(Objec obj)
指示其他某个对象是否与此对象“相等”,equals方法在非空对象引用上实现相等关系。
*3). protected void finalize() throws Throwable
当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法,子类重写finalize方法,以配置系统资源或执行其他清除。
*4). public final class <?> getClass()
返回此Object的运行时类
28. 几种设计模式
1. 简单工厂模式
简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式时工厂模式家族中最简单实用的模式。
2. 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。代理模式说白了就是“真实对象”的代表,在访问对象时引入一定程度的间接性
* 因为这种间接性可以附加多种用途。比如说代购,律师,中介
3. 适配器模式(Adapter):将一个类的接口转换成客户希望的另一个接口。
* 适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
适配器模式的另一种用法:
* 具体类在实现接口的时候,需要把所有的方法都实现,
* 可以建立一个适配器类,实现接口中的方法,空方法体,具体类再继承这个方法,需要实现哪个方法都可以
29. 内部类
内部类就是在一个类的内部定义的类
1). 成员内部类:直接在类中定义的类(成员)
成员内部类格式如下:
* class Outer{
* class inner{}
* }
编译上述代码会产生两个文件: Outer.class和Outer$Inner.class
在外部创建内部类对象
内部类除了可以在外部类中实现实例化对象,也可以在外部类的外部来实例化。那么,根据内部类产生的“.class”文件,Outer.class, "$"符号在程序运行时将替换成".",所以内部类的访问,通过“外部类.内部类”的形式表示。
2). 方法内部类:在一个类中的方法中定义的类(局部)
内部类可以作为一个类的成员外,还可以把类放在方法内定义。
注意:
* 1. 方法内部类只能定义在该内部类的方法内实例化,不可以在此方法外对其实例化
* 2. 方法内部类对象不能使用该内部类所在方法的非final局部变量
3). 静态内部类(成员)
* 在一个类内部定义一个静态内部类:
* 静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。
* 静态嵌套类仅能访问外部类的静态成员和方法
4). 匿名内部类(局部)
匿名内部类就是没有名字的内部类,匿名内部类有三种情况
* 1). 继承式的匿名内部类
* 2). 接口式的匿名内部类
* 3). 参数式的匿名内部类
在使用匿名内部类时,要记住以下几个原则
* 1). 不能有构造方法,只能有一个实例
* 2). 不能定义任何静态成员,静态方法
* 3). 不能时public, protected, private,static
* 4). 一定是在new的后面,用其隐含实现一个接口或实现一个类
* 5). 匿名内部类为局部的,所以内部类的所有限制都对其生效
问题:局部内部类访问局部变量必须用final修饰,为什么?
* 当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法被调用时会入栈,方法结束后即弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失,想用这个局部变量,显然已无法使用了。如果用final修饰,会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也就可以继续使用了。
* 注意:在jdk1.8取消了在局部内部类中使用的变量必须显示的使用final修饰,编译器默认会为这个变量加上final
* 内部类的概念在一定程度上打破了类的定义,但在一些叫复杂的类设计中,内部类解决了Java不能多继承的问题
* 依赖外部类对象:成员内部类,方法内部类,匿名内部类
* 不依赖外部类对象:静态内部类
* 所以我们在项目中,优先考虑选择静态内部类(不会产生内存泄漏)
30. 链表
链表:一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每个节点里存到是下一个节点的指针(pointer)
* 链表和数组:线性数据结构
* 数组适合查找,遍历,固定长度
* 链表适合插入,删除,不固定长度,但不宜过程,否则导致遍历性能下降
掌握数组和链表的优缺点,才直到使用时如何选择,基于数组实现的动态数组有ArrayList等,基于链表实现的有LinkedList等
在链表数据结构中,我们需要使用到递归算法
递归算法是一种直接或简洁调用自身算法的过程
* 在计算机编写程序中,递归算法对解决一大类问题是十分有效的
* 它往往使算法的描述简洁而且易于理解
递归算法,方法本身调用自己
1). 递归必须要有出口
2). 递归内存消耗大,容易发生内存溢出(每次都有方法的入栈,变量,对象引用都需要占用内存)
3). 层次调用越多,越危险
31. 基本数据类型包装类
在Java中有一个设计的原则“一切皆对象”,Java中的基本数据类型就完全不符合这种设计思想,因为八种基本数据类型并不是引用数据类型,所以java中为了解决这样的问题,JDK1.5以后引入了八种基本数据类型的包装类
1). 八种包装类分为两大类型:
* Number: Integer, Short, Long, Double, Float, Byte都是Number的子类,表示一个数字
* Object: Character, Boolean都是Object的直接子类
千锋教育2). 装箱及拆箱操作
* 将一个基本数据类型转换为包装类,那么这样的操作被称为装箱操作,将一个包装类转换为一个基本数据类型,这样的操作称为拆箱操作。
千锋教育3). 转型操作:在包装类中,可以将一个字符串变为指定的基本数据类型,一般在输入数据时会使用较多
* 在Integer类中,将string变为int型数据:public static int parseInt(String s)
* 在Float类中,将string变为float型数据:public static int parseFloat(String s)
注意:转型操作时,字符串必须由数字组成,否则会出现错误
test4). 享元模式(Flyweight Pattern):
使用共享对象,用来尽可能减少内存使用量,以及分享咨询给尽可能多的相似对象,它适用于当大量对象只是重复,导致无法令人接受的使用大量内存,通常对象中的部分状态是可以分享,常见做法是它们放在外部数据结构,当需要使用时再将它们传递给享元。
* 运用共享计数有效的支持大量细粒度的对象
一个字节的数字以内,可以共享一个内存地址:-128~127
5). 包与访问修饰符
包用于对多个java源文件的管理,就像我们的文件目录一样
* 定义一个包:package com.vince
(该语句只能出现在代码中的第一句)
6). 访问修饰符
千锋教育32. OO原则
1). 开闭原则
一个软件实体,如类、模块和函数应该对扩展开放,对修改关闭。
2). 合成/聚合复用原则
新对象的某些功能在已创建好的对象已实现,那么尽量用以用对象提供的功能,使之成为新对象的一部分,而不要再重新创建
3). 依赖倒置原则
高层模块不应该依赖高层模块,二者都应该依赖其抽象,抽象不应该依赖细节,细节应该依赖抽象。
4). 接口隔离原则
客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立中最小的接口上。
5). 迪米特法则
一个对象应该对其他对象保持最少的了解。
6). 里氏替换原则
所有引用基类的地方必须能透明地使用其子类的对象。
7). 单一职责原则
不要存在多于一个导致类变更的原因,即一个类只负责一项职责。
千锋教育33. class文件加载到内存的结构图