目录
一、Java基础
1、public class 和 class的区别:
* 一个java源文件当中可以定义多个class
* 一个java源文件当中public的class不是必须的
* 一个class会定义生成一个xxx.class字节码文件
* 一个java源文件当中定义公开的类的话,只能有一个,并且该类名称必须和java源文件名称一致。
* 每一个class当中都可以编写main方法,都可以设定程序的入口,想执行B.class中的main方法:java B,
想执行X.class当中的main方法:java X
* 注意:当在命令窗口中执行java Hello,那么要求Hello.class当中必须有主方法。没有主方法会出现运行
阶段的错误:
D:\course\JavaProjects\02-JavaSE\day02>java Hello
错误: 在类 B 中找不到主方法, 请将主方法定义为:
public static void main(String[] args)
2、标识符可以随意编写吗,有命名规则吗?有
规则1:标识符只能由数字、字母(包括中文)、下划线 _、美元符号$组成,
不能含有其它符号。
规则2:标识符不能以数字开头
规则3:关键字不能做标识符。例如:public class static void 这些蓝色的字体
都是关键字,关键字是不能做标识符的。
规则4:标识符是严格区分大小写的。大写A和小写a不一样。
规则5:标识符理论上是没有长度限制的。
3、综合的看一下,在类型转换的时候需要遵循哪些规则?
第一条:八种基本数据类型中,除 boolean 类型不能转换,剩下七种类型之间都可以
进行转换;
第二条:如果整数型字面量没有超出 byte,short,char 的取值范围,可以直接将其赋
值给byte,short,char 类型的变量;
第三条:小容量向大容量转换称为自动类型转换,容量从小到大的排序为:
byte < short(char) < int < long < float < double,其中 short和 char
都占用两个字节,但是char 可以表示更大的正整数;
第四条:大容量转换成小容量,称为强制类型转换,编写时必须添加“强制类型转换符”,
但运行时可能出现精度损失,谨慎使用;
第五条:byte,short,char 类型混合运算时,先各自转换成 int 类型再做运算;
第六条:多种数据类型混合运算,各自先转换成容量最大的那一种再做运算;
4、switch后面和case后面只能是int和String类型
5、方法定义:
[修饰符列表] 返回值类型 方法名(形式参数列表){方法体;}
[修饰符列表],此项是可选项,不是必须的,目前大家统一写成 public static
对于方法修饰符中有static关键字的,使用"类名.方法名(实参列表)"调用方法;方法在同类可省略"类名.",不同类不能省略
6、方法在执行过程中,在JVM的内存是如何分配的?内存是如何变化的?
1)方法只定义,不调用,是不会执行的,JVM也不会分配其“运行所属”的内存空间,只有调用时才动态分配内存空间。
2)在JVM内存划分中有三块主要的内存空间(还有其他内存空间)
*方法区内存
*栈内存
*堆内存
3)“栈”数据结构(先进后出原则)
4)方法代码片段存在哪里?方法执行时执行过程的内存在哪里?
*方法代码片段属于.class字节码文件一部分,字节码文件在类加载时将其放到方法区中。所以JVM三块主要内存空间方法区内存最先有数据,存放了代码片段。
*代码片段在方法区内存中只有一份,但可被重复调用,每次调用时,需要给该方法分配独立的活动场所,在栈内存中分配。【栈内存中分配方法运行的所属内存空间】。
5)方法在调用瞬间会给该方法分配内存空间,会在栈中发生压栈动作;方法结束后,释放内存空间,发生弹栈动作。
*压栈(入栈)
*弹栈(出栈)
6)局部变量在“方法体”中声明。局部变量运行阶段内存在栈中分配。

7、
*方法调用时,在参数传递时,实际上传递的是变量保存的“值”。
*栈内存主要存储局部变量
8、方法重载
1)什么时候用方法重载?
*功能相相似尽可能让方法名相同;功能不同时,尽可能让方法名不同
2)满足什么条件构成方法重载?
*在同一类中;
*方法名相同;
*参数列表不同:参数数量不同/顺序不同/类型不同
3)方法重载与什么有关?
*方法重载与方法名+参数列表有关;
*方法重载与返回值类型、修饰符列表无关;
9、递归
1)递归很耗费栈内存,递归算法能不用就不用
2)错误Error:java.lang.StackOverflowError ——栈内存溢出错误。错误无法挽回,结果是JVM停止工作。
3)递归必须有结束条件,没有结束条件一定发生栈内存溢出错误;
递归即使有结束条件,也可能发生栈内存溢出错误,因为递归的太深了。
二、面向对象
1、面向对象包括三大特征
封装
继承
多态
***类是现实世界当中具有共同特征的事物进行抽象形成的模板或概念。
***对象是实际存在的个体。
2、当我们采用面向对象的方式贯穿整个系统的话,涉及到三个术语:
OOA:面向对象分析
OOD:面向对象设计
OOP:面向对象编程
整个软件开发的过程,都是采用OO进行贯穿的。
实现一个软件的过程:
分析(A) --> 设计(D) --> 编程(P)
3、面向过程和面向对象有什么区别?
*面向过程的开发方式主要的特点:注重实现这个功能的步骤以及因果关系
*面向对象就是将现实世界分割成不同的单元,然后每一个单元都实现成对象,
然后给一个环境驱动一下,让各个对象之间协作起来形成一个系统。
4、创建对象
* java语言中所有的class都属于引用数据类型。
*方法体外声明的变量叫做成员变量。(实例变量属于成员变量)
*new运算符作用是创建对象,在JVM堆内存中开辟新的内存空间
*栈内存(局部变量):方法代码片段执行时给该方法分配内存空间,在栈内存中压栈;
*堆内存(实例变量):new的对象在堆内存中存储
5、对象与引用
*对象:new运算符在堆内存中开辟的内存空间称为对象;
*引用:引用是一个变量,但这个变量中保存了另一个java对象的内存地址;(引用数据类型定义的变量)
**java语言中,程序员不能直接操作堆内存,java没有指针;只能通过“引用”去访问堆内存当中对象内部的实例变量。
访问“实例变量”语法格式:
// 读取数据:引用.变量名
// 修改数据:引用.变量名=值
6、JVM内存管理
1)JVM(java虚拟机)主要包括三块内存空间:栈内存,堆内存,方法区内存
2)堆内存和方法区内存各有一个;一个线程一个栈内存;
3)方法调用时所需内存空间在栈内存中分配,简称压栈。方法执行结束后,该内存空间释放,简称弹栈。
4)栈内存主要存储方法体中的局部变量;
5)方法的代码片段以及整个类的代码片段都被存储到方法区内存中,在类加载时载入;
6)静态变量存储在方法区内存(重要)
7)程序执行过程中,new运算符创建的java对象存储在堆内存中,对象内部有实例变量,所以实例变量存储在堆内存中。
8)变量分类
-局部变量【方法体内声明】
-成员变量【方法体外声明】
*实例变量【没有static修饰】
*静态变量【static修饰】
9)三块内存变化最频繁的是栈内存; 最先有数据的是方法区内存; 垃圾回收器主要针对堆内存;
10)垃圾回收器【自动垃圾回收机制,GC机制】什么时候会考虑将某个java对象回收?
*当堆内存中的java对象成为垃圾数据时,会被垃圾回收器回收;
*什么时候堆内存中的java对象会成为垃圾数据?
没有更多引用指向它时;(这个对象无法被访问,因为对象只能通过引用方式访问。)
7、空引用访问“实例”相关数据一定会出现空指针异常( java.lang.NullPointerException)
**“实例”相关数据:这个数据访问的似乎必须有对象的参与;
8、关联关系:A has a B 关系 【A对象中含有B对象的引用】
三、重点 this、static
1、封装( 什么是封装?封装有什么好处?怎么封装,代码怎么写?)
1)封装就是利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,
数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。
2)封装后才会形成真正的“对象”,真正的“独立体”;
3)封装意味着以后的程序可以在不同的环境中重复使用,可以降低程序的耦合度,提高程序的扩展性,以及重用性或复用性。
4)封装后对于事物本身提高了安全性。
2、构造方法
1)构造方法又称为构造函数/构造器/Constructor
2)构造方法的“返回值类型”不需要指定, 也不能写void,写上就成了普通方法了
3)构造方法的方法名必须与类名保持一致;
4)构造方法作用:
*通过构造方法的调用,可以创建对象;
*创建对象的同时,初始化实例变量的内存空间【给实例变量赋值】
5)构造方法怎么调用?
*new 构造方法名(实参列表)
6)构造方法调用执行后,有返回值吗?
*每个构造方法实际执行结束后都有返回值,但“return 值”语句不需要写。构造方法结束时,java程序自动返回值;
并且返回值类型是构造方法所在类的类型。
7)实例变量是系统默认赋值,是在构造方法执行过程中初始化赋值的。
3、方法调用时的参数传递问题
*传递时,java只遵循一种语法机制,就是把变量中保存的“值”传递过去;
这个值有时是字面值;有时是另一个java对象的内存地址0x1234;
4、this关键字
1)this 是一个引用,是一个变量;this变量中保存了内存地址指向自身;this存储在JVM堆内存java对象内部。
2)创建100个java对象,每个对象都有this,也就是有100个this;
3)this可以出现在"实例方法"当中,this指向当前正在执行这个动作的对象。(this代表当前对象)
4)多数情况this可省略不写。
5)this不能在带有static关键字的方法中使用。(static的方法调用不需要对象直接使用类名,所以执行过程没有当前对象,也就不能使用this。)
6)this什么时候不能省略?
区分实例变量与局部变量时this不能省略。
7)this可以用在哪里?
*可以使用在实例方法中,代表当前对象【语法格式:this.】
*可以使用在构造方法中,通过当前构造方法调用其他构造方法【语法格式:this(实参);】
*** 重点【记忆】:this()这种语法只能出现在构造方法第一行
8)输出“引用”,自动调用引用的toString()方法。

5、
*没有static关键字的方法称为“实例方法”,实例方法怎么访问?“引用.”
*没有static关键字的变量称为“实例变量”
*注意:当一个行为/动作执行过程中需要对象参与,那么这个方法一定要定义为“实例方法”
*带有static的方法,既可采用“类名.”方式访问,也可采用“引用.”方式访问,但即使用“引用.”访问,实际上与引用指向对象无关。(此时引用为null不会出现空指针异常)
6、static
1)什么时候成员变量声明为实例变量?静态变量?
-所以对象都有这个属性,但这个属性值会随对象变化而变化【不同对象的这个属性值可能不同】
-所以对象都有这个属性,所有对象的这个属性值相同,建议定义为静态变量,节省内存开销。
*静态变量在类加载时初始化,内存在方法区中开辟。访问时不需要创建对象,直接使用“类名.静态变量名”的方式访问。
2)static修饰方法是静态方法,static修饰变量的静态变量;所以static修饰原始都是静态的,都可用“类名.”方式访问,(不建议用“引用.”)
3)static修饰的所有元素都是类级别的,与具体对象无关
4)静态方法中无法直接访问实例变量与实例方法;
5)方法什么时候定义为静态的?
方法描述的是动作,当所有对象执行这个动作时,产生的影响一样,那么这个动作不再属于某个对象的动作了,可以将其提升为类级别的动作(模板动作)。
6)大多数方法都定义为实例方法,因为一般一个动作在发生时都需要对象参与,但也有例外,例如:大多数“工具类”中的方法都是静态方法,因为工具类是为了方便编程,为方便方法调用,不用new对象是最好的。
7、static定义的具体代码块
1)语法格式:
static{
java语句
}
2)静态代码块在类加载时执行,且只执行一次
3)静态代码块在一个类中可以编写多个,遵循自上而下依次执行
4)静态代码块作用?
--与具体需求有关
--静态代码块是java为程序员准备一个特殊时刻——类加载时刻,若行为在此刻执行一定特殊出现,这段程序可放到静态代码块中。
5)通常在静态代码块中完成预备构造,先完成数据的准备工具。如:初始化连接池、解析XML配置文件……
8、实例代码块【了解】
1)实例代码块可以编写多个,遵循自上而下依次执行
2)实例代码块在构造方法执行之前执行,构造方法执行一次,实例代码块对应执行一次。
3)实例代码块也是java为程序员准备的一个特殊时机——对象初始化时机
四、继承、多态
1、继承(面向对象三大特征之一)
1)继承“基本”作用:代码复用。
继承 最“重要”作用:有了继承才有了“方法覆盖”和“多态机制”
2)继承语法格式:
[修饰符列表] class 类名 extends 父类名{
类体=属性+方法
}
3)java语言只支持单继承,一个类不能同时继承多个类。(c++支持多继承)
4)关于继承的以下术语:
B类继承A类,则:
A类称为:父类、基类、超类、superclass
B类称为:子类、派生类、subclass
5)java语言中子类继承父类继承哪些数据?
-私有的不支持继承;
-构造方法不支持继承;
-其他数据都可以被继承;
6)虽然java语言只支持单继承,但一个类也可以间接继承其他类,如:
C继承B,B继承A,A继承T,则C间接继承A、T类
7)java语言中假设一个类没有显示继承任何类,该类默认继承JavaSE库中提供的java.lang.Object类,一个对象与生俱来就有 Object类型中所有的特征。
2、方法覆盖/方法重写
1)方法覆盖又称为方法重写:override【官方的】/overwrite
2)什么时候使用方法重写?
*当父类中的方法无法满足当前子类的业务需求时,子类有必要将父类中继承过来的方法重新编写,即方法重写/方法覆盖;
3)满足什么条件方法会发生重写?
*方法重写发生在具有继承关系的父子类中
*方法重写时,返回值类型相同,方法名相同,形参列表相同
*方法重写时,访问权限不能更低,可以更高
*方法重写时,抛出异常不能更多,可以更少
4)注意:
*私有方法不能继承,所以不能覆盖;
*构造方法不能继承,所以不能覆盖;
*静态方法不存在覆盖;
*覆盖只针对方法,不针对属性;
3、多态【基础语法】
1)Animal、Cat、Bird三个类关系:
Cat继承Animal; Bird继承Animal; Cat与Bird没有继承关系
2)多态涉及的一些概念:
*向上转型(upcasting)
子类型——>父类型
又被称为:自动类型转换
*向下转型(downcasting)
父类型——>子类型
又被称为:强制类型转换【需加强制类型转换符】
*重点记忆:
无论向上转型还是向下转型,两种类型间必须要有继承关系。
没有继承关系,程序是无法编译通过的。
3)向上转型
向上转型只要编译通过,运行一定不会出问题。
4)向下转型
a.什么时候需要使用向下转型?
*当调用的方法是子类型中特有的,在父类型当中不存在,必须进行向下转型。
b.向下转型有风险吗?
*向下转型存在隐患,编译通过,运行可能出错。
Animal b=new Bird(); Cat c=(Cat)b;
以上程序运行时会出现java.lang.ClassCastException(类型转换异常)——总是在”向下转型时“发生。
c.怎么避免这个风险?
instanceof运算符,可以在程序运行阶段动态的判断某个引用指向的对象
5)instanceof
语法: 引用 instanceof 数据类型名
执行结果是布尔类型;
例如:b instanceof Animal
true表示 b引用指向的对象是Animal类型
false表示 b引用指向的对象不是Animal类型
6)java规范要求在向下转型【强制类型转换】前,使用instanceof
4、多态在实际开发中的作用
*降低程序耦合度,提高程序开展力;
*能使用多态尽量使用多态;
*父类型引用指向子类型对象;
核心:面向抽象编程,尽量不要面向具体编程。
OCP原则:对扩展开放,对修改关闭
五、final,包,super
1、final
1)final是一个关键字,表示最终的,不可变的。
2)final修饰的类无法被继承
3)final修饰的方法无法被覆盖
4)final修饰的变量一旦被赋值后,无法再重新赋值【不可二次赋值】
5)final修饰的实例变量必须手动赋值,不能采用系统默认值。
6)final修饰的引用,一旦指向某个对象后,不能再指向其他对象,那么被指向的对象无法被垃圾回收器回收。
final修饰的引用虽然指向某个对象后,不能再指向其他对象,但所指向的对象内部的内存是可以被修改的。
2、常量
1)final修饰的实例变量是不可变的,这种变量一般和static联合使用,被称为“常量”。
2)常量定义语法格式:
public static final 类型 常量名=值;
3)java规范要求所有常量名字全部大写,每个单词用下划线连接。
3、包机制
1)包:package,方便重新的过来,不同功能的类被分门别类放到不同软件包中,查找、管理比较方便,易维护。
2)包的定义:
-在java源程序的第一行编写package语句
-package只能编写一个语句
-语法结构: package 包名
3)包名的命名规范:
公司域名+项目名+模块名+功能名
4)包名要求全部小写,包名也是标识符
5)一个包对应一个目录
6)使用package机制后,该怎么编译?怎么运行?
-使用package机制后,Test类名变为:com.hfl.javase.Test
-编译:javac java源文件路径(生成class文件)
-手动创建目录,将class文件放到指定目录下——————》运行:java com.hfl.javase.Test
-另一种方式(编译+运行)
*编译:javac -d 编译后存放路径 java源文件路径
如:javac -d . *.java 编译当前所有java文件到当前目录下
7)import语句用来完成导入其它类,同一个包下不需要导入
java.lang.*系统自动导入,不需要import;
4、访问控制权限修饰符
1)访问控制权限修饰符来控制元素的访问范围
2)访问控制权限修饰符包括:
public 表示公开的,在任何位置都可以访问
protected 同包,子类
default(缺省) 同包
private 表示私有的,只能在本类中访问
3)访问控制权限修饰符可以修饰类、变量、方法……
4)当某个数据只希望子类使用,使用protected进行修饰
5)修饰符范围
private<缺省<protected<public
6)类只能使用public和缺省修饰符进行修饰。【内部类除外】
5、super
1)super
super能出现在实例方法和构造方法中。
super的语法是:“super.”、“super()”
super不能使用在静态方法中。
super. 大部分情况下是可以省略的。
super.什么时候不能省略呢?
父类和子类中有同名属性,或者说有同样的方法,
想在子类中访问父类的,super. 不能省略。
super() 只能出现在构造方法第一行,通过当前的构造方法去调用“父类”中
的构造方法,目的是:创建子类对象的时候,先初始化父类型特征。
2)super()
表示通过子类的构造方法调用父类的构造方法
3)当一个构造方法第一行既没有this() 又没有super()时,默认会有一个super();
表示通过当前子类的构造方法调用父类的无参构造方法,所以必须保证父类无参构造方法存在。
(最好手写父类的无参构造方法)
4)this()与super()不能共存,都只能出现在构造方法第一行
5)无论怎么折腾,父类构造方法一定会执行
6)super(实参)作用:初始化当前对象的父类型特征,并不是创建新对象,实际上对象只创建一个。
7)super关键字代表什么?
super关键字代表的是“当前对象”的那部分父类型特征
super不是引用。也不保存内存地址,不指向任何对象。
8)super的使用:
super.属性名 【访问父类的属性】
super.方法名(实参) 【访问父类的方法】
super(实参) 【调用父类的构造方法】
6、
* system.exit()————(终止程序的运行,退出JVM虚拟机)
* 实例变量赋默认值是在执行构造方法时赋值;
六、接口、抽象类
1、抽象类
1)抽象类:
类与类之间有共同特征,将这些具有共同特征的类进一步抽象形成抽象类;
由于类本身不存在,所以抽象类无法创建对象。
2)抽象类属于引用数据类型
3)抽象类无法实例化,无法创建对象,用来被子类继承;
4)final与abstract不能联合使用,两个关键字是对立的(final修饰的类不能被继承;抽象类主要用来被继承)
5)抽象类的子类可以是抽象类
6)抽象类虽然无法实例化,但抽象类有构造方法,这个构造方法是供子类使用的
7)抽象方法:
抽象方法本身没有实现的方法,没有方法体的方法。
public abstract void display();
*没有方法体,以分号结尾
*有abstract修饰
8)抽象类不一定有抽象方法;有抽象方法的一定是抽象类;
9)*****(重要)
一个非抽象的类继承抽象类,必须实现抽象类中的抽象方法----覆盖/重写,
这是java语法强行规定的,否则编译器报错。
作用:降低接口实现类对接口实现过程的难度,
将接口中不需要使用的方法交给抽象类完成,
这样接口实现类只需要实现需使用的方法即可。
2、接口(基础语法)
1)接口是一种"引用数据类型",编译后也是一个class文件
2)接口是完全抽象的。(抽象类是半抽象的);也可以说接口是特殊的抽象类。
3)接口定义语法:
[修饰符列表] interface 接口名{}
4)接口支持多继承,一个接口可以继承多个接口
5)接口只包含两部分内容:常量 、 抽象方法;
6)接口中的元素都是 public 修饰的(公开的)
jdk1.8添加了默认方法
7)接口中的抽象方法定义时 “public abstract” 可以省略,定义常量时的 “public static final” 可以省略
8)接口中的方法都是抽象方法,没有方法体,以“;”结尾;
9)<*****> 一个非抽象的类实现接口必须将接口中的所有方法加以实现(覆盖、重写)
10)一个类可以实现多个接口;
弥补了java的缺陷:java中类与类只支持单继承。实际上单继承是为了简单而出现的。
11)类与类之间叫继承,类与接口之间叫“实现”。
*继承使用 extends 关键字,实现使用 implement 关键字
*extends与implement可以共存,extend在前,implement在后
12)使用接口写代码时,可以使用多态(父类型引用指向子类型对象)
**调用其他接口中的方法需要转型(接口转型)
13)接口与接口之间进行强制类型转变时,没有继承关系也可以强转。(编译不报错)
但要注意,运行时可能会出现ClassCastException异常,需要加instanceof进行判断。
3、接口在开发中的作用
接口在开发中的作用类似于多态在开发中的作用
多态:面向抽象编程,不要面向具体编程,降低抽象耦合度,提高程序扩展性
(面向抽象编程————面向接口编程)
总结一句话:三个字“解耦合”
面向接口编程,可以降低程序的耦合度,提高程序的扩展力。符合OCP开发原则。
接口的使用离不开多态机制。(接口+多态才可以达到降低耦合度。)
接口可以解耦合,解开的是谁和谁的耦合!!!
任何一个接口都有调用者和实现者。
接口可以将调用者和实现者解耦合。
调用者面向接口调用。
实现者面向接口编写实现。
以后进行大项目的开发,一般都是将项目分离成一个模块一个模块的,
模块和模块之间采用接口衔接。降低耦合度。
4、类型与类型之间的关系
is a(继承)、has a(关联)、like a(实现)
is a:
Cat is an Anmal(猫是一个动物)
凡是满足 is a 的表示都可以设置为继承
A extends B
has a:
I has a Pen(我有一支笔)
凡是满足 has a 关系的表示“关联关系”
关联关系通常以“属性”的形式存在
A{
B b;
}
like a:
Cooker like a FoodMenu(厨师像一个菜单)
凡是满足 like a 的表示“实现关系”
实现关系通常是:类实现接口
A implements B
5、抽象类与接口之间的区别
抽象类是半抽象的;接口是完全抽象的;
抽象类中有构造方法;接口中没有构造方法;
接口与接口间支持多继承;类与类之间只能单继承;
一个类可以同时实现多个接口
一个类只能继承一个抽象类(单继承)
接口中只允许出现常量和抽象方法;
接口一般是对“行为”的抽象