一、javaSE(Java Platform, Standard Edition),标准版,各应用平台的基础,桌面开发和低端商务应用的解决方案。
--Java SE是基于JDK和JRE的,包括用于开发Java Web服务的类库,同时,Java SE为Java EE和Java ME提供了基础。 二、javaEE(Java Platform,Enterprise Edition),企业版,以企业为环境而开发应用程序的解决方案。
--Java EE 是在 Java SE 的基础上构建的,可以帮助咱们开发和部署可移植、健壮、可伸缩且安全的服务器端 Java应用程序。 三、javaME(Java Platform,Micro Edition),微型版,致力于消费产品和嵌入式设备的最佳方案。
--是为机顶盒、移动电话和PDA之类嵌入式消费电子设备提供的Java语言平台,包括虚拟机和一系列标准化的Java API。
一、一种面向对象的编程语言。 二、一种与平台无关的语言(根据JVM实现的)。 三、一种健壮性语言。 四、具备较高的安全性。
三:JDK、JRE与JVMjavascript
一、JVM:虚拟机,java虚拟机实际上只是一层接口,一层Java程序和操做系统通信的接口。.java源文件经编译生成.class字节码文件,
php
再由
java虚拟机加载并运行.class文件,若将.class文件当作一个软件,那么java虚拟机就是
css运行
这个软件的操做系统。
html 二、
JRE:java运行环境,包括:JVM+系统类库,它是运行Java程序的最小单位。
三、JDK:java开发工具包,包括:JRE+编译运行指令,它是开发Java程序的最小单位。
java
注:安装了JDK后,JRE已经存在无需额外安装。程序员
四:Java程序开发与运行机制算法
一、编写源程序,java源代码文件。
数据库
二、编译源程序,编译器编译编译成.java字节码文件。
编程
三、运行时,Java虚拟机(JVM)将.Java源文件编译成可运行的.class文件。
设计模式
四、Java环境变量的配置:
1)下载安装JDK,进入电脑的高级系统设置,找到环境变量;
2)新建JAVA_HOME :%安装路径%\Java\jdk(安装JDK路径);
3)path 后追加两个变量,即 : %JAVA_HOME%\bin 与%JAVA_HOME%\jre\bin;
4) 新建CLASSPATH系统变量,CLASSPATH= .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar (注意:必定要写 ".;",标点所有为英文状态下)。
五:Java中的一些规则
一、应用
1) 一个源文件中只
能有一个public修饰的类,其余类个数不限。
2)
一个
源文件有n个类时,编译结果的class文件就有n个。
3) 源文件的名字必须和public修饰的类名相同
。
4)
Java语言中单词拼写大小写严格区分。
5) main方法为入口方法。
6) 每一句以分号(;)结束。
二、注释
1) 单行注释//
2) 多行注释/* */
3) java文档注释/** */
三、标识符
1) 命名规则:
由字母、下划线、数字和美圆符号组成;
不能以数字开头;
区分大小写;
不能是关键字和保留字(goto、const);
长度通常不超过15个字符。
2)
驼峰式命名:
包名:所有小写。
类名:每一个单词首字母都大写。--大驼峰
方法名、参数名、变量名:第一单词首字母小写,后面其余单词首字母大写。--小驼峰
六:Java语言基础
一、关键字:Java中赋予了特殊含义的单词
访问控制 :public、private、protected
类,方法和变量修饰符 : abstract class extends final implements interface native new
static strictfp synchronized transient volatile
程序控制 : break continue return do while if else for instanceof switch case default
异常处理 : try cathc throw throws
包相关 : import package
基本类型 : boolean byte char double float int long short null true false
变量引用 : super this void
保留字 : goto const
二、数据类型
1) 基本数据类型:byte、short、int、long、float、double、char、boolean
数据类型 |
boolean |
byte |
char |
short |
int |
long |
float |
double |
void |
二进制位数 |
1 |
8 |
16 |
16 |
32 |
64 |
32 |
64 |
-- |
封装类 |
Boolean |
Byte |
Character |
Short |
Integer |
Long |
Float |
Double |
Void |
2) 引用数据类型: 字符串 String、数组 []、类 class、接口 interface、枚举 enum。
3) a.数据类型划分:
基本类型变量:数据的值
引用类型变量:数据的地址
b.声明的位置划分: 局部变量 全局变量
区别:
一、默认值:局部变量没有默认值,使用前必须初始化。
全局变量有默认值,默认为0,没必要须初始化。
二、声明位置:局部变量在方法内。 全局变量在方法外类内。
三、做用位置:局部变量只能在本身声明的方法里。全局变量在整个类中。
自动类型转换:从低级别到高级别,系统自动转的;
强制类型转换:把一个高级别的数赋给一个比该数的级别低的变量;
四、常量与变量
常量:在程序中,不会变化的数据。
变量:其实就是内存中的一个存储空间,用于存储常量数据。
做用:方便于运算。由于有些数据不肯定。因此肯定该数据的名词和存储空间。
特色:变量空间能够重复使用。
变量的做用域:做用域从变量定义的位置开始,到该变量所在的那对大括号结束;
生命周期:变量从定义的位置开始就在内存中活了;变量到达它所在的做用域的时候就在内存中消失了;
五、运算符
1) 算术运算符:+ 、 - 、 * 、 / 、 % 、 ++ 、 --
2) 赋值运算符:= 、 += 、 -= 、 *= 、 /= 、 %=
3) 关系运算符:> 、 < 、 >= 、 <= 、 == 、 !=
4) 逻辑运算符:
! (通常用于boolean类型前,表示非);
& (只要有一个false 最终结果就是false);
| (但凡是有一个true 最终结果就是true);
^ (若是两边同样,最终结果为false;若是两边不一样,最终结果为true);
&& (若第一个表达式结果为false,发生短路,第二个表达式不执行,最终结果为false);
|| (若第一个表达式结果为true,发生短路,第二个表达式不执行,最终结果是true)
5) 位运算符:用于操做二进制位的运算符。
~ 、 >> 、 << 、 >>>(无符号右移) 6) 字符串链接运算符:+ 7) 三目运算符:X ? Y : Z
X为boolean类型表达式,若x的结果为true,返回表达式Y的值,不然返回表达式Z的值。
七:Java中的流程控制
一、三种结构: 顺序、分支、循环
1) if语句
a.if(
){}
b.
if(){}else{}
c.
if(){}else if(){}
d.if(){if(){}else()}
e.if()执行语句 esle 执行语句 (
注意:执行语句只有一条语句的时候.能够将if esle 的大括号省略)
注意:()中为boolean类型表达式,
{}中为执行语句块
equals : 比较字符串用,比较的是内容。
== : 比较数值,比较的是引用的地址。
基本数据类型:变量名、变量值在栈中。
引用数据类型:变量名在栈中,变量值在常量池中。
object中的equals比较的是地址,底层封装的是==
== 比较基本数据类型时,比较的是内容
比较引用数据类型时,比较的是地址
String中也有equals,String中的equals被重写过了,比较的是内容。
2)switch多分支语句
import java.util.Scanner;
public class MySwitch {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("请输入今天星期几:");
int week = scan.nextInt();
switch (week) {
case 1:
System.out.println("星期一");
break;
case 2:
System.out.println("星期二");
break;
case 3:
System.out.println("星期三");
break;
case 4:
System.out.println("星期四");
break;
case 5:
System.out.println("星期五");
break;
case 6:
System.out.println("星期六");
break;
case 7:
System.out.println("星期天");
break;
default:
System.out.println("今天要不要上班呢?");
break;
}
}
}
注意:
一、表达式必须是int、byte、char、short、enmu、String类型
二、case后必须是常量或者finall变量,不能是范围
三、全部的case语句的值不能相同,不然编译会报错
四、default可要可不要
五、break用来执行完一个分支后使程序跳出switch语句块,不然会一直会执行下去。
if与switch比较:
a.if能够判断范围,也能够判断一个值switch只能判断指定的值。
b.若只判断指定的值,则使用switch语句,效率快 if判断范围,对数据判断灵活,自身的格式也比较灵活。
3)for循环
for ([循环变量初始值设定]; [循环条件判断]; [改变循环变量的值]){
循环体;
}
注意:
一、表达式2通常不能够省略,不然死循环
二、表达式3能够省略,可是在循环体中必须有语句修改变量,以使表达式2在某一时刻为false结束循环。
三、若同时省略表达式1,表表达式3,则至关于while(表达式2)语句
四、三个表达式均省略 即for(;;)语句,此时至关于while(true)语句
五、表达式一、表达式3能够是逗号表达式,以使循环变量值在修改时能够对其它变量赋值
六、通常状况下,表达式3,应向循环的结束变
1 public class Sfor { 2 3 public static void main(String[] args) { 4 for (int i = 1; i <= 9; i++) { 5 for (int j = 1; j <= i; j++) { 6 System.out.print(i+"*"+j+"="+j*i+" "); 7 } 8 System.out.print("\n"); 9 } 10 } 11 12 } 13 输出结果是: 14 1*1=1 15 2*1=2 2*2=4 16 3*1=3 3*2=6 3*3=9 17 4*1=4 4*2=8 4*3=12 4*4=16 18 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 19 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 20 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 21 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 22 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
4)while循环
while(条件表达式语句){
循环体语句;
}
do{
循环体;
}while( 循环条件判断);
注意:
一、当第一次执行时,若表达式=false时,则while语句不执行,而do/while语句执行一次后面的语句
二、必定要切记在switch循环中,若是没有break跳出语句,每个case都要执行一遍,在计算最终结果。
public class SWhile { public static void main(String[] args) { int x = 1; // 定义初值 int sum = 0; // 定义求和变量,用于存储相加后的结果 while(x <= 10) { sum += x; // 循环相加,也即 sum = sum + x; x++; } System.out.println(sum); } } public class CDoWhile { public static void main(String[] args) { int a = 10; int b = 10; // while循环语句 while(a == 8) { System.out.println("a == " + a); a--; } // do···while循环语句 do { System.out.println("b == " + b); b--; } while(b == 8); } }
二、break、return和continue
break:跳出某个循环
continue:跳出本次循环,进入下一轮
return:以return;终止方法的执行
注意:if外有循环能够用break、continue,单纯if不能够用。
三、递归
a.有返回值
b.有参数
c.可以有跳出循环的控制语句
d.本身调用本身
//用递归方法求累加
public class Recursion {
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.print("请输入要求的值:");
int N =scan.nextInt();
for(int n = 1; n <= N; n++) {
if(n % 20 == 0){
int sum = recursion(n);
System.out.println("1 到 " + n + " 的累加值是: " + sum);
}
}
}
public static int recursion(int n) {
if (n < 1) return 0;
return recursion(n - 1) + n;
}
}
八:重写(Overriding)与重载(Overloading)
方法重载:指同一个类中的多个方法具备相同的名字,但这些方法具备不一样的参数列表,即参数的数量或参数类型不能彻底相同
方法重写:存在子父类之间的,子类定义的方法与父类中的方法具备相同的方法名字,相同的参数表和相同的返回类型
注:
(1)子类中不能重写父类中的final方法
(2)子类中必须重写父类中的abstract方法
(3)子类函数的访问修饰权限不能小于父类的;
(4)子类的异常类型要小于父类;
重写方法的规则:
一、参数列表必须彻底与被重写的方法相同,不然不能称其为重写而是重载。
二、返回的类型必须一直与被重写的方法的返回类型相同,不然不能称其为重写而是重载。
三、访问修饰符的限制必定要大于被重写方法的访问修饰符(public>protected>default>private)
四、重写方法必定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。例如:父类的一个方法申明了一个检查异常IOException,
在重写这个方法是就不能抛出Exception,只能抛出IOException的子类异常,能够抛出非检查异常。
而重载的规则:
一、必须具备不一样的参数列表;
二、能够有不责骂的返回类型,只要参数列表不一样就能够了;
三、能够有不一样的访问修饰符;
四、能够抛出不一样的异常;
重写与重载的区别在于:
重写多态性起做用,对调用被重载过的方法能够大大减小代码的输入量,同一个方法名只要往里面传递不一样的参数就能够拥有不一样的功能或返回值。
用好重写和重载能够设计一个结构清晰而简洁的类,能够说重写和重载在编写代码过程当中的做用非同通常.
一、重写是在继承关系中;重载是在同一个类中。
二、重写是方法名、参数列表和父类相同;重载,方法名相同,参数列表不相同(个数、类型、顺序)。
三、重写返回值类型和父类相同;重载和返回值无关。
四、重写访问权限修饰符不能比父类更加严格;重载没有要求。
九:面向对象和面向过程
一、面向对象:是以具体的事物为单位,考虑的是它的特征(属性)和行为(方法)。
二、面向过程:是以具体的流程为单位,考虑功能的实现。
十:类和对象
一、对象:看得见摸得着的具体事物。
类:抽象化的概念
二、类和对象的关系:
类是对象的模板/抽象化的概念,对象是类的实例。
三、建立类和对象
类:
特征:全局变量/属性/成员变量
动做:方法
对象:
类名 对象名=new 类名()
注意:一个类能够建立多个对象,,每一个对象之间没有关系。
十一:内存图
一、栈:先进后出,存放基本数据类型变量名和变量值,引用数据类型的变量名,方法执行的时候进入栈中
二、堆:先进先出,new出来的对象的实例,包括类的属性个方法。
十二:构造方法
一、构造方法是new关键字调用的,用来帮助构建对象
二、显示构造对象
三、隐示构造对象(没有显示的状况下存在)
四、构造对象能够重载,参数类型不一致。
十三:关键字
一、static调用格式:
1)同一个类中:
静态的: 方法名 属性名
类名.方法名 类名.属性名
对象名.方法名 对象名.属性名
非静态的: 对象名.属性名 对象名.方法名
2)不一样类中:
静态的: 对象名.方法名 对象名.属性名
类名.方法名 类名.属性名
非静态的: 对象名.属性名 类名.方法名
注意:
一、static能够修饰属性、方法、代码块,不能够修饰类和构造方法。
二、静态方法随着类的加载而加载。
三、在静态方法区内的东西只有一份,全部的对象共享这一份空间,只要有一个对象对属性进行修改,全部的对象调用都是修改后的数据。
四、代码块的执行顺序:静态代码块(只被调用一次)>构造代码块{}>构造方法>普通方法(需调用)
二、this关键字
1)能够调用属性和方法。 this.属性名(全局变量) this.方法名();
2)在构造方法中:
a.this();括号内的参数个数、顺序、类型根据调用的方法来决定。
b.必须放在第一行,只能调用一次。
c.调用构造方法时只能在构造方法中调用,调用属性和方法时能够在构造方法中能够在普通方法中。
d.当全局变量和局部变量有重名字的时候,用this来区分。
三、super关键字
1)super指代父类对象。
2)super能够调用属性、方法、构造方法。
3)super调用父类的构造方法。
4)super调用构造方法时候必须放在第一行。
四、final最终的
1)能够修饰全局变量,声明的时候必须赋值,只能赋值一次。
2)能够修饰局部变量,声明时候能够不赋值,但也只能赋值一次。
3)能够修饰方法,能够正常使用,不能被重写。
4)能够修饰类,能够正常使用,不能被继承。
5)用final修饰的属性一般叫常量。
6)static final 全局变量。每一个字母都要大写。
五、this和super的区别
1)this指的是本类建立的对象。 super指代的是父类的对象
2)this能够调用属性、方法、构造方法。 super也能够调用属性、方法、构造方法。
3)this调用属性和方法的时候,调用本身本类的属性和方法。 若是本类没有,那就用super去父类中找
4)this调用构造方法调用,调用本类的其余构造方法。 super调用父类的构造方法。
5)this和super在调用构造方法的时候必须放在第一行。
6)this和super不能同时存在
六、最小做用域最强原则: 局域变量在此方法中,比全局变量在此方法中的做用强。
十四:面向对象的三大特征
一、封装
做用:提升代码的安全性 1)将属性私有化,并提供对外界的接口(get/set方法)。 2)用private修饰的属性和方法,只能在本类中使用。
二、继承
做用:提升代码的复用性,减小重复代码 1)子类能够继承父类非私有的属性和方法,不能继承构造方法和私有的属性和方法。 2)能够综合子类的共同特征来去提炼父亲的类。 3)子类在继承父类的各类属性和方法时,也能够有本身的属性和方法。 4)一个子类只能有一个父类,java只能单继承,不能多继承,由于多个类中的方法名相同,方法体不一样,不知使用哪一个。 5)一个类继承最顶端叫作基类或者超类,全部的超类叫作object 。 6)在继承关系中,若是父类没有无参数的构造方法,如何解决? a.子类中添加一个和父类构造方法参数列表相同的构造方法,经过super参数传递给父类的构造方法 b.若是父类容许修改的时候,能够在父类中建立一个无参的构造方法 7)在继承关系中,代码块的执行顺序:父静>子静>父构造代码块>父构造方法>子构造代码块>子构造方法
三、多态
1)分类 编译时多态:在编译过程当中察觉的多态,重载,向上转型。 运行时多态:在运行过程当中察觉的多态,向下转型。 2)向上转型、向下转型是在继承关系中,向下转型必须在向上转型的基之上。 3)在继承关系中,父类的对象能够指向子类的实例,父类引用实体方法的时候,是调用子类重写之后的方法。 4)向上转型 父类的引用指向子类的实体 父类类名 对象名=new 子类类(); 优势:减小重复代码,提升代码的复用性 缺点:父类的引用没法调用子类特有的属性和方法 解决方案:向下转型 5)向下转型: 子类对象的父类引用赋给子类 子类类名 对象名=(子类类名)父类对象; 6) instanceof 判断左边的对象是否属于右边的类 对象名 instanceof 类名(子类类名) 7)匿名对象 new 类名() 只有堆空间,没有栈空间,只能属于一次,为了节省代码。
十五:
抽象abstract与接口interface
abstract:
做用:节省代码,提升代码的复用性
1)抽象类格式:访问权限修饰符 abstract class 类名{ 2)抽象方法格式:访问权限修饰符 abstract 返回值类型 方法名(形式参数列表); 注意: 一、若是一个类里有抽象方法,那么这个类必须声明成抽象类。 二、一个类里面能够没有抽象方法,能够有非抽象方法, 三、类继承抽象类: 把子类也用abstract修饰,变成抽象类。 子类重写父类的抽象的方法 四、抽象类不能建立对象。 五、抽象类能够有构造方法,在建立子类的时候,super隐式调用父类的构造方法,将父类的属性和方法放到子类的对象空间里。 六、在继承你关系中,子类可以继承抽象类的各类属性和方法,除了私有的和构造方法。 七、只有公开的才能够和abstract连用,static final private 都不能够。 static属于类方法,不容许覆盖,abstract必须被覆盖。final不能被重写。
interface:
做用:规范了代码,提升代码的拓展性
一、格式:访问权限修饰符 interface 接口名称{}
二、实现类的格式:访问权限修饰符 class 实现类名 implements 接口名{必须重写接口中的全部的抽象方法}
三、接口中只有全局常量和抽象方法。
四、书写的时候能够省略部分修饰符,系统会默认给添上。
五、接口在实现的同时去继承,extends在implement前面。
六、接口能够多实现,实现的也必须是接口,方法名能够重复,实现类实现一个就好了,由于没有方法体,不会发生冲突。
抽象和接口的区别:
一、关键字:抽象类 abstract 接口interface
二、抽象类继承 extends 接口实现 implements
三、子类继承抽象类和 实现类实现接口的格式不一样
四、接口中只有全局变量和抽象方法 抽象类中有各类属性和方法
五、抽象类只能单继承 接口能够多实现
六、抽象类的子类只能继承一个父类 实现类能够实现多个接口,而且还能够继承父类
七、抽象类的做用:提升代码的复用性 接口的做用:一、规范代码二、提升代码的拓展新
十六:访问权限修饰符
本类中 本包中 其余包子类 其余包非子类
public √ √ √ √
protected √ √ √ ×
default √ √ × ×
private √ × × ×
十七:内部类
分类:成员内部类、静态内部类、局部内部类、匿名内部类
一、成员内部类: 一、能够用四种访问权限修饰符修饰 二、能够有本身的属性和方法,除了静态的。 三、可使用外部类的全部属性和方法,包括私有的。 四、建立对象 一、经过建立外部类对象的方式建立对象 外部类 外部类对象=new 外部类(); 内部类 对象名=外部类对象.new 内部类(); 二、内部类 对象名=new 外部类.new 内部类(); 二、静态内部类 一、格式:static class 类名{} 二、能够声明静态的属性和方法 三、可使用外部的静态的属性和方法 四、建立对象 内类名 对象名=new 内类名();(能够直接建立) 外部类名.内部类 对象名=new 外部类.内部类(); 包名.外部类名.内部类 对象名=new 包名.外部类.内部类(); 五、外部类与内部类同名时,默认是使用内部类对象调用外部类属性 this表明内部类对象 六、要想使用外部类属性,须要使用外部类对象调用 三、局部内部类 一、在方法中声明 二、只能用default修饰 三、能够声明属性和方法,但不能是静态的 四、建立对象,必须在声明内部类的方法内建立 五、调用方法的时候,局部内部类才会被执行 四、匿名内部类 一、匿名内部类只是用一次 二、格式: 父类或接口名 对象名=new 父类或接口名(参数列表){ 重写抽象方法 } 调用抽象方法:对象名.方法名
十八:经常使用设计模式
一、单例模式 分类:懒汉式、饿汉式
一、构造方法私有化
二、在本类中建立本类对象
三、保证对象的惟一性final
四、给外界提供获得对象的方法 static
五、在多线程中,饿汉式安全,懒汉式不安全
二、简单工厂模式 批量建立对象
1 建立工厂类 : 建立对象的方法
2 果汁类 是全部种类果汁的父类
3 在工厂类的方法中返回果汁类
4 根据测试类中传递的字符串判断到底返回哪一种果汁
5 测试类经过工厂类返回果汁对象
三、建造者模式
内部类使用场景 目的:静态内部类建立外部类对象
一、 建立外部类,在其中建立一个静态内部类
二、静态内部类中写属性,构造方法和set get方法
三、静态内部类中写一个方法,必须返回外部类对象
四、 给外部类建立对象,传递参数。
四、装饰者模式
一、在处理流中使用
二、子类重写父类的方法,提升父类方法的功能及效率
三、为了尽量减小重复代码,在重写的方法中用父类的对象调用父类原来的方法
四、获得父类对象能够经过将父类对象做为子类属性,经过子类构造方法传递父类对象
十九:数组及经常使用算法
一、声明: int a[]; int []b;
二、初始化:
动态初始化:
一、a=new int[2]; int[0]=1;... 动态初始化:
二、b=new b[]{3,4}; 静态初始化:int [] c={5,6};
三、数组经常使用的方法:
排序:Array.sort();
查找:Array.binarySearch();
打印:Array.toString();
复制:Array.copyof();
四、经常使用操做
一、冒泡排序 for(int i=0;i<a.length-1;i++){//控制外循环的次数 for(int j=0;j<a.length-1-i;j++){//控制内循环次数,比外循环少一次,与下一个比较 if(a[j]>a[j+1]){ int temp=a[j]; a[j]=a[j+1]; a[j+1]=temp; } } } 二、选择排序 for (int i = 0; i < a.length-1; i++) { int k=i; for (int j = i; j < a.length-1; j++) { if (a[k]>a[j+1]) { k=j+1; } } if(i!=k){ int temp=a[i]; a[i]=a[k]; a[k]=temp; } } 三、顺序查找 public static int find(int []b,int a){ for (int i = 0; i < b.length; i++) { if (a==b[i]) { return i; } } return -1; } 四、二分查找 public static int find(int b[],int a){ int max=b.length-1; int min=0; for (int i = 0; i < b.length; i++) { int midle=(max+min)/2; if(a==b[midle]){ return midle; }else if(a>b[midle]){ min=midle+1; }else if(a<b[midle]){ max=midle-1; } } return -1; }
二十:时间相关的类
一、Date类 .getTime();计算毫秒
二、SimpleDateFormat类 格式化时间 .format();返回的是String字符串
三、Calendar接口
日历字段之间的转换提供了一些方法
.get(Calendar.YEAR);
.get(Calendar.MONTH);// 默认是当前月份减一 从0开始的
.get(Calendar.DAY_OF_MONTH);
.get(Calendar.DAY_OF_WEEK);
Calendar calendar = Calendar.getInstance();
Date date = calendar.getTime();
四、Runtime运行时时间 .freeMemory(); 当前的系统剩余空间
五、System.exit(0);退出程序,参数是0是正常退出
System.gc();调用垃圾回收器,不必定可以起来,只是起到一个促进的做用
二十一:Java异常处理机制
异常:
一、在运行时期出现的不正常的事件,从继承的角度看,throwable是错误和异常的超类
二、错误Error:程序员没法处理的严重性问题,资源耗尽,jvm系统内部的错误
异常Exception:程序员能够处理的通常性问题,偶然的外界因素,编程的逻辑性错误
三、处理的必要性角度:
受检异常:编译时期就能发现的异常,必需要去处理的异常,继承自Exception
非受检异常:运行时期发现的异常,不是必需要去处理的,继承自RuntimeException
四、异常的处理机制: 当运行代码的时候首先先碰到异常,首先产生异常对象,抛出给jvm,jvm会携带异常对象,
去找代码可以处理或者捕获异常代码,若是找到了,则交给这个代码去处理,没有找打,则程序中止运行。
五、异常处理的两种方式
一、捕获异常
try{可能会产生异常的代码}catch(异常类 异常对象){处理异常的代码}
try{}catch(){}catch(){}... catch中子类异常放在父类异常的上面
try{]catch(){}finally{} finally中的代码必定会被执行到
try{}finally{}
1> 若是不去捕获异常,发生异常,异常后面的代码都不会被执行到
2> 若是捕获异常 try/catch后面的代码会被执行到
3> 捕获异常,try块中异常后面的代码不会被执行到
二、抛出异常
产生异常的位置不去处理异常,由调用此方法的调用者去处理异
throws 方法的声明后面 后面跟的是异常的类名 能够跟多个类名之间用逗号隔开 能够抛出受检异常和非受检异常
throw 方法的内部 异常的对象名 一个对象 抛出非受检异常
六、自定义异常
自定义
受检异常继承Exception
非受检异常 RuntimeException
final finally finalize区别
final 最终的,可修饰类,方法,属性
类:不能被继承
方法:不能被重写,能够被继承
属性:全局变量:声明是必须初始化。局部变量:声明的时候能够不初始化。但都只能赋值一次
finally 跟try/catch后面,不管是否发生异常都会被执行。关闭数据库,关闭数据流。
finalize 由系统调用,垃圾回收器回收以前作一些清理的工做。
二十二:
数组:长度固定,数据类型相同
集合:长度不固定,数据类型能够不一样,只能存对象
collection
List Set
Vector
ArrayList HashSet
LinkedList TreeSet
Map
HashMap
TreeMap
List:元素是有序的,元素能够重复。由于该集合体系有索引。
|--ArrayList:底层的数据结构使用的是数组结构。特色:查询速度很快。可是增删稍慢。线程不一样步。
|--LinkedList:底层使用的是链表数据结构。特色:增删速度很快,查询稍慢。
|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。
Set:元素是无序(存入和取出的顺序不必定一致),元素不能够重复。
|--HashSet:底层数据结构是哈希表。线程不一样步。 保证元素惟一性的原理:判断元素的hashCode值是否相同。若是相同,还会继续判断元素的equals方法,是否为true。
|--TreeSet:能够对Set集合中的元素进行排序。默认按照字母的天然排序。底层数据结构是二叉树。保证元素惟一性的依据:compareTo方法return 0。
Set集合的功能和Collection是一致的
一、HashSet: 哈希表 一、能够经过元素的两个方法,hashCode和equals来完成保证元素惟一性。若是元素的HashCode值相同,才会判断equals是否为true。
若是元素的hashCode值不一样,不会调用equals。
二、hashcode是内存地址经过必定运算的到的int类型的数值。返回值是int类型的数据,各个属性的hash值。 相加
三、hashcode值相同,也不必定是同一个对象
四、调用hashcode方法能够帮助去过滤调用彻底不可能相同的 对象,提升执行效率
五、equals最终肯定两个对象是否相同的
Map :
1)该集合存储键值对,一对一对往里存
2)要保证键的惟一性 |--Hashtable:底层是哈希表数据结构,不能够存入null键null值。该集合是线程同步的。JDK1.0,效率低。 |--HashMap:底层是哈希表数据结构。容许使用null键null值,该集合是不一样步的。JDK1.2,效率高。 |--TreeMap:底层是二叉树数据结构。线程不一样步。能够用于给Map集合中的键进行排序。 初始容量16,加载因子0.75 Map和Set很像。其实Set底层就是使用了Map集合。
二十三:Java多线程
1)线程和进程
一、线程
注意:多线程。从宏观角度:同时执行了多个线程。
从微观角度:同一时间只能执行一个线程
多个线程是竞争关系,抢占cpu资源,不然只能等待。
二、进程和线程的区别
进程是应用程序,线程是一条执行路径
进程有独立的内存空间,崩溃不会影响其余程序,
线程没有独立的空间,多个线程在同一个进程的空间,可能会影响其余线程
一个进程中,至少有一个线程
三、主线程与子线程
主线程:main方法产生的线程,也叫做UI线程。
子线程:除了主线程之外的,也叫工做线程。
守护线程(即daemon thread),是个服务线程,准确地来讲就是服务其余的线程。
四、建立线程的方式
a.建立一个类继承Thread,重写run方法,建立线程对象,启动线程,Thread.currentThread().getName(),哪一个线程调用,名字就是哪一个现成的名字.
b
.
共享资源类实现Runable接口,
重写run方法,建立共享资源对象
,
建立线程对象,将共享资源对象添加到线程中
,启动线程
c.实现callable接口,Callable接口表明一段能够调用并返回结果的代码;Future接口表示异步任务,是尚未完成的任务给出的将来结果。
因此说Callable用于产生结果,Future用于获取结果。
d.线程池ThreadPoolExcutor
new ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime, TimeUnit unit,BlockingQueue workQueue,RejectedExecutionHandler handler)
(1)corePoolSize: 线程池维护线程的最少数量 (core : 核心)
(2)maximumPoolSize: 线程池维护线程的最大数量
(3)keepAliveTime: 线程池维护线程所容许的空闲时间
(4)unit: 线程池维护线程所容许的空闲时间的单位
(5)workQueue: 线程池所使用的缓冲队列
(6)handler: 线程池对拒绝任务的处理策略
思考:说一下 runnable 和 callable 有什么区别?
Runnable接口中的run()方法的返回值是void,它作的事情只是纯粹地去执行run()方法中的代码而已;
Callable接口中的call()方法是有返回值的,是一个泛型,和Future、FutureTask配合能够用来获取异步执行的结果。
五、run和start的区别
每一个线程都是经过某个特定Thread对象所对应的方法run()来完成其操做的,方法run()称为线程体。经过调用Thread类的start()方法来启动一个线程。
start()方法来启动一个线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,能够直接继续执行下面的代码; 这时此线程是处于就绪状态, 并无运行。
而后经过此Thread类调用方法run()来完成其运行状态, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, Run方法运行结束, 此线程终止。而后CPU再调度其它线程。
run()方法是在本线程里的,只是线程里的一个函数,而不是多线程的。 若是直接调用run(),其实就至关因而调用了一个普通函数而已,直接待用run()方法必须等待run()方法执行完毕
才能执行下面的代码,因此执行路径仍是只有一条,根本就没有线程的特征,因此在多线程执行时要使用start()方法而不是run()方法。
run没有开辟新的栈空间,没有新线程,都是主线程在执行
start开辟了新的栈空间,在新的栈空间启动run()方法
六、线程的调度
setPriority();分配优先级,默认5,最低1,最高10
.join();插队,阻塞指定的线程等到另外一个线程完成之后再继续执行
.sleep();须要设置睡眠时间
.yield();礼让,当执行到这个方法时,会让出cpu时间,立马变成可执行状态
sleep和pield的区别:
sleep 线程进入被阻塞的状态
yeild 线程转入暂停执行的状态
七、打断线程的终止方式
一、用标记,当终止线程时,会执行完run方法
二、stop()方法,不建议使用,会执行不到特定的代码
三、interrupt(),只能中断正在休眠的线程,经过抛异常的方法中断线程的终止。
InputStream inputStream=System.in;
int m=inputStream.read();
myThread2.interrupt();//经过外界输入打断
八、线程的五种状态
新建(new) 就绪(runnable) 执行(running) 死亡(dead) 阻塞(blocked)
一、新建状态(New):新建立了一个线程对象。
二、就绪状态(Runnable):线程对象建立后,其余线程调用了该对象的start()方法。该状态的线程位于“可运行线程池”中,
变得可运行,只等待获取CPU的使用权。即在就绪状态的进程除CPU以外,其它的运行所需资源都已所有得到。
三、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
四、阻塞状态(Blocked):阻塞状态是线程由于某种缘由放弃CPU使用权,暂时中止运行。直到线程进入就绪状态,才有机会转到运行状态。
阻塞的状况分三种:
(1)、等待阻塞:运行的线程执行wait()方法,该线程会释放占用的全部资源,JVM会把该线程放入“等待池”中。
进入这个状态后,是不能自动唤醒的,必须依靠其余线程调用notify()或notifyAll()方法才能被唤醒,
(2)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入“锁池”中。
(3)、其余阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。
当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程从新转入就绪状态。
五、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
思考:(1)sleep() 和 wait() 有什么区别?
sleep():方法是线程类(Thread)的静态方法,让调用线程进入睡眠状态,让出执行机会给其余线程,等到休眠时间结束后,线程进入就绪状态和其余线程一块儿竞争cpu的执行时间。
由于sleep() 是static静态的方法,他不能改变对象的机锁,当一个synchronized块中调用了sleep() 方法,线程虽然进入休眠,可是对象的机锁没有被释放,其余线程依然没法访问这个
对象。
wait():wait()是Object类的方法,当一个线程执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其余线程可以访问,
能够经过notify,notifyAll方法来唤醒等待的线程
(2)notify()和 notifyAll()有什么区别?
若是线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。
当有线程调用了对象的 notifyAll()方法(唤醒全部 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会
去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的全部线程移动到锁池中,等待锁竞争。
优先级高的线程竞争到对象锁的几率大,倘若某线程没有竞争到该对象锁,它还会留在锁池中,惟有线程再次调用 wait()方法,它才会从新回到等待池中。而竞争到对象锁的线程
则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。
2)同步
发生在两个以两个以上的线程中
解决代码的重复问题 优势:提升了线程中数据的安全性 缺点:下降了执行效率
一、同步代码块 synchronized(锁){同步代码块} 注意:锁分任意锁和互斥锁,锁是对象,琐是惟一的。
二、同步方法 public synchroinzed 返回值类型 方法名(){同步代码}
三、在共享资源中:
线程操做相同,锁是this
synchronized (this) {// 同步代码块,包含同步代码块。任意锁,互斥锁。
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "---" + ticket--);
} else {
break;
}
}
线程操做不相同,锁是共享资源对象
synchronized (card) {
card.setMoney(card.getMoney() + 1000);
System.out.println("Boy+1000---" + card.getMoney());
}
四、在同步方法中:
共享资源,线程操做相同,资源类中的锁是this
共享资源,线程操做不相同,资源类中的锁也是this
public synchronized void input(){
money+=100;
System.out.println("input+100----"+money);
}
(1)什么是死锁?
死锁是指两个或两个以上的进程在执行过程当中,因为竞争资源或者因为彼此通讯而形成的一种阻塞的现象,若无外力做用,它们都将没法推动下去。此时称系统处于死锁状态或系统
产生了死锁,这些永远在互相等待的进程称为死锁进程。是操做系统层面的一个错误,是进程死锁的简称,最先在 1965 年由 Dijkstra 在研究银行家算法时提出的,它是计算机操做系统
乃至整个并发程序设计领域最难处理的问题之一。
(2)怎么防止死锁?
死锁的四个必要条件:
一、互斥条件:进程对所分配到的资源不容许其余进程进行访问,若其余进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源
二、请求和保持条件:进程得到必定的资源以后,又对其余资源发出请求,可是该资源可能被其余进程占有,此事请求阻塞,但又对本身得到的资源保持不放
三、不可剥夺条件:是指进程已得到的资源,在未完成使用以前,不可被剥夺,只能在使用完后本身释放
四、环路等待条件:是指进程发生死锁后,若干进程之间造成一种头尾相接的循环等待资源关系
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之 一不知足,就不会发生死锁。理解了死锁的缘由,尤为是产生死锁的四个必要条件,
就能够最大可能地避免、预防和 解除死锁。因此,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确 定资源的合理分配算法,避免进程永久占据系统资源。
此外,也要防止进程在处于等待状态的状况下占用资源。所以,对资源的分配要给予合理的规划。
(3)说一下 synchronized 底层实现原理?
synchronized能够保证方法或者代码块在运行时,同一时刻只有一个方法能够进入到临界区,同时它还能够保证共享变量的内存可见性。Java中每个对象均可以做为锁,
这是synchronized实现同步的基础:
普通同步方法,锁是当前实例对象
静态同步方法,锁是当前类的class对象
同步方法块,锁是括号里面的对象
(4)synchronized 和 Lock 有什么区别?
首先synchronized是java内置关键字,在jvm层面,Lock是个java类;
synchronized没法判断是否获取锁的状态,Lock能够判断是否获取到锁;
synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程当中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),不然容易形成线程死锁;
用synchronized关键字的两个线程1和线程2,若是当前线程1得到锁,线程2线程等待。若是线程1阻塞,线程2则会一直等待下去,而Lock锁就不必定会等待下去,若是尝试获取不到锁,
线程能够不用一直等待就结束了;
synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(二者皆可);
Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少许的同步问题。