目录:
一、Java基础知识
1、Java的语言特性:
来自与Java白皮书:
▶ 简单性
▶ 面型对象(在Java的世界里,一切皆为对象)
▶ 分布式
▶ 健壮性
▶ 安全性
▶ 体系结构中立
▶ 可移植性
▶ 高性能
▶ 解释性
▶ 多线程
▶ 动态性
2、Java的注释:
对于Java有三种注释:
1、单行注释:// 注释内容
2、多行注释:/* 注释内容 */(不能嵌套使用)
3、文档注释:/** 文档注释 */
3、标识符:
在程序中,有用户给类名、方法名或者变量所取的名字。
4、关键字:
关键字是Java语言提前定义好的,有特殊含义的标识符,或保留字
5、数据类型与变量:
1)、常量:
在程序运行期间,固定不变的量叫做常量。
分别有:★ 字符串常量
★ 整形常量
★ 浮点型常量
★ 字符常量
★ 布尔常量
★ 空常量
2)数据类型:
在Java中分为:基本数据类型和引用数据类型
3)、变量:
概念:对于经常改变的内容,在Java中,我们称之为变量。
语法格式:
数据类型 变量名 = 初始值;
比如:
int a = 10;
6、类型转换:
在Java中,当参与运算数据类型不一致时候,会进行类型类型转换。
分为:自动类型转换 和 强制类型转换
自动类型转换(隐式):代码不需要处理,在代码编译的时候,编译器就会自动的转换类型。
特点:从小范围转到大范围会自动转换。
int a = 10;
long b = 100L;
b = a;//自动类型转换,a与b都为整形,b大,a小
强制类型转换(显式):代码需要进行处理的,不能自动处理的。(可能会使数据丢失,在转换 的时候)
特点:从大范围转到小范围就需要强制类型转换。
int a = 20;
long b = 200L;
a = (int) b;//强制类型转换
7、类型提升:
概念:在不同的类型之间在进行运算的时候,数据类型小的会提升到数据类型大的。
在类型提升当中有几个特殊要注意的类型:byte,short等。(他们的字节都小于4)
我们来看:
byte a = 10;
byte b = 20;
byte c = (byte) (a + b);
byte+byte会先转换为int类型,再往回转换就需要强转了。
8、运算符:
我们直接看表格就可以了:
9、输入与输出:
1)、输出:
输出到控制台,对于Java来说其有三种输出的方式:
1、System.out.println(msg); //输出带换行
2、System.out.print(msg); //输出不带换行
3、System.out.printf("format", msg); //格式化输出,和C语言的输出相似
2)、输入从键盘:
使用Scanner 来读取字符串/整数/浮点数
多次输入:
10、逻辑控制表达式:
这个我们在C语言的时候就有所了解了,所以这里我们就简单的看一下逻辑图就可以了:
在这里我们来看一下,在Java中如何实现有系统随机获得随机数:
11、方法的使用:
Java中的方法就和C语言中的函数差不多,但是呢,在Java中我们没有指针,所以我们在单纯用方法的传参来改变实参的值是不好实现的,不能在传的形参上改变实参的值。
方法定义:
修饰符 返回值类型 方法名称(参数类型 形参) {
//方法体
return 返回值;
}
1)、重载:
在方法中,我们有一个重要的知识点,就是方法的重载。 我们来看看什么是重载:
想要实现方法的重载,我们要注意:
1、方法名相同。
2、参数列表必须不同
3、与返回值的类型无关
重载呢,会是方法名字相同,只需要注意传入的参数类型,就可以调用想要调用的方法了。
2)、递归:
自身中包含了自己,并且要有结束条件,要不然就会进入死循环,一直开辟空间,致使资源崩溃。
我们来举个例子:
12、数组:
1)、什么是数组:
数组就是相同类型元素的集合,并且空间是连在一起的,其起始坐标为 0,也就是数组的下标。
2)、数组的创建
数组中存放的类型[ ] 数组名 = new 数组中存放的类型[数组的个数];
比如:
int[ ] array = new int[10];
3)、初始化:
1、动态初始化:
在创建数组的时候,直接指定数组中的数组个数。
2、静态初始化:
在创建初始化的时候,省略 new 数组中存放的类型[数组的个数],使用{data1,data2,data3}。
比如:int[ ] array = {1,2,3,4,5,6,7};
对于静态初始化也可以这样写 int[ ] array = new int[ ]{1,2,3,4,5,6,7};
数组如果没有初始化,默认的初始化boolean为false,引用类型为null,其余为0.
4)、数组的访问与遍历:
数组在内存中是一段连续存在的空间,空间的编号从0开始,该编号就是其下标,是依次递增的,数组可以通过下标来访问任意位置的下标。
比如:
但是我们在访问数组的时候呢,我们不要使其访问越界。
我们可以使用循环来遍历数组的所有元素:
我们来看简便的写法: 在Java中也有一个新的for循环访问,for-each 循环:
5)、数组的应用场景:
对于数据的保存:
public static void main(String[] args) {
int[] array = {1,2,3,4};
for (int arr : array) {
System.out.println(arr);
}
}
作为函数的传承:
在之前我们是不是说明了,对于Java我们没有指针,所以改变形参不能使实参进行改变。
但是我们使用数组是可以改变的,因为我们的数组是引用类型,所以可以改变。
作为函数的返回值:
6)、二维数组:
对于二维数组来说,其实本质上就是数组,其每个元素是每一个数组。
语法:
数据类型[ ][ ] 数组名称 = new 数据类型[行数][列数] {初始化数据};
比如:
13、类和对象:
1)、类的定义和实例化:
类就是对于一个对象的描述的。在我们Java中定义一个类的时候要使用到class关键字。
类的定义格式:
class 类名 {
// 字段(属性)或 成员变量
// 成员方法 或 行为
}
注意:
类名要用大驼峰
不能带static关键词
当我们定义了一个类,就相当于在计算机中定义了一种新的类型。当我们用类创建对象的过程中,称为类的实例化 。在Java中采用new这个关键词,来配合类名类来实例化对象。
我们来看看如何实现:
注意:
1、使用 . 来访问对象中的属性和方法。
2、同一个类可以创建多个实例。
2)、类和对象的说明:
1. 类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员。
2. 类是一种自定义的类型,可以用来定义变量。
3. 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量。
3)、this的引用:
但我们的形参名和成员变量相同的时候,我们怎么分辨谁是谁呢?这时候我们就使用this关键词了。那么 this 又是什么呢?
this是引用当前对象的关键词,在成员方法中,我们访问其成员变量的操作,都是通过该引用去访问的。
我们看看是怎么使用的:
this 的引用特性:
1、this的类型,就是哪个对象调用就是哪个对象的引用类型
2、this只能在“成员方法” 中方法
3、在 “成员方法” 中,this只能引用当前对象,不能在引用其他对象
4)、对象的构造方法和初始化:
对于构造方法来说,是一种特殊的方法,在我们构造方法时,我么需要注意的是:
1、名字必须与类名相同
2、没有返回值类型,尽管是void也不行
3、创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
4、构造方法是可以重载的
5、如果用户没有显示定义时,编译器会生成一份构造方法,生成默认方法一定是无参的
在这里我们要注意,在我们定义之后,编译器不会再生成
6、构造方法中,可以通过this调用其他构造方法来简化代码
在这里我们注意 this() 构造方法中第一条语句,不能想成闭环
我们来看看如何想成构造:
对于初始化类说呢,我们有两种初始化方法,默认初始化 和 就地初始化
默认初始话:
比如我们上面举的例子就是默认初始化。
Student student = new Student();
就地初始化:
这个就是就地初始化。
5)、对象的打印:
如果我们想要打印对象的属性我们要如何才能打印呢?我们使用 toString 方法。在使用时我们需要再对象中重写toString方法:
6)、static 成员:
在Java中呢,被static修饰的成员,称之为静态成员,也称之为静态成员,其不属于某个具体的对象,是所有对象的所共享的。
(1)、static修饰成员变量:
static修饰的成员变量,称之为静态成员变量。
其不属于某个具体的对象,是所有对象所共享的。
1、对于静态成员对象,既可以通过对象访问,也可以通过类名访问,但是更推荐使用类名访问
2、类变量存储在方法区当中
3、生命周期伴随着类的一生
我们来看看怎么实现的:
(2)、static修饰成员方法:![](https://i-blog.csdnimg.cn/direct/9ca67f4219ec479c8e1921f37457097a.png)
Java中,被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员一般是通过静态方法来访问的,在我们的静态方法中我们不能调用非静态成员变量,同时不能存在this这个关键词。
(3)、static成员变量初始化:
静态成员变量的初始化分为两种:静态代码块初始化 和 就地初始化
1、就地初始化: 这个就是就地初始化。
2、静态代码块初始化:
一般用于初始化静态变量。
7)、代码块:
在Java中,使用 {} 定义的一段代码称为代码块。
普通代码块:
对于这个呢,我们是经常使用的,并且是十分的简单的。在方法中的
构造代码块(实例代码块):
构造代码块一般用于初始化实例成员变量。定义在类当中的,并不能有修饰符。
静态代码块:
使用static修饰的代码块就是静态代码块,一般用于初始化静态成员变量。
8)、内部类:
在Java中呢,可以将一个类定义在另一个类或者方法的内部,其前者我们称为内部类,后者我们称外部类。
对于内部类来说,我们的内部类分为:实例内部类 、静态内部类、局部内部类、匿名内部类。
实例内部类:
未被static修饰的类,我们成为实例内部类
对于在main函数中创建实例内部类对象的时候,我们这么写:
静态内部类:
被static修饰的内部类为静态内部类。
局部代码块:
定义在外部类的方法或者{}中,该种内部类只能在其定义的位置使用,对于这个代码块我们使用的非常的少。
匿名内部类:
![]()
14、面向对象的三大特性:
面向对象有三个特性分别为:封装、继承、多态。 下面我们来简单的复习一下:
1)、封装:
封装的概念:对于封装来说呢,将数据和操作数据的方法进行有机的结合,隐藏对象的属性和实 现的细节,仅对外提供接口来和对象进行交互, 比如我们的电脑来说呢,我们的开 机,只提供我们使用但是我们看不见它的实现方法。
在Java中,我们对于实现封装主要通过类和访问修饰限定符来实现的:就是类可以数据和封装的数据方法结合在一起。
在Java中呢,我们提供了四种访问修饰限定符:private、default、protected、public四种访问修饰限定符。我们再来看看这个图片:
我们在上面看见了包的这个关键字,那么我们接下来看看什么事包:
1、包:
包的概念:为了更好的管理类,把多个类收集在一起成成一组,称之为软件包。
所以在Java中我们也是引入了包,包是对类、接口等的封装机制的体现,是一种对类和接口等的很好的组织方式,在同一个工程中允许存在相同的类名,但要在不同的包中。
导入包中的类:
在Java中我们使用import语句进行导入包。
我们也可以这样写:
这样可以直接使用 java.util 里面的其余的包。但是呢,我们在这样写的时候呢,我们要注意防止出现冲突,比如这样:
因为在 util 和 sql 中都有Data的包,因此编译器不知道我们调用的是哪个。
在Java中我们可以使用 import static 来导入包中静态的方法和字段。
自定义包:
这个呢就是自定义包的流程:
我们使用包和上面接受介绍的访问修饰限定符类配合组成封装。
2)、继承:
继承的概念:继承是专门用来进行共性的抽取 ,以达到复用的作用。
比如呢:我们的 猫 和 狗 都是动物,所以我们可以使其动物作为父类,猫和狗为子类。
(1)、继承的语法:
在Java中如果要表示类的之间继承关系的话,我们要使用 extends 关键词。
修饰符 class 子类 extends 父类 {
//........
}
当我们在继承父类后 ,我们要在其子类添加一些我们特有的类。要不就相当于没有任何意义,要体现出和父类的不同。
(2)、成员的访问:
子类中访问成员变量:
1、子类和父类不存在同名的成员变量:
可以直接访问父类中的成员。
2、子类和父类存在同名的成员变量:
如果想要访问父类中和子类同名的成员变量的话要用到 super 关键词:
子类中访问父类的成员方法:
1、成员方法名字不同:
2、成员方法名字相同:
如果想要访问父类中和子类同名的成员方法的话要用到 super 关键词,和访问成员变量是一样的使用的。
这里要注意,对于super关键词来说,只能在非静态方法中使用。
(3)、子类构造方法:
对于子类构造方法来说,需要先调用父类的构造方法,然后再执行子类的构造方法。
我们来看看子类构造方法:
在这里的时候呢,我们对于 super 关键词这里还有一个用法,我们用super关键字调用父类的构造方法。
这个呢就是这个作用,但是呢,当我们没有写的时候,编译器会自动调用。
对于这个 super() 必须是要在第一行语句。
(4)、继承的方式:
单继承:
多层继承:
不同类继承同一个类:
(5)、final关键词:
final 关键字可以修饰变量、成员方法、及类。
1、final 修饰变量:
当修饰变量的时候,使其变量表示为常量。
2、final 修饰类:
当修饰类的时候,表示此类不能被继承。
3、final 修饰方法:
当修饰方法的时候,表示该方法不能被重写。
对于重写来说,我们会在多态中了解到,我们马上就会看到。
(6)、继承和组合:
继承的表示对象的方式是:is - a 的关系:比如 狗是动物,猫是动物这种。
组合的表示对象的方式是:has - a 的关系:比如 汽车
在汽车中呢,我们的汽车成员变量是 轮胎类、轮胎类等。
3)、多态:
多态的概念:
就是当我们去完成某个行为时,当不同的对象去完成时会产生不同的状态
比如 狗吃狗粮,猫吃猫粮
多态的实现条件:
1、必须在继承的条件下
2、子类必须要对父类的方法进行重写
3、通过父类的引用调用重写的方法
来看看是怎么实现的:
我们可以看到,不同的类调用eat方法的时候,会执行不一样的结构
那么我们接下看看,这个多态当中我们应用到了哪种知识:
(1)、重写:
概念:
也可以称之为覆盖,重写是子类对父类的非静态、非private修饰、非final修饰、非构造方法等的方法进行重新编写。返回值和形参都不需要改变。
在重写里面,我们还有两个很重要的概念:
静态绑定:也为前期绑定,即是在编译时,根据用户所传递的实参类型就已经确定了具体需 要调用哪种方法。比较典型的为:重载。
动态绑定: 也可称为后期绑定,即是在编译时,不能确定方法的行为,需要等程序运行时才 能确定方法。
(2)、向上转型和向下转型:
向上转型:
就是创建一个子类对象,来当做父类的对象使用。
对于向上转型呢,我们有三种方法来实现这种操作,我们在来看看:
1、 直接复制:
2、方法的传参:
3、作为方法的返回值:
向上转型的优点:
可以使代码的实现更加简单灵活。
向上转型的缺点:
不能调用子类中所特有的方法。
向下转型 :
在我们向上转型为父类对象的时候,在转型为子类的方法就是向下转型。
但是对于向下转型来说呢,有时候呢我们在向下转型的时候呢,可能会是向上转为父类之后,再由父类向下转换为子类的时候呢,可能转换的不是原来的子类,这样就会出错。
那么我们这个时候呢,我们就要借助一个关键词了:instanceof 。
我们再来复习一下如何使用:
对于instanceof这个关键词想要了解更多的话,可以去这里看看:
https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.20.2
(3)、多态的优缺点:
优点:
1、可以是代码降低其 “圈复杂度” ,避免大量的使用 if-else 方法。
2、可以使代码的可扩展能力变得更强。
缺点:
1、会使代码的运行效率降低。
在使用多态的时候,要避免在构造方法调用多态方法。
15、抽象类:
在了解概念之前呢,我们在吗面向对象的概念中,所有的对象都可以通过类来创建,但是不是所有的类都可以完整的描述一个对象。
概念:
所以我们把上面这种不能描述一个完整的对象的类,称之为抽象类。
比如我们上面的 Animal 类就不能完整的描述一个对象 ,它描述不了Dog类中的bark()这个方法。
在抽象类当中我们要使用的关键字是 :abstract
抽象类的语法:
抽象类的特性:
1、抽象类不能实例化对象 :
2 、抽象方法是不能是private的:
这个呢是非常好理解的,我们的抽象方法是必须要重写的,所以不能是 private 修饰符
3、抽象方法不能被 final 和 static 修饰:
这个呢,就和上面的解释是一样的,抽象方法是要被重写的。
4、抽象类必须要被继承,并且被继承后要把抽象方法给重写,如果在子类中还是不想重写 的话,那么我们的子类也要被 abstract 修饰
5、抽象类中不一定要有抽象方法,但是抽象方法一定要在抽象类当中。
抽象类的好处:
对于抽象类来说,我们不能实例化对象,要是想使用的话,我们只能继承于子类,然后子类重写抽象类当中的抽象方法。
抽象类就是相当于多了一条重写的检验。
16、接口:
在我们看看概念之前,我们先来看看现实中的接口都有什么,比如我们的电脑上的USB接口,我们可以插鼠标、U盘、键盘等,对于USB就是接口。
概念:
由上面可知我们的接口就是,多个类的一个公共规范,是一种引用类型。
接口的实现:
创建接口时, 接口的命名一般以大写字母 I 开头
接口的使用:
对于接口来说,不能直接使用,必须要有一个类开实现接口,实现接口中所有的抽象方法。
接口的特性:
1、接口是引用特性,但是不能直接的 new 对象。
2、接口中的方法是不能在接口中实现的,只能有实现接口的类来实现。
3、接口中不能有静态方法和构造方法。
4、如果接口中的方法没有被实现,那么类必须要使用 abstract 修饰。
实现多个接口:
接口间的继承:
Clonable和深拷贝:
Clonable对于是一个浅拷贝:
我们来看看实现:
这样就是浅拷贝。
那么什么是深拷贝呢?我们来看看:
这样就可以实现深拷贝了。
对于这里还是不是很懂得呢,可以看我的以前的那个 抽象类和接口 的博客。
在创建对象的时候,可能我们会创建一个数组的对象,我们的数组有一个sort方法可以比较对象的大小,但是我们看当我们使用的时候会出现什么情况:
这是因为,sort 不是知道比较哪个成员变量,那么我们要如何才能比较呢?我们来看:
17、 Object类:
Object类是所有类的父类。
在这里我们只了解Object的三种方法:
1、toString方法:
获取对象的信息,对于这个我们需要重写方法,在使用的时候。
2、对象之间的比较 equals 方法:
对于 == 来说呢我们在比较基本类型的时候,是比较他们的值,但是当我们比较引用类型的时候,我们比较的是地址,所以这时候我么要用到 equals 方法:
我们来看看如何使用的:
我们可以看到我们在上面的代码中,我们比较引用类型的话要是使用 == 的话比较的是地址,但是对于我们的 equals 方法是比较内容。但是我们在使用equals 时候呢要重写,因为在Object当中的equals方法也是比较的地址的,我们看看不重写的源代码:
我们可以看到,这里比较的也是地址,因为使用的是 == 比较的
3、hashCode方法:
在了解这个方法之前呢,我们先来看一下toString的源代码:
我们可以看到,我们的toString的源代码中体现了hashCode方法,那么它是起到了一个什么作用呢?
对于hashCode方法是使我们获得一个具体的对象位置。
对于hashCode这个方法呢,我们现在是不能达到一个具体的了解的,因为这里面的涉及到了数据结构,所以呢在JavaSE基础这里呢,我们知识了解一下其作用。
在我们定义对象的时候呢,当我们定义的对象是一样的时候,是不是认为它们存储在同一个位置。那么我们来看:
我们可以看到,在对象的成员变量是一样的时候呢,但是我们获得的位置没有一样,那么我们要如何才能使其结构一样呢?
我们可以看到,当我们重写hashCode的方法后,在调用这个方法后,结果就变得是一样的了。
18、String类:
我们直接看它的逻辑图:
对于String类来说呢,是不可在原String类上进行修改的,对于上面的方法都是进行新的String类创建。 如果我们想要在原字符上进行修改的话呢,我们就要使用StringBuffer和StringBuilder。
对于StringBuffer和StringBuilder来说呢,我们是有String类的方法的,并且有一些Sting类没有的方法。并且是很有用的方法:
1、insert(int offset, String str)
是在offest这个位置插入str
2、deleteCharAt(int index)
是删除index位置上的字符
3、delete(int start, int end)
是删除 start 和 end 的区间的字符
4、replace(int start, int end, String str)
将 start 到 end 位置上的字符替换为str
5、reverse()
将字符串反转
6、append(String str)
在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、double、float、int、long、Object、String、StringBuff的变量
19、 异常:
对于异常来说呢,我们有 编译时异常 和 运行时异常:
编译时异常:
就比如是对于clone()方法时候的编译时异常
运行是异常:
RunTimeException以及其子类对应的异常,都称为运行时异常
在Java中我们对于处理异常是呢,我们要使用五个关键字来进行处理异常:
try、catch、throw、throws、finally这五个关键字。
1、throw
用于异常的抛出。
2、throws
用于异常的声明
3、try-catch
这两个关键词结合在一起使用,try里面放肯呢个出现的遗产,catch是对于异常的处理。
4、finally
为了使资源的释放,把一些一定要执行的语句放到finally里面
自定义异常:
1. 自定义异常类,然后继承自Exception 或者 RunTimeException
2. 实现一个带有String类型参数的构造方法。我们来看看例子:
自定义异常类。
二、总结:
OK了,这次对于Java的基础的总结就到这里就结束了,接下来呢,我们就要进入到数据结构的阶段了,让我们敬请期待吧~~对于这次的博客呢,是非常的多的,希望大家可以耐心地看完喽~~拜拜喽!!!期待我们的下次见面吧!!!