1. JDK JRE JVM(三大任务)
JDK( Java Development Kit) : java 开发工具包
JVM 虚拟机的三大任务: 1、加载代码(.class)、 2 校验代码(头信息、版本)、 3 执行代码
2. Java常用命令:java javac
javac : 将源程序编译成可执行程序
java:运行.class可执行程序
执行过程:
# 编译文件
C:\Users\jack\Desktop\XZ_264_JAVA_01\code\01>javac -encoding utf-8 HelloWorld.java
# 执行java程序 .class 文件
C:\Users\jack\Desktop\XZ_264_JAVA_01\code\01>java HelloWorld
hello world
3. 命名规则
- 【强制】代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。
- 【强制】代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式
- 【强制】类名使用 UpperCamelCase 风格,必须遵从驼峰形式
- 【强制】方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从驼峰形式。
- 【强制】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
正例:MAX_STOCK_COUNT - 【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。
正例: 应用工具类包名为 com.alibaba.open.util、类名为 MessageUtils - 【强制】中括号是数组类型的一部分,数组定义如下:String[] args;
- 【强制】抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类命名以它要测试的类的名称开始,以 Test 结尾。
- 【强制】变量名不能使用关键字
4. 内存划分(栈、堆)
- java 定义了 8 中基本数据类型和引用数据类型(JDK 预定义的引用数据类型和自定义的引用数据类型),java 程序的执行会将内存划分为栈空间和堆空间
- 栈空间:自动分配,不需要程序员去申请
1.栈空间存取数据的效率高。
2.栈中的数据按“先进后出”的方式管理。
3.栈空间存储空间较小,不能存放大量的数据。
4.JVM 将基本类型的数据存放在栈空间。 - 堆空间:需要程序员去申请
1、堆空间存取数据的效率最低;
2、数据存放的位置随机分配;
3、堆空间存储数据的空间大,能存放大容量的数据。
5.基本数据类型
基本数据类型是CPU可以直接进行运算的类型。Java定义了以下几种基本数据类型:
整数类型:byte,short,int,long
浮点数类型:float,double
字符类型:char
布尔类型:boolean
计算机内存的最小存储单元是字节(byte),一个字节就是一个8位二进制数,即8个bit。它的二进制表示范围从00000000 ~ 11111111
,换算成十进制是0 ~ 255
,换算成十六进制是00~ff
。
内存单元从0开始编号,称为内存地址。每个内存单元可以看作一间房间,内存地址就是门牌号。
一个字节是1byte
,1024字节是1K,1024K是1M,1024M是1G,1024G是1T。一个拥有4T内存的计算机的字节数量就是:
4T = 4 x 1024G
= 4 x 1024 x 1024M
= 4 x 1024 x 1024 x 1024K
= 4 x 1024 x 1024 x 1024 x 1024
= 4398046511104
不同的数据类型占用的字节数不一样。我们看一下Java基本数据类型占用的字节数:
byte | short | int | long | float | double | char |
---|---|---|---|---|---|---|
1 | 2 | 4 | 8 | 4 | 8 | 2 |
6. 类型转换
- 小类型向大类型的转换
- 小类型向大类型的转换会自动完成,即不需要程序员编写额外的代码,由 JVM 负责。提示:自动类型转换也叫"隐式类型转换"。
- 自动转换的规则:符号位会自动扩展, 负数补 1, 正数补 0。
- 自动类型转换包含以下情况:
(1)byte->short->int->long->float->double
(2)int 和 char 类型的数据在某些情况下可以自动相互转换。
PS:小类型向大类型转换一般情况下是安全的。当小类型的精度高于大类型时要注意精度丢失的隐患
int i = 0x10000001;
float f = i;
System.out.println(i);// 268435457
System.out.println(f);// 2.68435456E8
- 大类型向小类型的转换
1)强转类型转换-简称强转
2)强制类型转换时,要注意边界数风险问题
int i =129;
byte b = (byte) i;
System.out.println(i); //129
System.out.println(b); //-127
//i:00000000 00000000 00000000 10000001 -> b:10000001
//符号位以后取反+1,即11111110+1=11111111,即为-127
- int 和 char 类型之间的转换
Java 对 char 类型的数据在底层是按 int 类型来处理的。
int->char
int i =97;
char c = (char) i;
System.out.println(i);//97
System.out.println(c);//a
char->int
char c = 'A';
int i = c;
System.out.println(c);//A
System.out.println(i);//65
字符型进行计算:
char c = 'A';
System.out.println(c+1);//66
7. 运算符
- 算术运算符
加号(+)、 减号(-)、 乘号(*)、 除号(/) 、取模(%) 、自增运算符(++) 、自减运算符(–) - 逻辑运算符
&、|、!、&&、||
&&、||、!(短路运算方式 )对“或运算”如果运算符左边的表达式的值为 true,则整个表达式的结果为 true,不必对运算符右边的表达式再进行运算;同样,对“与运算”,如果左边表达式的值为 false,则不必对右边的表达式求值,整个表达式的结果为 false。
-
关系运算符
-
位运算符
按位与运算符(&)
按位或运算符(|)
按位异或运算符(^)
按位取反运算符(~)
左移位运算符(<<)和右移位运算符(>>) -
赋值运算符
一次可以给多个变量赋值
int i = 1000;
int a, b, c, d; a = b = c = d = i;
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
- 条件运算符
条件表达式?值 1(表达式 1):值 2(表达式 2);
当条件表达式位 true 是取值值 1,false 取值值 2;
8. 流程控制
• Java 虽然是面向对象的语言,但在局部的语句块内部仍然需要借助结构化的基本流程结构(顺序结构、分支结构、循
环结构)来组织语句,完成相应的逻辑功能。
• 三种基本流程控制结构示意图分别如下图所示:
-
顺序结构
-
分支语句
a) 条件分支语句
i. if 语句
ii. if-else 语句
iii. if-else if-else
iv. Switch 语句
一般格式如下:
switch (key) {
case value:
语句块1;
break;
……
default:
break; }
-
循环语句
- while 循环
- do while 循环(do-while 循环与 while 循环的不同在于:它先执行循环中的语句,然后再判断条件是否为真,如果为真则继续循环;如果为假,则终止循环。因此,do-while 循环至少要执行一次循环语句。)
- for 循环
-
特殊循环语句
- 增强 for 循环(JDK5.0 之后的新特性)
-
注释
- //、/**/
-
递归
案例:1+2+3….+100;
public static int sum(int num){
return num==1?1:num+sum(num-1);
}
9. 数组
-
数组的创建和声明
- 定义:数组是一个长度固定的数据结构,它存储多个相同类型的数值。数组直接被 Java 编程语言所支持,数组也是一个对象(引用数据类型)。数组是一个 Object 类的一个不明显的扩展。
- 数组的特征: 有序、具有相同类型、通过数组名和下标确定数组中的元素。
- 数组的声明:
a)数组的元素类型 数组变量名[];
b)数组的元素类型[] 数组变量名;
创建数组空间:创建数组空间可以在声明的时候进行创建,也可以先声明然后在创建空间。数组名=new 数组元素类型[数组的长度];
int[] arr = new int[10];
等同于下面的
int[] arr; arr=new int[10];
-
数组的初始化和元素
初始化数组就是要使数组中每个元素具有确定的值,如果数组元素类型为基本数据类型,由于基本数据类型都有缺省值,数组会自动将元素初始化为缺省值,对于元素类型为引用数据类型的数组,初始化数组的每个元素则是必要的,否则元素为 null.
PS:每个数组都有一个属性length
,表示该数组可以存放元素的个数。Java 环境会自定检测数组的下标是否越界。
数组的 静态初始化 和 动态初始化:-
动态初始化:使用 new 关键字初始化,需要指定数组的长度。例如:
int[] arr = new int[5];
通过for循环或者其他方式对数组的元素进行赋值。 -
静态初始化:在声明的同时进行初始化,需要指定数组的元素,根据元素由系统指定它的长度。
int[] arr={6,5,4,3,2};
-
-
一维数组
一维数组的内存划分:-
对于基本数据类型:
-
对于引用数据类型:以 Sring 伪列
定义一字符串数组String[] strs = {"java","html","javaScript"};
又例:
-
排序法:
主要排序法
- 二维数组
//静态初始化和遍历
int[][] arr = {
{
12,44,35,14,3},{
76,54,31,34},{
21,314},};
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j]+"\t");
}
System.out.println();
}
//动态初始化和遍历
int[][] arr = new int[3][];
arr[0]=new int[2];
arr[1]=new int[3];
arr[2]=new int[4];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j]+"\t");
}
System.out.println();
}
10. 面向对象
面向对象思想:
- OOA Object-Oriented Analysis: 面向对象分析法
- OOD Object Oriented Design:面向对象设计
- OOP Object Oriented Programming:面向对象编程
对象:万物皆对象、世间所有的事物都可以称之为是对象(某个人、某个物品、虚拟的游戏里面的东西)
类:
- 类实质上定义的是一种对象类型,它是对具有相似属性行为的对象的一种抽象;
- 描述了属于该类型的对象的性质——统一的属性和操作方式。
- 总结:类,是创建对象的模板。
属性:对象的特征(人的姓名、人的年龄…)
方法:对象的操作、动作(吃饭、工作…)
定义类:
class 类的名称{
[访问修饰符] 数据类型 属性名; /*声明成员变量*/
...
[访问修饰符] 返回值类型 方法名([参数列表]) {
程序代码语句;
return 值或表达式; } }
成员变量的定义:又叫实例变量,定义在类中,方法外的变量叫做成员变量,属于某一个对象。
成员方法:又叫实例方法,必须通过某个对象来进行访问调用。
PS:栈空间保存的是基本数据类型和字符串,包括局部变量的引用,堆空间保存的动态产生的数据,比如 new 创建出来的对象,也就是引用数据类型。上面两个Person 实例在堆空间开辟了两块内存,那么相互之间进行调用的时候就不会受到影响,只要使用了 new 关键字,必会在堆空间开辟内存
构造函数:
- 要使用面向对象,首先必须构造对象,并指定它们的初始状态,然后通过对象调用方法。
- 在 java 的语言设计中,使用构造函数(constructor)来构造新的实例,一个构造函数是新的方法,它的作用就是构造对象并进行初始化.
(1)构造函数的方法名与类名相同。
(2)构造函数没有返回类型。
(3)构造函数的主要作用是完成对类对象的初始化工作。
(4)构造函数不能由编程人员显式地直接调用。
(5)在创建一个类的新对象的同时,系统会自动调用该类的构造函数为新对象初始化。
构造函数的特点有:
(1)构造函数和类具有相同的名字。
(2)一个类可以有多个构造函数。
(3)构造函数可以有 0 个、1 个或多个参数。
(4)构造函数没有返回值。
(5)构造函数总是和 new 关键字一起被调用。
构造函数的作用:
(1)对象初始化
(2)引入更多的灵活度(变量赋值或更复杂的操作)
(3)Java 中可以不定义构造函数
Java 中可以不定义构造函数,此时系统会自动为该系统生成一个默认的构造函数。这个构造函数的名字与类名相同,它没有任何形式参数,也不完成任何操作。如果显式声明其他的构造函数,这个无参的构造函数就不存在了,如果需要使用无参的构造函数,则需要显示的声明出来。
一个类中可以有多个构造方法,多个构造方法之中参数列表不同(个数、顺序、类型),即构造方法重载。JVM会自动根据传入的实参列表来决定调用哪个构造函数。
this 关键字:
this 关键字:与对象关联,表示当前对象(实例),即 new 出的是哪个对象,代表的就是哪个对象.
this 关键字的作用:可以调用调用类中的构造方法,普通方法,成员变量。this 调用构造方法只能是在构造方法中使用,必须是第一行
方法重载:
方法重载是 java 中实现面向对象多态性机制的一种方式
- 方法重载:在同一个类中(前提条件),方法名相同、参数列表不同、和返回值无关。
- 调用方法重载: JVM根据参数列表来决定调用哪个方法重载。方法重载不考虑方法的返回类型。
变量的作用域:
按照变量的作用域分类,类中只有两种变量:
实例变量:在所有方法之外但在类体中声明或定义的变量
局部变量:在方法中声明或定义的变量
实例变量的有效范围是整个类;
局部变量的有效范围在方法体之中,出了方法体就自动消失了;
参数传递:
方法的参数只有两种类型:基本数据类型和引用数据类型。
- 在 Java 中,参数的传递只有一种方式,就是按值传递(传递自身的拷贝):
- 对于基本数据类型,传递的值就是变量自身的值
- 对于对象类型,传递的值就是对象的引用(而不是对象自身!)
方法不能改变传递给它的参数的自身
例 1:基本数据类型作为参数
public class Test {
public void change(int a){
a=20;
}
public static void main(String[] args) {
int a = 10;
System.out.println(a);//10
Test t = new Test();
t.change(a);
System.out.println(a);//10
}
}
例 2:对象类型作为参数
当对象作为参数时,在方法中只能改变对象的状态不能改变对象的引用
public class Test {
public void change(Person person) {
person.age = 20;
}
public static void main(String[] args) {
Person person = new Person();
person.age = 10;
System.out.println(person.age);// 10
Test t = new Test();
t.change(person);
System.out.println(person.age);//20
}
}
class Person {
int age;
}
例 3:字符串作为传递参数
public class Test {
public void change(String str) {
str = "jack";
}
public static void main(String[] args) {
//字符串是一个特殊的引用数据类型。它的传递方式和基本数据类型一致
String str = "tom";
System.out.println(str);
Test t = new Test();
t.change(str);
System.out.println(str);
}
}
例 4:数组作为传递参数
public class Test {
public void change(int[] arr) {
int[] arr2 = {
30 };
arr = arr2;
}
public static void main(String[] args) {
int[] arr = {
10 };
System.out.println(arr[0]);// 10
Test t = new Test();
t.change(arr);
System.out.println(arr[0]);
}
}
封装:
a)封装是对象的一种隐藏技术,其目的是将对象中的属性和方法组织起来。同时隐藏不想暴露的属性和方法及实现细节。
b)用户或其它对象不能看到也无法修改其实现。只能通过接口去调用对象的方法,达到互相通信的目的。
c)封闭的目的在于将设计者与使用者分开。使用者不必知道实现的细节,只需用设计者提供的方法来访问该对象。
继承:
继承是面向对象编程技术的一块基石,它允许创建分等级层次的类。运用继承,可以创建一个通用类定义一系列一般特性。该类可以被更具体的类继承.
- 被继承的类称为父类或者超类或者基类
- 继承父类的类称为子类或者派生类
- 执行继承时,子类将获得父类的所有成员(包括 private 的成员,私有的不能直接访问),并具有自身特有的属性
没有 extends,默认父类为 Object .一个类只能有一个父类,即单继承.子类继承父类的全部成员
• 类的继承,是为了子类能够访问父类中已经定义的属性和方法,就如同是自己的属性和方法一样。
• 继承最大限度的重用了代码。子类通过继承可以访问父类的属性和方法,而不必为一个新类编写相同的代码。
• 一个子类可以继承多个父类。但 JAVA 语言只能直接继承一个父类。通过间接继承可以继承多个父类。
super 关键字:
super 是一个引用,专门用来在子类中访问父类中的构造函数、方法和实例变量。
- 使用 super 在子类的构造函数中调用父类的构造函数,语法:
super()或者 super(参数列表)
super()必须是在子类构造函数中的第一个执行语句。 - 在子类的方法中调用父类中的方法,语法:
super.方法名(参数列表) - 在子类的方法中调用父类中的实例变量, 语法:
super.实例变量名
方法重写(覆盖)override:
是 java 实现多态机制的另外一种形式。
- 在不同类中,如果子类中的一个方法与父类中的方法有相同的返回类型、相同的方法名并具有相同数量和类型的参数列表,这种情况称为方法覆盖。
- 当一个覆盖方法通过父类引用被调用,Java 根据当前被引用对象的实际类型来决定执行哪个版本的方法。
- 可以通过 super 关键字调用直属父类中被覆盖的方法版本。
抽象类:
定义:一种类型,只提供部分方法的具体实现。
语法:abstract class 类名{….}
一般情况下,抽象类既包含具体方法,又包含抽象方法。
具体方法:既有方法的声明,又有方法的实现(即有方法体)。
抽象方法:只有方法的声明,而没有方法的实现(即没有方法体)。语法:
abstract 返回类型 方法名(参数列表)
抽象类的示例:
public abstract class Father {
String name;
int age;
public Father() {
}
public Father(String name, int age) {
this.name = name;
this.age = age;
}
public abstract void say();// 抽象方法,没有方法体
public void see() {
System.out.println("see");
}
}
public class Son extends Father {
public Son() {
}
public Son(String name, int age) {
super(name, age);
}
// 必须要重写父类的所有抽象方法,包含间接父类
@Override
public void say() {
System.out.println("我必须要重写父类的所有抽象方法");
}
}
public class Test {
public static void main(String[] args) {
Father f = new Son();//抽象类不能被实例化,必须通过子类进行实例化
f.say();
}
}
总结:
- 抽象类不能被实例化。
- 抽象类就是用来继承的。
- 子类必须为抽象类中的所有抽象方法提供具体实现,否则,子类也将是一个抽象类
- 抽象类中可以声明实例变量,这些实例变量就是为了提供给子类继承的
- 抽象类可以有一个或多个构造函数,它是提供给子类进行调用的
- 特别地,抽象类中的所有方法都可以是具体方法
里氏代换原则:
- 当一个地方需要一个父类对象,我们可以通过子类对象类替代他。
- 子类不可以重写父类的具体方法
里氏替换原则通俗的来讲就是:任何父类可以出现的地方,子类一定可以出现,子类可以扩展父类的功能,但不能改
变父类原有的功能。它包含以下含义:
- 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
- 子类中可以增加自己特有的方法。
多态:
多态和动态绑定:
声明类型:对象变量被声明时的类型
实际类型:对象变量实际指向的对象类型
一个对象变量可以指向多种实际类型的现象称为“多态”
在运行时自动选择正确的方法进行调用的现象称为“动态绑定”
Java 根据对象的实际类型来进行方法调用
- 编译时多态:编译时动态重载.(方法重载)
- 运行时多态:指一个对象可以具有多个类型。 (方法重写)
运行时多态的三大前提条件:
1.) 继承
2.) 重写
3.) 父类引用指向子类对象
instanceof 关键字:判断一个类是否属于一个类型,必须要有继承的关系。
if(f instanceof Son)
作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型
内部类:
在一个类中定义的类称为内部类,内部类之外的类称为外部类 ;
内部类可以访问其外部类的所有变量和方法;
内部类完全在其包围类的范围之内;
内部类中的 this 指的是内部类的实例对象本身,如果要用外部类的实例对象就可以用类名.this 的方式获得。
内部类对象中不能有静态成员,原因很简单,内部类的实例对象是外部类实例对象的一个成员
内部类:普通内部类、局部内部类、静态内部类、匿名内部类
内部类
Object 类:
Object 类是 Java 类体系结构的根;
Java 系统中的每个类都是 Object 类直接或间接的子类 ;
Object 类包括在 java.lang 包中,此类定义了所有对象都具备的基本状态和行为,可以用类型为 Object 的变量来引用任意类型的对象 ;
final最终类
:
如果一个类被声明为 final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为abstract 的,又被声明为 final 的。
被定义成 final 的类,通常是一些有特殊作用的、用来完成标准功能的类,将一个类定义为 final 则可以将它的内容、属性和功能固定下来,与它的类名形成稳定的映射关系,从而保证引用这个类时所实现的功能是准确无误的
设计模式之工厂模式
接口
接口是设计的结果 ,抽象类是重构的结果
接口