面向对象
面向对象思想:面向对象是基于面向过程的编程思想。
面向过程:强调的是每一个功能的步骤
面向对象:强调的是对象,然后由对象去调用功能
面向对象特点:是一种更符合我们思想习惯的思想;可以将复杂的事情简单化;将我们从执行者变为指挥者。
面向对象开发:就是不断创建对象,使用对象,指挥对象做事情。
面向对象设计:管理和维护对象之间的关系。
面向对象特征:
封装(encapsulation)
继承(inheritance)
多态(polymorphism)
完成某个需求时:
分析有哪些类:UML(统一建模语言),名词提取法。
每个类都有哪些东西:属性,方法
类与类之间的关系是什么:耦合
类与对象的关系
java中最基本的单位是类。
类:一组相关的属性和行为的集合,是一个抽象的概念。
事物就是通过类来体现出来。事物是由属性(该事务的描述信息)和行为(该事务能做什么)组成。
对应类中为:成员变量和成员方法。
对象:是该类事物的具体实现形式,具体存在的个体。
成员变量:和以前变量的定义是一样的格式,但是位置不同,在类中方法外。
成员方法:和以前的方法定义是一样的格式,但是把static去掉。
如何使用类及类中的属性和行为呢:创建该类的一个对象使用。
格式: 类名 对象名=new 类名();
如何使用成员变量: 对象名.变量名
如何使用成员方法: 对象名.方法名(参数…)
匿名对象:就是没有名字的对象。
应用场景:
A:调用方法:仅仅只调用一次的时候(若多次调用,不适合)
优点:匿名对象调用是在堆内存中,调用完毕就是垃圾,可以被垃圾回收器回收
B:匿名对象可以作为实际参数传递。(当方法中的形式参数是一个引用类型比如类的时候,实际参数可以用匿名对象当作该类的一个对象)
封装
通过对象给成员变量赋值,可以赋值一些非法的数据,这是不合理的。
在赋值之前,应该先对数据进行判断。怎么进行判断呢?就是写一个方法对数据进行校验。但是不用方法就起不到作用了。所以要求必须使用方法,不能直接调用成员变量。
封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式。
原则:将不需要对外提供的内容都隐藏起来。把属性隐藏,提供公共方法对其访问。
优点:隐藏实现细节,提供公共的访问方式;提高了代码的复用性;提高安全性。
private:私有的,是一个权限修饰符,可以修饰成员变量和成员方法。
被private修饰的成员只能在本类中访问。
最常见的应用:把成员变量用private修饰,提供对应的getXxx()/setXxx()方法以使外界可以访问
this关键字:this代表所在当前类的一个对象引用。
方法被哪个对象调用,this就代表那个对象。
用this的场景:当局部变量隐藏成员变量时,成员变量可能被局部变量覆盖无意义,所以要用this。 super
构造方法
作用:给对象的数据进行初始化
格式:方法名和类名相同。没有返回值,连void都没有。没有具体的返回值。
注意事项:如果不提供构造方法,系统会给出默认的构造方法
如果提供了构造方法,系统将不再提供默认的构造方法。如果还想使用无参构造方法,就必须自己给出,建议永远自己给出无参构造方法。
构造方法也可以重载。
给成员变量赋值有2种方法:
A. 无参构造方法+setXxx();
B. 带参构造方法
类中包含有:成员变量、成员方法、构造方法。
成员方法
根据返回值可以分为:void类型和非void类型。
根据形式参数:空参方法和非空参方法。
Student s=new Student();
在内存中发生了什么?
加载Student.class文件进内存
在栈内存为s开辟空间
在堆内存为学生对象开辟空间
对学生对象的成员变量进行默认初始化。null 0 0.0 \u0000
对学生对象的成员变量进行显式初始化
通过构造方法对学生对象的成员变量赋值
学生对象初始化完毕,把对象地址赋值给s变量。
当一个变量是用来描述类的信息时,这个变量就应该被定义为成员变量。(成员变量不要瞎定义)
变量的范围是越小越好,因为能及时的被回收。
当多个对象有共同的成员变量值的时候,java就提供了一个关键字来修饰:static。
static可以修饰成员变量和成员方法。
static关键字的特点:随着类的加载而加载;优先于对象存在;被类的所有对象共享(这也是我们判断是否使用静态关键字的条件);可以通过类名调用(其实本身也可以通过对象名调用,推荐使用类名调用)静态修饰的内容我们一般称为与类相关的,类成员
注意事项:在静态方法中是没有this关键字的(因为静态是随着类的加载而加载,而this是随着对象的创建而存在,静态比对象先存在)
静态方法只能访问静态的成员变量和静态的成员方法。(main方法是静态方法,不能调用非静态方法,如果想调用的话,可以先在main方法中创建一个对象,通过这个对象来调用非静态方法)
非静态方法可以访问静态的成员变量和成员方法,也可以访问非静态的成员变量和成员方法。
静态变量和成员变量的区别:
所属不同:静态变量属于类,也被称为类变量
成员变量属于对象,也被称为实例变量(对象变量)
内存中的位置不同:静态变量存储于方法区的静态区
成员变量存储于堆内存中
内存出现的时间不同:静态变量随着类的加载而加载,随着类的消失而消失
成员变量随着对象的创建而存在,随着对象的消失而消失
调用不同:静态变量可以通过类名调用,也可以通过对象名调用
成员变量只能通过对象名调用
main方法的格式讲解:
public:公共的,访问权限是最大的。由于main方法是被jvm调用的,所以权限要够大。
static:静态的,不需要创建对象,通过类名就可以调用,方便jvm的调用。
void:方法的返回值是返回给调用者,而main方法是被jvm调用的,返回给jvm无意义。
main:是一个常见的方法入口,所有语言都是以main方法为入口
String[] args:这是一个字符串数组。这个东西早期是为了接收键盘录入的数据的。
eg:java 类名 hello world java 遍历args就会发现是 hello world java
后来用java.util.Scanner代替了
测试类的作用:创建其他类的对象,调用其他类的功能。
在同一个文件夹下,类定义在两个文件中和定义在一个文件中其实一样的。
静态的一种用法:在工具类中,将构造方法私有化,这样外界无法创建该类的对象,然后将要调用的方法static静态化,这样main方法调用时候只能通过类名.方法名调用。
项目提供的都是class文件,无从得知class文件内都有哪些方法哪些属性。所以需要加说明书。
说明书的制作:
A:写一个工具类
B:对这个类加文档注释:
/**
*@author
*@version
*@param
*return
*/
C:用工具解析文档注释:javadoc工具
D:格式:
javadoc -d (文件夹的路径) -author -version (类名).java
制作帮助文档出错:找不到可以文档化的公共或受保护的类。告诉我们类的权限不够。(若想权限够,在class前加public)
所以以后开发可以利用工具类加说明书,对该类中实现的方法的static、返回值、方法名、参数注意然后就可以调用使用,对怎么实现的方法不用在意,这就是面向对象思想。
.html转换为帮助文档就是.chm文档
使用帮助文档API(Application Progaramming Interface,应用程序编程接口):
打开帮助文档
点击显示,找到索引,找到输入框
明确要找什么
在输入框内输入要查找的类,回车
看包,java.lang包下的类不需要导入,其他的都需要全部导入
再简单的看看类的解释和说明,类的版本信息
看类的结构
成员变量:字段摘要
构造方法:构造方法摘要
成员方法:方法摘要
学习构造方法
有构造方法:创建对象
无构造方法:成员可能都是静态的
看成员方法:
静态、返回值类型、方法名、参数列表。
代码块:在java中使用{}括起来的代码称为代码块,根据其声明和位置不同,可以分为局部代码块,构造代码块,静态代码块和同步代码块。
局部代码块:局部位置,在方法中出现,限定变量生命周期,及早释放,提高内存利用率。
构造代码块:在类中成员位置出现(直接{}括起来),每次调用构造方法都执行,并且在构造方法前执行。
作用:可以把多个构造方法方法中相同的代码存放到一起。
静态代码块:在类中成员位置出现(直接{}括起来),{前面加了static修饰。在加载的时候就执行,且只执行一次。
作用:用于给类进行初始化。
一个类中的执行顺序:与书写顺序无关,执行时都是这个顺序
静态代码块(只执行一次,加载类的时候就执行)–构造代码块(每次调用构造方法都执行)–构造方法
Math类:是针对数学进行操作的类,没有构造方法,成员都是静态的。
产生随机数:public static double random(): [0.0,1.0)
产生1-100的随机数:int number=(new)(Math.random()*100)+1;
继承
多个类的成员变量,成员方法等都是相同的。每一次定义的时候都需要重新定义一遍,所以要考虑改进,提高代码的复用性,用继承。
多个类中存在相同的属性和行为时,将这些内容抽取到单独的一个类中,那么多个类无需在定义这些属性和行为,只要继承那个类即可。
格式:
class 子类名 extends 父类名{}
单独的这个类称为父类,基类,超类。
多个类称为子类,派生类。
优点:提高了代码的复用性:多个类相同的成员可以放到同一个类中
提高了代码的维护性:如果功能的代码需要修改,修改一处即可。
让类与类之间产生了关系,是多态的前提。(也是继承的弊端:类的耦合性很强)
开发的原则:低耦合,高内聚。
耦合:类与类的关系
内聚:自己完成某件事情的能力
继承的特点:
\1. java中只支持单继承,不支持多继承。(C++支持多继承,格式:extends 类1,类2…)
\2. java支持多层继承(继承体系)
继承的注意事项:
\1. 子类只能继承父类所有非私有的成员(成员方法和成员变量),也体现了继承的一个弊端:打破了封装性
\2. 子类不能继承父类的构造方法,但是可以通过super关键字来访问父类的构造方法
\3. 不要为了部分功能而去继承(当类与类之间的关系是“is a”的关系时使用继承)子类is父类的a
子类中的成员变量和父类中的成员变量如果一样的话,再调用时候遵循就近原则。
在子类方法中访问一个变量的查找顺序:1.在子类方法的局部范围找,有就用
2.在子类的成员范围找,有就用
\3. 在父类的成员范围找(不可能在父类的方法局部范围找,因为方法不调用不执行,相当于没有)
super关键字:super代表父类存储空间的标识(父类引用,可以操作父类的成员,但不是父类的一个对象,只是父类的一个存储空间)
this代表本类对象的引用
用法:
A. 调用成员变量:
this.成员变量:调用本类的成员变量
super.成员变量:调用父类的成员变量
B. 调用构造方法:
this(…):调用本类的构造方法
super(…):调用父类的构造方法
C. 调用成员方法:
this.成员方法:调用本类的成员方法
super.成员方法:调用父类的成员方法
继承中构造方法的关系:子类中所有的构造方法默认都会先访问父类中空参数的构造方法。
因为子类会继承父类中的数据,可能还会使用父类的数据,所以,子类初始化之前,一定要先完成父类数据的初始化。每一个构造方法的第一条语句默认都是super();
如果父类没有无参构造方法,那么子类的构造方法会出现报错。(这就是为什么建议构造方法永远手动给个无参的构造方法)
解决方法:A.在父类中加一个无参构造方法
B.子类通过super(…)去显示调用父类其他的带参的构造方法。
C. 子类通过this去调用本类的其他构造方法,但是一定会有一个去访问了父类的构造方法。
子类中一定要有一个去访问了父类的构造方法,否则父类的数据就没有初始化。
注意事项:this()或者super()必须出现在第一条语句上。如果 不是放在第一条语句上,就可能会对父类数据进行了多次初始化。
一个类的初始化过程:成员变量进行初始化(默认初始化,显示初始化),构造方法初始化
子父类的初始化(分层初始化)先进行父类初始化,再进行子类初始化。虽然子类中构造方法默认有一个super() ,但是初始化的时候不是按照那个顺序的,而是按照分层初始化进行的。super()只是表示要先初始化父类数据在初始化子类数据。
继承中成员方法的关系:通过子类对象去访问一个方法,首先在子类中找,然后在父类中找,如果没有就报错(不会去父类的父类中找)
方法重写(方法覆盖,方法复写):子类中出现了和父类中方法声明一模一样的方法。
方法重载:本类中出现的方法名一样,参数列表不同的方法,与返回值无关。
方法重写的应用:当子类需要父类的功能,而功能主体子类有自己特有的内容时,可以重写父类中的方法(重写是完全重写,如果还想用父类中的方法内容,可以用super调用),这样,既沿袭了父类的功能,又定义了子类特有的功能。
注意事项:父类中私有方法不能被重写。(其实父类中私有方法子类根本就无法继承,更谈不上重写)
子类重写父类方法时,访问权限不能更低。(最好就一致)
父类是静态方法,子类也必须通过静态方法进行重写。(其实不算方法重写)
父类不是静态,子类用static静态,会报错。
所以,子类重写父类方法的时候,最好声明一模一样。
由于继承中方法有一个方法重写,所以父类的功能会被子类覆盖,当不想让覆盖的时候,java提供了一个关键字:final
final:最终的意思。可以修饰类、方法、变量。
final可以修饰类:该类不能被继承
final可以修饰方法:该方法不能被重写
final可以修饰变量:该变量不能被重新赋值。这个变量其实是常量。
final修饰局部变量(一般权限修饰符修饰局部变量无意义,但是final特殊):在方法内部,该变量不能被改变。
在方法声明上,基本类型是值不能被改变。引用类型是地址值不能被改变,但是该对象的堆内存的值还可以改变,注意区别。
final修饰变量的初始化时机:
1.被final修饰的变量只能赋值一次
2.在初始化时就给值(建议)或者在构造方法完毕前给值(非静态的常量)。
*多态*
多态:同一个对象,在不同时刻体现出不同的状态。
判断多态可以从左往右念:子是父?是的话可以多态,不是的话不能。
多态的前提:
A. 要有继承或者实现关系。
B. 要有方法重写。(如果没有方法重写也是可以的,但是就没有了意义)
C. 要有父类或者父接口引用指向子类对象。
父 f=new 子();
多态中的成员访问特点:
A. 成员变量:编译看左边(父类),运行看左边。
B. 构造方法:创建子类对象的时候,访问父类的构造方法,并对父类的数据进行初始化。
C. 成员方法:编译看左边(父类),运行看右边(方法重写相当于覆盖了)。
D. 静态方法:编译看左边(父类),运行看左边。(所以说静态方法的重写根本不算是重写)
由于成员方法存在方法重写,所以只有它运行的时候看右边。
多态的好处:
A. 提高了代码的维护性(继承保证)
B. 提高了代码的扩展性(由多态保证,以后如果在添加父类的子类,可以使用父类的引用调用工具类,便于代码的扩展性)
多态的弊端:不能使用子类的特有功能。
如果非要调用子类的这些功能:
A. 创建子类的对象调用方法。(可以,但是不合理,太占内存)
B. 把父类的引用强制转换为子类的引用。(向下转型)
Fu f=new Zi(); (向上转型,从子到父,父类引用指向子类对象)
Zi z=(Zi)f; (向下转型,从父到子,父类引用转为子类对象) 要求f必须是能够转换为Zi的。
ClassCastException:类型转换异常,一般在多态的向下转型中容易出现。
当一个类中的东西特别多时,我们可以把这个类分成几个小类:基本类、操作类等。
分包:A.功能划分
B.模块划分
C.先按模块划分,再按功能划分
集合实现,IO实现,GUI实现,数据库实现。
如果一个方法传的参数是三个以上,建议传个对象。
如果多个地方用到了某个变量,可以把这个变量定义为成员变量,定义在成员方法外。
能小范围尽量不大范围,因为用完最好回收。
让多个对象共享同一个成员变量,用static修饰。
循环里面如果有switch,并且在其中有break,结束的不是循环,而是switch语句,如果想结束整体,可以用 System.exit(0);