《之前的复习》
第一天:
Java的技术架构:JavaEE、JavaSE、JavaMEJava的跨平台原理:依赖于JVM。
JRE和JDK区别:
JRE是Java的运行环境,给用户使用。
JDK是Java的开发工具集。是提供给开发人员使用。
下载和安装JDK www.oracle.com
配置环境变量path:
path是给操作系统使用,path配置操作系统可以直接执行的程序或命令。只要把可执行的程序或者命令配置在path中,这时当我们在dos窗口中来执行这个程序或命令的时候,操作系统就会在当前的目录下超找有没有这个可执行的程序,如果有就执行,如果没有就去path配置的路径下查找,并执行。如果path中也没有,就提示不是内部或者外部命令。
我们需要把jdk的安装目录中的可执行命令配置到path中。是可以在任意目录下去运行JDK中的可执行程序。java javac
临时配置,可以使用set命令在dos窗口中临时设置path所指的路径。
set path=路径
set path=
删除path中的配置的路径
书写helloworld程序
class Demo
{
public static void main(String[] args)
{
System.out.println(“aaaaaa”);
}
}
Java程序写完之后,它源文件。源文件需要经过javac进行编译,编译之后会生成class文件(字节码文件),在使用java命令运行这个class文件
java程序的错误分成2部分:
编译时的错误:源代码中有语法错误
运行时的错误:这时程序在运行的时候,导致JVM运行程序发生的一些问题。
配置classpath:
classpath是JVM使用的。classpath中配置的JVM可以直接执行的class文件。
classpath=.;路径
第二天:
注释:给程序进行解释说明。可以调试程序
注释分类: 单行注释// 多行注释 /* */ 文档注释/** */
关键字:被Java语言赋予特定含义的一些单词或者字母的组合。
标识符:用户根据自己的需求定义的一些字母数字_$组合在一起的一些名称。
作用:可以用作类名、方法名、变量名、数组名、常量名、包名、接口名等
标识符不能以数字开始。
常量:
整数:负数、零、正数
小数:
字符:要求必须使用单引号引用起来,一般要求中间有且只有一个字符。 转义字符 ‘\ ’
布尔:真假值
字符串:需要使用双引号引用起来
null:null
进制:二进制、八进制、十进制、十六进制
变量:表示的内存中的空间。
数据类型:8种基本类型
byte short int long 整数默认是int类型
float double 默认double
char
boolean
定义变量:
数据类型 变量名; 声明在内存中开辟一片空间,这个空间的类型就是定义是书写的类型。并且这个空间中只能存放规定的类型
类型转换:
隐式类型转换:
byte b = 123;
强制类型转换:
运算符:
算术运算 + - * / % ++ --
int i = 3;
i = i++;
赋值运算: = 功能是把右侧的结果赋值到左侧的空间 += -= *= /= %=
a+=b a =a +b
关系运算:运算结果是boolean值 > >= < <= != ==
逻辑运算 : 运算结果是boolean值
&& & || | ^ !
位元算:对数据进行二进制数位运算
& | ^ ~ << >> >>>
1001
& 1100
-------------
1000
三元运算: 表达式1 ? 表达式2 : 表达式3
当表达式1为true 就把表达式2作为三元元算的结果
当表达式1为false 就把表达式3作为三元元算的结果
第三天
语句:
判断结构
if( 条件 ){
}
if( 条件 ){
}else{
}
if( 条件 ){
}else if( 条件 ){
}else if( 条件 ){
}
else if( 条件 ){
}else{
}
多分支结构
switch( 常量 ){ byte short int char enum String
case 常量:
语句;
break;
case 常量:
语句;
break;
case 常量:
语句;
break;
case 常量:
语句;
break;
default
语句;
break;
}
循环结构
三大循环:
while( 条件 ) {
}
do{
}while( 条件 );
for( 表达式1;表达式2;表达式3 ){
}
循环嵌套:
for( ) //外循环
{
for(){ //内循环
}
语句;
语句;
语句;
}
break和continue
第四天、第五天
方法(函数):
方法的定义格式:
修饰符 返回值类型 方法名 ( 参数类型 参数名,参数类型 参数名,参数类型 参数名 )
{
}
调用: 方法名( 实参 )
定义方法时的2个明确:
1、明确方法要不要接收参数
2、明确方法的返回值类型
注意:当方法中没有返回值的时候,方法中不能出现带有参数的return语句 retturn ; return 值 ;
方法的重载:
在同一个类中出现了同名的方法,但参数列表不同。overload 重载和返回值类型没有关系。
在描述功能的时候,功能相同,但功能接收的参数不同。
数组:
数组主要解决可以开辟多个空间,来存储更多的数据。
数组中存放的元素类型都是相同的。并且数组定义好之后,它们的长度固定。数组拥有下标(索引index),从0开始,到length-1结束
定义数组:
元素类型[] 数组名 = new 元素类型[数组长度];
int[] arr = new int[4];
元素类型[] 数组名 = {元素1,元素2,元素3,......};
数组的操作:
遍历 使用循环提供数组的下标 然后通过每次循环提供的不同的下标,再结合数组名,就可以访问数组的这个空间。
求最值:在计算最值的时候,需要假设一个值为最值,要求假设的这个值,一定是数组中的某个元素。然后遍历数组,取出数组中的每个值,和假设的值做对比。
求和值:在未计算和值之前,定一个变量,来统计每次的和。这个变量初始值一般为零。
计数器:用来记录满足条件的数据的个数。这个变量初始化值也是零
排序:
选择排序
int[] arr = new int[10];
for( int i=0 ; i<arr.length-1 ; i++ ){ //它就是在提供每次你到底要选择那个空间来和后面剩下的空间做比较的下标
for( int j=i+1 ; j < arr.length ; j++ ){ //内循环是提高外循环身后剩下的所有空间的下标,因此它的起始值,应外循环身后的第一个空间的下标
if( arr[i] < arr[j] ){
int temp = arr[i];
arr[i] = arr[j];
arr[j] =temp;
}
}
}
冒泡排序
for( int i=0;i<arr.length-1;i++ ){ //外循环控制的共计相邻元素需要比较轮数
for( int j=0;j<arr.length-i-1 ;j++ ) {
if( arr[j] > arr[j+1] ){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] =temp;
}
}
}
折半查找:
要对数组进行折半查找,要求数组一定是有序的。
Arrays
二位数组:
数组中的数组。
定义格式:
元素类型[][] arr = new 元素类型[二位数组长度][每个一位数组长度];
二位数在使用的时候需要注意必须获取到二维数组,然后在去遍历每个一维数组
面向对象
面向对象是思想:
在需要完成某个任务,或者需求的时候,首先不要想着自己如何动手去实现,而是思考有没有已经存在的事物,或者个体可以完成我们的需求。如果有,就直接调用这个事物或者个体,来完成需求即可。
后期在完成Java中的一些任务和需求的时候,我们也要按照面向对象的这种思想来操作。我们先不要想着自己如何去写代码实现具体的每个步骤和功能,而是找有没有已经存在的类可以完成这个功能,有就创建对象,调用功能,完成需求。如果没有,这时自己就封装这个样一个可以完成需求的类,以后再要使用,就可以直接调用。
Java中的对象体现:
Java中使用一个类来描述我们身边的事物:
生活中的事物,一般都有特点:
事物的属性
事物的行为(功能)
我们就需要把生活中的事物,使用java代码来体现。
这个事物就可以使用Java中的类来描述。事物中的属性可以使用Java中的变量来描述。而事物的行为(功能)使用Java中的方法来描述。
这些变量和方法,只要封装到描述当前这个事物的类中即可。
这时再使用Java中的new关键字创建这个类的个体(实例、对象)就可以调用封装在其中的内容。
类和对象的关系:
封装:把不需要外界直接访问的内容都隐藏起来。然后通过公共的方式让外界间接的来访问。
private关键字:主要用来修饰类中的成员。被private关键字修饰的成员,只能在本类中访问,也就是说在类以外的地方无法访问。
类中的成员变量一般都会private,然后对外提供get或者set方法来给这个成员变量设置或获取值。
构造方法:
主要是在创建对象的时候给当前这个对象的成员变量进行初始化的。
构造方法什么时候执行:
是在成员变量默认初始化完成之后由当前的这个对象调用的。
构造方法可以调用一般方法吗?可以。在构造方法执行的时候对应已经存在了,只是调用构造方法给当前对象进行初始化而已。
一般方法能调用构造方法吗?不能。一般方法在执行的对象早已创建完成了。构造方法已经执行结束了。构造方法是在对象创建过程中执行的,对象创建完,构造方法就执行结束。
构造方法之间的调用:
在同一个类中,调用其他的构造方法需要使用this关键字。
格式:this( 实参 ); 调用本类中的其他构造方法
注意:构造方法之间不能形成嵌套调用。
this:this代表当前对象。在方法中,非静态的方法都需要对象来调用。在这些非静态方法中都会有一个隐式的this变量,用来记录当前调用这个方法的那个对象
构造方法中也有this,而构造方法中的这个this代表的是当前正在创建的那个对象
static:
static关键字主要用来修饰类中的成员。被静态修饰的成员可以被类名直接调用,也可以被对象调用。
静态修饰的成员,不能调用非静态,因为静态是在类加载的时候就加载完成,就已经准备好了,可以直接运行。而非静态的成员,必须依赖于对象。而类加载完,对不一定存在。
但非静态的可以调用静态。非静态的在执行的时候,对象都已经存在了,对象存在就说明类早就加载完成。
静态的成员方法中不能存在this和super关键字。
当某个成员变量是所有对象所共享的是,这时这个成员变量就可以被静态修饰。
当类中的成员方法,没有访问到对象的特有数据(对象中的成员变量),这个成员方法也可以被静态修饰。
静态代码块:
给类进行初始化的。当在程序启动的时候,就要把一些初始的数据准备完成,这些准备数据的代码就可以写静态代码块中。
加载数据库驱动和数据连接。经常会放在静态代码块。
它会在类加载的时候,静态的成员变量显示初始化完成之后执行。
static{
{
}
}
构造代码块:
是给所有的对象进行初始化的。只要创建对象,它都会执行。当一个类中有多个构造方法时,并且这些构造方法中有相同的初始化代码,这些代码在每个构造方法中都要书写,代码严重重复。可以把这些相同的给对象初始化的代码抽取到构造代码块中。
它是在创建对象的时候,在对象的成员变量显示初始化完之后执行。
{
{
}
}
局部代码块:
它只能存在局部位置中。限定变量的生命周期
类加载和对象的创建流程:
类加载:
1、当在程序中要使用某个class文件的时候,如果方法区中没有这个class文件,那么JVM就会在当前目录(如果配置classpath,就会在classpath目录)下查找对应的class文件,并加载。
2、在加载这个class文件的过程中,非静态的内容会被加载到方法区的非静态区域中,而静态的内容会被加载到静态区中。
3、在加载类中静态成员变量的时候,会先把所有的静态都加载到内存中之后,开始给所有的静态成员变量默认初始化。(作业第一题)
4、当类中的所有静态成员变量默认初始化完成之后,开始给这些静态的成员变量显示初始化
5、当所有的静态成员变量显示初始化完成之后,开始执行这个类中的静态代码块。
6、当静态代码块执行完成之后,这个class文件加载完成。
对象创建流程:
1、使用new关键字创建对象,首先需要在堆中给其分配内存空间,分配内存地址
2、给对象中的所有非静态的成员变量进行默认初始化
3、开始执行对应的构造方法,这时就把对应的构造方法加载到栈内存中运行
4、在构造方法中有隐式三步
4.1、开始执行super();
4.2、给对象中的成员变量显示初始化
4.3、执行构造代码块
4.4、当前构造方法中的代码执行
5、对象创建完成,构造方法弹栈。
单例设计模式:
设计模式是解决问题需求行之有效的方案或者策略。
23种设计模式:
学习设计模式,需要明确每个设计模式到底解决的是什么问题。当我们遇到响应的需求和问题的时候,直接套用这个设计模式即可。
单例设计模式解决的问题:
保证当前程序这个对象是唯一的。
单例设计模式的书写步骤:
1、私有构造方法
2、创建本类对象
3、对外提供访问本类对象的方法
单例设计模式代码体现:
懒汉式
class Single
{
private Single(){}
private static Single instance = null;
public static Single getInstance()
{
if( instance == null )
{
instance = new Single();
}
return instance;
}
}
饿汉式
class Single
{
private Single(){}
private static Single instance = new Single();
public static Single getInstance()
{
return instance;
}
}
一个类中都能够书写什么内容:
成员变量(静态和非静态)
成员方法(静态和非静态)
构造方法
静态代码块
构造代码块
成员内部类(静态和非静态)
继承:Java中的类是描述事物的。生活中的事物它们都会存在一些继承关系。
Java中的继承,就是让类和类之间产生了关系。由于类是描述事物的,在Java中让类和类之间产生继承关系的时候,一定要保证这2个类甚至多个类之间一定要属于同一类事物。
继承的好处:
让类和类之间产生关系,为多态提供前提。父类定义好的行为功能,子类可以直接使用。
继承的弊端:
打破了封装性。
继承的顺序:
1. 将父类对象加载到内存中,再将子类对象加载到内存中
2. 在堆内存中加载子类对象
3. 加载成员变量(先父后子)
4. 成员变量默认初始化(先父后子)
5. 运行子类构造函数
{有隐式三步
Super(),
调用父类构造函数。
成员变量显示初始化
构造代码块执行
构造函数体
}
Java中不支持多继承,会出现调用的不确定性。但支持多重继承。
继承中的成员的变化:父类中描述都是这个事物体系中共性的内容。
1、成员变量: 子父类中出现了同名的成员变量。在子类中如果直接使用成员变量名,那么访问的是子类自己的成员变量。
如果要使用父类的成员变量可以使用super.成员变量名
2、成员方法:父类定义好的功能,子类可以直接拿来使用。
当子类和父类中出现一模一样的方法时,这种现象称为方法的复写override。
当父类定义好了功能,子类中也有这个功能了,但是子类的功能体和父类有些不同。这时子类就可以延用父类的方法定义格式,重写这个方法的方法体。
方法复写的注意事项:
1、子类复写父类的方法时,要求子类的方法定义格式(返回值类型,方法名,参数列表)必须一致
2、子类复写父类的方法时,要求方法的权限访问修饰必须大于或等于父类的权限
3、静态只能复写静态。在子类复写父类的方法时,子类只能修改方法的访问权限,而不能修改方法的访问方式。
4、私有的内容不参与复写。
3、构造方法:
构造方法不会出现复写现象。
子类在创建对象的时候会调用父类的构造方法。因为在子类进行初始化的时候,必选先要知道父类是如何进行初始化的。子类在继承父类的时候,这时创建子类对象,并没有创建父类对象,那么父类的成员变量会在创建子类对象的时候随着子类对象的出现,在子类对象的堆中存在父类的成员变量。
final关键字:
主要用来修饰类,成员,变量
final修饰的类不能被继承。final修饰的方法不能被复写。final修饰的变量为常量。
多态:把一种事物使用多种表现形态表示出来。但是这个事物的对象只有一个。
把一个对象使用另外一种形态来描述出来。这时这个对象就已经多态。这个对象可以用它本身的形态来展示,也可以使用另外的其他形态来展示。
把这种现象就称为当前这个对象(事物)的多态性
在Java中的多态体现:
子类的对象赋值给了父类的引用或者接口的引用,这时就是把这个子类对象使用父类类型或者接口类型来表示。这时就形成了多态。
多态的好处:
隐藏了子类的特有功能,我们不需要关注子类,只需要看父类或者接口中的方法。
在以后查看api的时候,如果有一个继承体系,这时我们需要查看继承体系的顶层内容,如果顶层定义的功能就能够满足我们的需求,这时
就直接创建任意一个子类对象,然后赋值给这个顶层的引用即可。
多态弊端:
由于把子类使用父类或接口类型来接收。导致只能使用父类定义的共性功能,而无法使用子类特有的功能。
如果我们要使用子类的特有功能怎么办?
向下转型:
当已经发生了多态现象,这时需要使用子类的特有内容,就需要把这个父类引用转成子类引用。
注意向下转型的时候,一定要保证被转的那个父类引用所指的对象一定是我们现在要转的类型。如果不是就发生ClassCastException
如何避免这个异常:
在使用向下转型之前,一定要做健壮性判断
引用 instanceof 类型
向上转型:
把子类对象赋值父类引用或者接口引用时就发生了向上转型
多态的前提:必须有继承或者实现
多态中的成员变化:
成员变量
在使用多态的时候,使用到了成员变量,编译时期要看引用所属的类中是否有这个变量
运行时期依然使用的引用所属类中俄成员变量
编译运行都看左边(赋值号左边)
成员方法
编译时期要看引用所属类中是否有这个成员方法。
运行时期使用的对象所属类中的方法。
编译看左边,运行看右边
静态方法
编译时期看引用所属类中是否有这个静态成员方法。
运行时期依然使用引用所属类中的静态成员方法。
编译运行都看左边
抽象类和接口:
抽象类依然是个类,只不过这个类在描述事物的时候,发生事物中有些功能无法直接描述清楚,只能描述这个事物基本功能定义格式,但是不能把这个功能体书写清楚。这时我们就可以使用抽象方法来描述这个功能。由于方法位于类中。导致这个类中有了抽象方法,那么这个类就必须变成抽象类。
抽象类一定是父类吗?
一定是。但不一定是顶层父类。 抽象类中一定描述事物体系共性内容
抽象类可以创建对象吗
不可以。
抽象类中有构造方法吗?
有,给子类进行初始化使用的
抽象类可以没有抽象方法吗?
可以。不让创建本类对象。它用在设计模式中的适配器设计模式
抽象关键字不能和那些关键字共存
static
private
final
接口:
接口的出现解决问题:
普通的类,还是抽象类都是在描述事物体系。事物在后天的进化中或者训练中可以获得一些不属于这个事物体系本身的固有行为。
这时就可以把这些额外的不属于事物体系的功能抽取接口中,那个事物具备这个额外功能,就让它去实现这个接口即可
接口的出现给事物体系增加额外功能。
接口的出现还有另外一种功能,就是定义规则,一方实现规则,另外一方就可以根据这个规则来使用实现类。
Java中的接口支持多继承,类和接口实现关系,并且可以多实现。
内部类:
内部类也是在描述事物的。只不过这个事物要依赖于其他事物的内部。这时这个事物就可以使用内部类来描述。
内部类的定义位置:
外部类的成员位置
如果把一个内部类放在外部类的成员位置上,这时就可以把这个内部类当作外部类的成员来看待,就可以使用成员修饰符类修饰这个成员位置上的内部类。
注意:放在成员位置上没有被私有的内部类,它可以在外部类以外的地方访问。访问的时候需要先创建外部类对象,在创建内部类对象。
在成员位置上的非静态内部类中,不能定义静态成员。
外部类的局部位置
放在局部位置上的内部类,只能在这个局部位置上访问。
局部内部类访问局部变量时,这个变量需要被final修饰
匿名内部类:
格式:
new 类名(); 创建一个对象
new 父类或者接口( ) {
} ; 匿名内部类
匿名内部类中都会有方法的复写或者方法的实现
class 类 extends 父类
{
}
class 类 implments 接口{
}
new 类();
Object类:
所有类的父类。它中定义了所有类的最共性的方法。所有的子类都可以使用其中的方法
equals 原生的equals方法在比较两个对象的时候,依然使用的对象的内存地址在比较,而我们在比较对象的时候,一般都需要根据对象的特有数据进行比较
经常在书写一个类的时候,都要复写equals方法
toString:把对象的表现形式变成字符串 原生 类型@哈希值 [I@32789EF
因此在书写类的时候,也要复写toString建立适合当前这个类的真实表现形式