Java之父:詹姆斯·高斯林
1995年,Java问世 1999年,Java2发布 2009年,Oracle收购sun
Java SE(Java Platform Standard Edition)称之为Java平台标准版,是Java平台基础,应用于桌面环境。
Java SE包含了Java应用所需的基础环境和核心类库,还定义了基于桌面应用的基础类库,可以编写桌面应用。
Java EE(Java Platform Enterprise Edition)称之为Java平台企业版,应用于基于Java的应用服务器。
构建在Java SE基础之上,用于构建企业级应用。
Java ME(Java Platform Micro Edition)称之为Java平台微型版,为嵌入式消费电子设备提供Java解决方案,应用于移动、无线及有限资源的环境。
已被淘汰。
Java源文件(*.java)经过javac命令编译生成字节码文件(*.class),通过java命令启动jvm将字节码文件装载解释给操作系统运行。
编译时没有在内存中运行,运行时才在内存中运行。
由此可以看出,Java属于跨平台的,一次编程到处运行。
.class字节码如下所示:
Java源程序与编译型源程序在运行时的区别:
JDK(Java Development Kit)称为Java开发包或Java开发工具,是一个编写Java的Applet小程序和应用程序的程序开发环境。JDK是整个Java的核心,包括了JRE,一些Java编译、运行等开发工具。不论什么Java应用服务器实质都是内置了某个版本的JDK。主流的JDK是Sun公司发布的JDK。
JRE(Java Runtime Envirnment)称之为Java运行环境,JDK是个开发环境。JRE包含了Java系统类库和JVM。因此写Java程序的时候需要JDK,而运行Java程序的时候就需要JRE。而JDK里面已经包含了JRE,因此只要安装了JDK,就可以编辑Java程序,也可以正常运行Java程序。
JVM(Java Virtual Machine)称为Java虚拟机。
其关系如下图所示:
如下所示:
JAVA_HOME(指的是JDK安装路径) 例如C:\Program Files (x86)\Java\jdk1.8.0_91 Path(配置开发工具的路径) %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin; CLASSPATH .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
1.Eclipse
由IBM撤资千万美元打造的开源项目,基于“插件”特性,具备高度灵活性。其本身也是用Java语言编写的,因此需要JDK或JRE的支持.
Eclipse在保存时自动进行javac命令编译成字节码文件,run时运行。
2.IntelliJ IDEA
Java标识符有以下注意事项:
1.所有的标识符只能以字母(A-Z 或者 a-z)、数字、美元符($)、或者下划线(_)组成,不能以数字开头 2.关键字不能用作标识符 3.标识符大小写敏感
修饰符类型
Java主要有两种修饰符:
1.访问控制修饰符 : default, public , protected, private 2.非访问控制修饰符 : final, abstract, static, synchronized等 访问控制修饰符
定义
使用访问控制修饰符来保护对类、变量、方法和构造方法的访问。
- default(默认的)
缺省,默认,不使用任何修饰符。可以在本类和同一包中访问。使用对象:类、接口、变量、方法。
- private(私有的)
private修饰的只能被本类中访问,并且类和接口不能声明为 private(不然没有意义)。
主要用于隐藏类的实现细节和保护类的数据。
- public(公共的)
对所有类可见和使用。使用对象:类、接口、变量、方法。被声明为 public 的类、方法、构造方法和接口能够被任何其他类访问。
- protected(受保护的)
对同一包内的类和所有子类可见和使用。使用对象:变量,方法。
区别
修饰符 本类 同一个包中的类 子孙类(同一包) 子孙类(不同包) 其他类 public 可以访问 可以访问 可以访问 可以访问 可以访问 protected 可以访问 可以访问 可以访问 可以访问
在子类中,子类实例可以访问从基类
继承而来的 protected 方法,而基类
实例不能访问基类的protected方法。
不能访问 default(默认) 可以访问 可以访问 可以访问 不能访问 不能访问 private 可以访问 不能访问 不能访问 不能访问 不能访问 注意事项
成员访问修饰符按照可访问的范围从大到小的顺序是:public、protected、default、private。
非访问控制修饰符
static(静态的)
static修饰的和非static修饰的区别:
1.static修饰的属于类级别,可以可以通过类名来访问(建议),也可以通过实例对象来访问(不建议);非static修饰的为动态的(私有),属于对象级别的。
2.static修饰的变量叫做:静态变量或者类变量;static修饰的方法叫做:静态方法或者类方法
只要程序加载了类的字节码,不用创建任何实例对象,静态变量和静态方法就会被分配空间,然后就可以被使用了
3.非static修饰的变量叫做:实例变量;非static修饰的方法叫做:实例方法
创建实例对象,其中的实例变量和实例方法才会被分配空间,才能使用实例变量和实例方法。
- 静态变量(类变量)
1.使用static修饰的变量属于静态变量(类变量)。无论一个类实例化多少对象,它的静态变量只有一份拷贝。 2.注意:局部变量不能被声明为静态变量。
- 静态方法(类方法)
1.静态方法里面不能直接调用类的非静态成员(因为静态方法里面没有this),但是可以通过对象调用来访问 2.静态方法可以直接调用类的静态成员 3.非静态方法可以直接调用静态成员。
4.静态方法由于不需要对象参与,故静态方法不存在this隐式传递,方法里面不能使用this关键字 故:静态资源不能直接访问非静态资源,非静态资源可以直接访问静态资源。
- 非静态方法(实例方法)
1.非static关键字修饰的方法在调用时,this被隐式的传递(故可以在非静态方法里面使用this关键字)。
- 静态代码块
语法 static{ //代码 }
特点 1.只会加载执行一次
2.静态代码块会在类加载时被执行(类加载:第一次使用该类时)
3.静态代码块属于静态资源
如下所示:
public class Test1 { public Test1() { System.out.println("构造方法执行了"); } static { System.out.println("静态代码块执行了"); } public static void main(String[] args) { new Test1(); new Test1(); new Test1(); } } 运行结果为:静态代码块执行了 构造方法执行了 构造方法执行了 构造方法执行了
final(最后的、最终的)
- final常量
概念 使用final 用于创建常量。使用final修饰的常量必须显示的指定初始值(否则报错),且一旦赋值后,
就不能被修改重新赋值。
赋值方式 final修饰的成员变量:
方式一:在声明的时候就赋值
方式二:在声明时未赋值,但是在构造方法里面赋值
方式三:在声明时未赋值,但是在普通代码块里面赋值
final修饰的局部变量:
在使用之前赋值就行。
- static final常量
概念 final通常与static一起使用来创建类常量 赋值 方式一:在声明的同时就初始化赋值
方式二:在声明时未赋值,在静态代码块中赋初值(final常量不能,因为不是static)
命名规范 所有字母全大写 优点 提高代码的可读性,可维护性,可扩展性,可移植性。 注意事项:static final常量会在编译期就被替换为其常量值,提升程序性能,如下所示:
class Parent{ public static final int NUM = 100; } class Child{ public static void main(String[] args){ System.out.println(Parent.NUM); //上面的代码在编译时,就会替换为System.out.println(100); } } Parent的常量NUM会在编译时就被替换为其常量值100,从而不用载入Parent类,提升程序性能。
- final方法
类中的final方法可以被子类继承,但是不能被子类修改(重写)。因此,声明final方法的主要目的就是防止该方法的内容被修改。
- final类
final类不能被继承,因此没有类能够继承final类的任何特性。
abstract(抽象的)
- 抽象类
1.抽象类虽然存在构造方法,但是不能被直接实例化对象,但是子类在实例化时会间接实例化抽象父类对象。 2.声明抽象父类的唯一目的就是为了让子类继承,将来子类对该抽象父类进行扩充。 3. 一个类不能同时被abstract和final修饰(因为final使得类不可被继承,而abstract修饰的类如果不能被继承将没有任何意义)。 4.抽象类意义:
为子类提供一个公共的类型
封装子类中重复的内容
子类方法虽然有不同的实现,但在父类定义是一样的。
- 抽象方法
1. 抽象方法是一种没有任何实现的方法,以分号;结尾。该方法的具体重写由子类提供。 2. 抽象方法不能被声明为final和static。 3.子类继承抽象父类,必须重写该抽象父类的所有抽象方法,除非子类也是抽象类。 4.如果一个类包含抽象方法,那么该类必须要被声明为抽象类(因为抽象方法是一种不完整的方法,故抽象类也是不完整的类)。 synchronized
synchronized关键字声明的方法同一时间只能被一个线程访问。
1.变量的定义
变量就是指在内存空间中开辟的储存空间,用于存放运算过程中需要的数据。
2.变量的命名
变量名只能由以字母(A-Z 或者 a-z),美元符($)、数字、或者下划线(_)组成,不能以数字开头,且大小写敏感,不能以关键字和保留字命名。
命名采用驼峰命名法。
3.变量的类型
1.局部变量 在方法、构造方法或者语句块里面定义的变量称为局部变量。
变量的声明和初始化都是在方法中,一旦方法执行结束之后,局部变量就会自动销毁。
2.类变量(静态变量) 类变量是定义在类中但在方法体之外的变量,使用static修饰。
这种变量在创建对象的时候初始化。
3.成员变量(非静态变量) 类变量也是定义在类中但在方法体之外的变量。
关键字
Java的关键字对java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的结构等。
主要有以下关键字:
类别 关键字 说明 访问控制 1.private 私有的 2.protected 受保护的 3.public 公共的 类、方法和变量修饰符 4.abstract 声明抽象 5.class 类 6.extends 扩充、继承 7.final 最终值,不可改变的 8.implements 实现(接口) 9.interface 接口 10.native 本地,原生方法(非Java实现) 11.new 新、创建 12.static 静态 13.strictfp 严格、精准 14.synchronized 线程、同步 15.transient 短暂 16.volatile 易失 程序控制语句 17.break 中断循环,只用于switch分支语句和循环语句中。 18.case 定义一个值以供switch选择 19.continue 继续,只能用于循环语句中,表示跳过结束本次循环,继续下一次循环。 20.default 默认 21.do 运行 22.else 否则 23.for 循环 24.if 如果 25.instanceof ......是否是......的实例 26.return 返回 27.switch 根据值选择执行某个case 28.while 循环 错误处理 29.assert 断言表达式是否为真 30.catch 捕捉异常 31.finally 有没有异常都执行 32.throw 抛出一个异常对象 33.throws 声明一个异常可能被抛出 34.try 捕捉异常 包相关 35.import 导入包 36.package 包 基本类型 37.boolean 布尔型 38.byte 字节型 39.char 字符型 40.double 双精度浮点型 41.float 单精度浮点型 42.int 整形 43.long 长整型 44.short 短整型 变量引用 45.super 超类、父类。可以通过super关键字来实现对父类成员的方法,用来引用当前对象的父类。 46.this 本类,指向自己的引用。 47.void 无返回值 保留关键字 48.goto 是关键字,但不能使用 49.const 是关键字,但不能使用 50.null 空 保留字
保留字:为java预留的关键字。现在还没用到,但是在升级版本中可能作为关键字。
保留字有如下:byValue, cast, false, future, generic, inner, operator, outer, rest, true, var , goto ,const,null
1.单行注释 //....... /* ........ */ 2.多行注释 /*
* .........
*/
空白行或者有注释的行,Java 编译器都会忽略掉。
1.类的全限定名:
类的全限定名就是包名 + 类名,如果一个类只有类名没有包名,则全限定名就是类名。
2.包名语法
package 包1.包2.包3...;
3.注意事项
- 包名建议唯一,且全小写,
- 使用域名反转形式。
4.包里面的类的使用
要想使用某个包下面的某个类,就必须引入该包下面的类。
5.导入包
方式一:import 包名.类名; 如:import java.util.Random; 方式二:包名.类名 类名; 如:java.util.Random random; 注意:import 包名.*;会引入该包名下所有的类,但是不建议,会影响程序性能。
注意:java.lang包系统会默认自动导入,因此lang包下面的类不用手动引入也能使用。 即import java.lang.*;系统默认导入。
不同包下相同的类名只能引入一个,不然报错。
1B(1字节)=8bit(8位),1字节最大值为0111 1111 (-128 - 127即 -2^7 - 2^7-1)
1.基本数据类型(8种,数值类型)
数值型 整数型(整数类型的直接量默认为int类型)
整数相除,直接丢弃小数部分(不会四舍五入),
结果值还为整数。比如5/3=1
byte(字节):1个字节,8位
最小值是 -128(-2^7)
最大值是 127(2^7-1)
默认值位0
short(短整型):2个字节,16位
最小值是 -32768(-2^15
最大值是 32767(2^15 - 1)
默认值是 0
int(整型):4个字节,32位
最小值是 -2,147,483,648(-2^31)
最大值是 2,147,483,647(2^31 - 1)
默认值是 0
long(长整型):8个字节,64位
最小值是 -9,223,372,036,854,775,808(-2^63)
最大值是 9,223,372,036,854,775,807(2^63 -1)
默认值是 0L,使用时需要在后面添加L
浮点型(不能用来表示精确的值,如货币,因为在运算时会有误差)
(浮点类型的直接量默认为double类型)
float(单精度):4个字节,32位
默认值是 0.0f
需要在小数后面添加f或者F,如2.1f
double(双精度):8个字节,64位
默认值是 0.0d
精度(小数点位数)是float类型的两倍
字符型
Java字符类型采用Unicode 字符集编码
字符类型的直接量可以采用字符形式、十进制方式或十六进制形式
如: char c = 'a';
char c = 97;
char c = '\u0061';
对于不方便输出的字符,可以采用转义字符\来输出,如换行:'\n';
制表符:'\t';单引号:'\'';\:'\\'。
char:2个字节,16位,本质上是无符号整数
最小值是 \u0000(即为0)
最大值是 \uffff(即为65,535)
char 数据类型可以储存任何字符
注意: java中,只要是字符,不管是数字还是英文
还是汉字,都占两个字节,都是一个char。
utf-8 的汉字占3个字节 gbk 是两个
布尔型 boolean:一个字节,表示一位的信息
默认值是 false,只能为true或者false
只能用于关系或者逻辑运算。
2.引用类型(地址类型)
除了上面的8种基本数据类型,其他的全是引用数据类型。
引用类型指向一个对象,指向对象的变量是引用变量。这些变量在声明时被指定为一个特定的类型,变量一旦声明后,类型就不能被改变了。
1.对象 2.数组 3.字符串 3.比较
- ==比较的是地址是否相同
- equals比较的是内容是否相同
1.二进制
二进制转八进制,三位一看;二进制转十六进制,四位一看。
2.八进制
八进制以0开头:如0177
3.十六进制
十六机制以0x开头:如0x7f
溢出:正数过大溢出结果变为负数最小,负数溢出,变为正数最大。
时间原点位1970.1.1 00:00:00。System.currentTimeMillis获取系统从1970.1.1 00:00:00到当前时间毫秒差并返回。
1.自动类型转换(小到大)
整型、实型(常量)、字符型数据可以混合运算。运算中,不同类型的数据先转化为同一类型,然后进行运算。转换从低级到高级。
低 ------------------------------------------> 高 byte,short,char —> int —> long -> float —> double
有如下注意事项:
1.不能对boolean类型进行类型转换,转换的类型要兼容。 2.不能把对象类型转换成不相关类的对象 3.在容量大的类型转换成容量小的类型时必须使用强制类型转换 4.转换过程中可能导致溢出或者损失精度。如果要转换的字节数小于转换后的字节数,那么就没有风险;否则有风险。
例如:int i = 128; byte b = (byte)i;
因为 byte 类型是1个字节, 8 位,最大值为127;int是四个字节,32位。1个字节小于4个字节,所以当 int 强制转换为 byte 类型时,值 128 时候就会导致溢出。
5.浮点数到整数的转换时通过舍弃小数得到,而不是四舍五入。
例如:(int)23.7 = 23;
6.转换时,必须满足转换前的数据类型的位数要低于转换后的数据类型。
例如:short数据类型的位数为16位,就可以自动转换位数为32位的int类型。
2.强制类型转换(大到小)
转换的条件是转换的数据类型时兼容的。转换是有风险的(溢出)。
例如:int x = 123; byte y = (byte)x;将int类型强制转换为byte类型
3.多种不同数据类型参与运算,结果以最大的数据类型为最终类型。
如int x = 100 + 3.12;是错误的,正确的写法为: double x = 100 + 3.12; 或者 int x = (int)(100 + 3.12);
4.byte、short和cahr转换为int
- int类型直接量可以给byte、short和char赋值,但数值不能超过其能够表示的范围。
如:byte x = 1; short y = 1; char z = 1;是正确的 byte x = 128; char z = 65536; short y = 32768;都是错误的,超出范围溢出
- byte、short和char类型参与运算时,一律会先转换为int类型再进行运算
如:byte x = 1; byte y = 1; 错误的为:byte z = x + y; 正确的为:byte z = (byte)(x + y);
Java有如下运算符:
1.算术运算符
算术运算符用在数学表达式中。
+ 加法 - 减法 * 乘法 / 除法 % 取余 ++ 自增:操作数的值增加1。注意:++a与a++是不一样的,++a先自增再运算,a++先运算再自增。
-- 自减操作数的值减少1 2.关系运算符
如下所示:
== 是否等于,比较的是地址 != 是否不等于 > 是否大于 < 是否小于 >= 是否大于等于 <= 是否小于等于 3.逻辑运算符
用来连接关系,如下所示:
&& 逻辑与运算符,仅当两个操作数都为真时,条件才为真。 || 逻辑或运算符,两个操作数任何一个为真时,条件为真。 ! 逻辑非运算符,取反。 短路逻辑:
当使用&&时,在第一个操作数为false,其结果必定为false,后面的操作数将不会再执行了。 当使用||时,在第一个操作数为true,其结果必定为true,后面的操作数将不会再执行了。 注意:&与|没有短路效果,因此建议使用&&与||
4.三种运算符优先级
算术运算符 > 关系运算符 > 逻辑运算符
5.条件运算符(三元/目运算符)
语法为:条件表达式?表达式1:表达式2。
说明:问号前面的位置是判断的条件,判断结果为boolean型,为true时调用表达式1,为false时调用表达式2。
例如:int x = 6; int y = x > 2? 0 : 1; 结果:y为0
6.instanceof关键字运算符
该运算符用于操作对象实例,判断引用所指向的对象是否是指定的类型(类类型或接口类型),如果是返回true,否则返回false。
如:boolean result = "hello world" instanceof String; 结果:result为true
7.赋值运算符
如下所示:
= a = 2; += a += 2; <---> a = a + 2; -= a -= 2; <---> a = a - 2; *= a *= 2; <---> a = a * 2; /= a /= 2; < ---> a = a / 2; %= a %= 2; <---> a = a % 2; 8.字符串连接符+
字符串不能与任何数值进行运算,字符串 + 数值时,Java会自动将数值转换成字符串,然后两个字符串进行拼接成一个字符串。
字符串 + 字符时是拼接的字符,而不是拼接的字符的Ascall编码。
Java循环结构是用于解决一组相同或者相似的语句被有规律的执行。
1.while循环
先判断再循环。
while(布尔表达式){ //... }
2.do...while循环
会至少执行一次,先循环再判断。
do{ //代码 }while(布尔表达式);
3.for循环
for(初始化; 布尔表达式; 更新){ //代码 }
4.增强for循环
for(声明语句 : 表达式){ //代码 }
5.break关键字
用于结束某个循环,如果有多层循环嵌套,只会结束当前break处于的这层循环。
6.continue关键字
用于让程序立刻跳转到下一次循环的迭代。
1.if语句
if语句只有一条支路,其语法如下所示:
if(布尔表达式){ //代码 }
2.if...else语句
if...else语句有两条支路,其语法如下所示:
if(布尔表达式){ //代码 }else{ //代码 }
3.if...else if...else语句
if...else if...else语句拥有多条支路,其语法如下所示:
if(布尔表达式){ //代码 }else if(布尔表达式){ //代码 }else{ //代码 }
switch语句可以拥有多条支路,用于判断一个变量与一系列值中某个值是否相等的情况(>,>=,<,<=不能使用),每个值称为一个分支。因此,switch不够灵活。
语法如下所示:
switch(expression){ case: value1: //代码 break; //可选 case: value2: //代码 break; //可选 //可以有任意数量的case语句 default: //可选 //代码 break;//可选 }
有如下规则:
1.switch里面的expression变量类型可以是:byte、short、int、char、枚举类型。在JDK1.7之后支持String类型。不支持long、float、double类型。 2.case后面的value值必须和expression变量的数据类型一样。 3.当遇到break时,switch语句终止执行;case语句可以不包含break,如果没有break,则会继续执行该case语句的下一条case语句,直到出现break。 4.switch语句可以包含一个default分支,default在没有case语句的value值与expression变量值相等的情况下执行。default分支不需要break。如果default分支后面还有case语句,且没有break时,则会执行后面的case语句。 如下所示:
public class Test5 { public static void main(String[] args) { int x = 10; switch (x) { case 1: System.out.println(1); case 2: System.out.println(2); case 10: System.out.println(10); case 4: System.out.println(4); case 5: System.out.println(5); default: System.out.println(6); break; } } }
运行结果为:
10 4 5 6
1.数组的类型
数组属于对象,其父类是Object,每个数组都实现了Cloneable和java.io.Serializable接口。如下所示打印数组类型:
public class Test6 { public static void main(String[] args) { int[] array = {1,2,3}; System.out.println(array.getClass()); System.out.println(array.getClass().getName()); array.clone(); } }
运行结果为:
class [I [I
“[”表示这是一个数组,而且是一维的,“I”表示数组元素是int类型的。通过这个方法还可以打印其他类型的数组名来:
Array type
Corresponding class Name
int[]
[I
int[][]
[[I
double[]
[D
double[][]
[[D
short[]
[S
byte[]
[B
boolean[]
[Z
参考:https://blog.csdn.net/jdbdh/article/details/82117952
2.一维数组
数组的定义
相同数据类型的元素组成的一个集合。
特点
- 数组中的元素按线性排列。所谓的线性排列就是除第一个元素外的每个元素都有唯一的前驱元素,除最后一个元素外每个元素都有后继元素。
- 可以通过数组中的序号(数组序号从0开始计数)来访问数组中存放的元素。
- 删除效率低(要进行移位操作),查询操作高。
数组的声明
语法如下所示:
数据类型[] 数组名;(推荐) 或者数组类型 数组名 []; 如:int[] a;(推荐) 或者 int a [];
数组的初始化
- 静态初始化
静态初始化只能在声明的同时就初始化赋值。
int[] a = {1,2,3,4};
- 动态初始化
动态初始化带new 关键字。
int[] a = new int[4]; (4表示数组的长度) int[] a = new int[] {1,2,3,4};
数组的访问
- 获取数组的长度
int[] a = {1,2,3}; 数组长度:int length = a.length;
- 数组元素的访问
通过数组名称[下标]来访问数组里面的元素
int[] a = new int[]{1,2,3}; 显示数组中元素为2的方式为:a[1]
- 数组的遍历
int[] a = {1,2,3}; 数组的遍历为: for(int i = 0; i < a.length; i ++){ System.out.println(a[i] + " "); }
- 数组的拷贝
方式一:使用:System.arraycopy(src,srcPos,dest,destPos,length); src:源数组 srcPos:源数组的起始位置 dest:目标数组 destPos:目标数组的起始位置 length:复制的长度,即要复制的元素的个数 方式二:使用Arrays.copyOf(original, newLength); 此方法返回一个拷贝后的新的数组 original:源数组 newLength:目标数组的长度 两种方式的区别: 方式一更加灵活
- 数组的排序
方式一:冒泡排序 方式二:Arrays.sort
- 数组的打印
int[] array = {1,2,3}; System.out.println(Arrays.toString(array));
二维数组
数组初始化
动态初始化 数据类型 数组名 [][] = new 数据类型[m][n]
数据类型 [][] 数组名 = new 数据类型[m][n]
数据类型 [] 数组名 [] = new 数据类型[m][n]
例如:int [ ][ ] arr=new int [5][3]静态初始化 数据类型 [ ][ ] 数组名 = {{元素1,元素2....},{元素1,元素2....},{元素1,元素2....}.....};
例如:int [ ][ ] arr={{22,15,32,20,18},{12,21,25,19,33},{14,58,34,24,66},};
参考资料:菜鸟教程 https://www.runoob.com