JAVA
来源:
sun公司,oracle收购
版本情况:
1.0 ....1.5(5.0)....8.0(1.8)...11(2.1)
安装JDK ,JDK 编译环境 ,JRE 运行环境
配置:我的电脑(属性),高级,环境变量,系统变量,path(内容的最前 + ";"在分号前复制jdk的bin目录的位置)
javac 文件(包括后缀) 编译
java 文件的名字(没有后缀) 运行
java语言特点:半编译半解释(通过jvm,多个平台,各有自己的jvm)
源代码(.java)->javac -> java字节码(.class)->java ->本地机械码文件(cpu只能运行机械码)
jvm:java虚拟机
main: 主函数 :代表程序的开始和程序的结束
// :注释 ,不能运行的代码,给我们程序员说明程序用的
public class Test{
public static void main(String args[]){ //从这里开始
System.out.println("hello hehe"); //在系统的控制台输出(一定)的内容
} //到这里结束
}
{} :块 代码块
数据类型:
基本数据类型(4类8种):
整数:
byte:1个字节 ,8位 ,-128 ~127
short:2个字节,16位,-2^15 ~2^15-1
int:4个字节,32位,-2^31 ~2^31-1 (默认)
long:8个字节,64位,-2^63 ~2^63-1
所有书写的整数,默认都是int类型,long类型的数字默认是最后+L
所有书写的整数,默认是十进制
数字前面 0, 为8进制
数字前面 0x,为16进制
进制转换最好通过二进制进行中转
浮点数:
float: 4个字节,32位
double: 8个字节,64位
默认的所有的书面写的浮点数都是doubule,float类型的数字默认+f
不能参与严格的计算,可以用来显示
字符:2个字节 ,单引号引起来一个字符
char:本质是short,但是通过字符表映射成字母显示
支持转义字符: '\''
回车:\n
支持unicode \u
布尔值:1个字节
boolean: true ,false
不参与算数运算,只能进行逻辑和关系运算
引用数据类型(无数):
数组 :一组数 []
类 :6章
接口:7章
数据类型转换:
显式转换:程序员通过代码主动转换
整数 ,浮点数,字符 ;(datatype)data
如果大范围的数据类型转向小类型的范围,有溢出的可能(看数据是否超过要转的类型的取值范围)
隐式转换:计算机替程序员把数据转换(转的效果和显式一样)
计算机何时替我们做隐式转换
小范围自动转大范围
byte,short,char 直接跳到int
浮点型最大
变量:
使用变量的前提:
1.声明变量 int a ;
2.变量的初始化 a = 1;
作用域:块作用域
在声明块及内部的浅套块可以使用,外部则不认;
大作用域和嵌套作用域有同名的变量,使用的时候优先使用离自己声明更近的变量
函数块里声明的变量:局部变量
类块声明的变量:实例变量或者叫属性
运算符:
算数:+ - * / %
/:两个整数相除,结果只能还是整数,浮点去掉
%:符号看被除数
++ 自增 ,--
语法点: 位置在变量前,先完成自增运算 ,后作为一个变量来使用
位置在变量后,则先作为变量使用,最后在独自完成自增(滞后性)
比较运算:> < >= <= == !=
逻辑运算: 短位: && , || ,! (如果表达式的左边结果已决定整个表达式的结果,则不计算右边)
按位: & , |
位运算:必须是整数才能计算
& , | ,~ ,^ ,>> ,<< ,>>>
计算机底层存储补码,一切运算都以补码进行
1.10进制转成2进制原码(负数 符号位1,其他和正数一样)
如果正数,则直接当补码用
如果负数 , 先转反码(符号位不变,其他1变0,0变1),在把反码转补码(符号位不变,反码其他位+1)
2.两个补码运算,运算结果一定是补码,看符号位是否0,0则直接当原码,转回10进制
如果符号位是1,则先把补码(符号位不变,其他-1),在把反码转原码(符号位不变,其他1变0,0变1),
0则直接当原码,转回10进制
赋值运算:= += -= *= /= %= >>= <<= >>>=
逻辑上 a+=b a= a+b ,逻辑上相等,但是实际上有区别。
条件运算: ? :
运算符优先级:
1>2>3
流程控制语句:
选择:
?:
if( 布尔值 ){ }
如果布尔值为true,则执行语句块的代码,否则不执行
int chengji = 90;
if(chengji >=90 && chengji<=100){
System.out.println("A");
}
if(chengji >=80 && chengji<90){
System.out.println("B");
}
if(chengji >=70 && chengji<80){
System.out.println("C");
}
if(chengji >=60 && chengji<70){
System.out.println("D");
}
if(chengji >=0 && chengji<60){
System.out.println("E");
}
缺点:不方便写,性能差
if(chengji<60){
System.out.println("E");
}else{
if(chengji>=60 && chengji <70){
System.out.println("D");
}else{
if(chengji >=70 && chengji <80){
System.out.println("C");
}else{
if(chengji >=80 && chengji <0){
System.out.println("B");
}else{
System.out.println("A");
}
}
}
}
缺点乱:
if (chengji < 60) {
System.out.println("E");
} else if (chengji >= 60 && chengji < 70) {
System.out.println("D");
} else if (chengji >= 70 && chengji < 80) {
System.out.println("C");
} else if (chengji >= 80 && chengji < 0) {
System.out.println("B");
} else {
System.out.println("A");
}
缺点:性能不极致
key:int byte short char 1.7版本之后 枚举 ,字符串
case值不能重复,
跳出:
break:跳出包含当前break语句最近的switch或者循环块
continue:跳出本次循环
不允许其他语句出现在break或者continue之后
switch (chengji/10) {
case 10:
System.out.println("A");
break;
case 9:
System.out.println("A");
break;
case 8:
System.out.println("B");
break;
case 7:
System.out.println("C");
break;
case 6:
System.out.println("D");
break;
default:
System.out.println("E");
break;
}
缺点:不能写条件,只能匹配值,使用场景少
循环语句:
while:事前事后双判断,只要符合条件就重复执行
do while: 直接执行,事后判断,只要符合就重复执行
例子:
int a = 1;
while(a<6){
System.out.println(a++);
}
do{
System.out.println(a++);
}while(a<6);
for(int a = 1;a<6;a++){
// 0.初始化表达式;1.条件表达式;3.循环后操作表达式
System.out.println(a);
// 2.循环体
}
0.1,2,3,1,2,3,1,2,3........
初始化表达式先执行,仅执行一次;
执行条件表达式,表达式结果为TRUE执行循环体,但是如果结果为false则直接跳出循环
执行玩循环体后,执行循环后操作表达式;
执行玩循环后操作表达式之后重新执行条件表达式
for适合处理已知循环次数的循环问题(int i =0;i ;i++)
while:适合解决未知循环次数的循环问题 (true){ },内部陪一个跳出条件语句
do while:
引用类型:
数组:
基本数据类型变量:
int a;
//变量的声明
a = 1;
//变量的赋值
int b= 2;
//变量的初始化
数组的变量:
int []arr;
//数组的声明
arr = new int[2];
//数组的创建,new 开辟内存空间
arr[0] = 1;
//数组的赋值
arr[1] = 2;
//数组的赋值
int []brr = {1,2};
//静态初始化
数组最小下标0,最大数组长度-1 ;长度是length属性
二维数组的声明,创建,遍历
冒泡:
int [] arr = {9,4,3,1,2,8,7,6,5};
//冒泡排序
//1.先找数组中最小的数
int temp ;
int count = 0;
for(int j = 0;j //有多少个数,就挪多少次,把所有数都挪过一遍,顺序就自然出来 System.out.println("开始寻找第"+(j+1)+"轮寻找最小数"); for(int i=0;i //把数组中从前到后,向临的两个元素进行比较大小,如果比不过就换位置,为了把最大或者最小挪到最后 System.out.print("本次比较,当前比较的数是第"+i+"下标"+arr[i]+",和第"+(i+1)+"下标"+arr[i+1]+" " ); if(arr[i] //比较前后数的大小,互换位置 temp = arr[i]; arr[i] = arr[i+1]; arr[i+1] = temp; System.out.println("本次比较发现"+arr[i]+"大于"+arr[i+1]+",所以互相换位置 "); } for (int z = 0; z < arr.length; z++) { System.out.print(arr[z]+","); } System.out.println(); count++; } } System.out.println("~~~~~~~"); System.out.println(count); 选择: int arr[] = {192,976,23,56,768,342,132,56,9,4,0,123}; int temp; //找到当前最大的数 ,直接把最大的数和最后一个数交换 int maxIndex ; //记录当前最大值的下标 for(int j = 0;j //找多少轮最大值,有多少数找多少次 maxIndex = 0; //默认最左边0下标为当前的初始最大值下标 for(int i= 0;i //从第一个数进行比较一直比较到能比较的最后一个数 if(arr[maxIndex] //如果比较后发现当前默认最大值比不过,那被比较的值应该是新的最大值,记录它的下标 maxIndex = i; } } if(maxIndex != arr.length-1-j){ //如果最大值的下标和应该的位置不匹配,则互换值 temp = arr[maxIndex]; arr[maxIndex] = arr[arr.length-1-j]; arr[arr.length-1-j] = temp; } } for(int i:arr){ //输出 System.out.print(i+","); } 二维数组的遍历: int [][]brrs = {{1,2,3},{4,5,6},{28,1}}; for(int j =0;j for(int i=0;i System.out.print(arrs[j][i]+","); } System.out.println(); } 方法:函数的声明和调用(不用对象参与叫函数,需要对象调用才是方法) 函数的优点:1.代码量变少,变整洁 2.可读性强 3.忽略细节 4.易于维护和修改 函数 的声明:只是创建了一个带有某种特定功能的代码块,自己不能运行,必须被调用 语法: 所谓实参:是为了满足函数功能必须给予的基础数据 所谓形参:由于声明函数的时候没有实际数据,但是为了完成代码算法的编写 公式中需要临时代替数据参与的变量;其实就是函数的局部变量。 public static void|datatype functionName (datatype varname [,...]){ // 权限控制 修饰符 没有|返回值类型 函数名字 (数据类型 变量名)形参列表 //函数的代码块(固定的功能代码) [return data ;] //如果不用void则必须return ;return永远只能是当前函数的最后一句话 } 函数的调用:具体执行函数的功能 functionName (data[,...]) // 使用的函数名字 ()实参列表) 重载: 一个类中,同名的方法 参数列表不同:个数不同,类型不同 面向对象: what: 面向对象的思想:是一种编程思想 面向对象的特性:封装,继承,多态 ! 面向对象的语言:java语言有关面向对象的语法! why: 解决复杂问题,大型软件的开发和维护问题 how: 解决对象 对象:现实世界在代码中的代表,把一个复杂的现实问题抽象成代码中的对象来解决问题。 需要计算机提供对象,(计算机如何知道对象应该是啥样的??) 类class: 语法:class{ 类的成员: 属性 方法 // 块,嵌套类 } 类是对象的模板,对象是类 的代表 对象的诞生: 类名 引用 = new 构造器; 引用和对象的区别: 引用是保存对象的地址值,通过引用来代指对象。 匿名对象:没有引用的对象。 优点:省内存。 缺点:不能重复使用。 建议:优先使用,但是如果发现需要重复使用则一定不能用匿名。 构造器语法: 构造器的名字必须和所在类的名字完全一样。 类名 (形参列表){ 代码块 } 默认构造器: 构造器可以不写,系统默认送一无参,无内容的构造器;但凡有一个构造器则系统不送了 构造器和方法 的区别: 构造器也叫构造方法(一方面长得像,功能也像;永远都不是方法) 构造器永远没有返回值,不需要写void,(除了权限控制符)也不能有其他的修饰符 构造器重载: 构造器允许有多个,多个构造器可以发生重载,(形参列表不一致) 构造器的作用: 创建对象(程序员写的构造器跟创建对象无关) 为了对象的初始化 构造器的内存: 构造器默认生产的对象,每个对象都有自己独立的属性,方法统一。 this的作用: 第一种作用,当"this." ,代表当前正在运行或者使用或者生产的对象(当前对象)。 第二种作用,当"this()",代表当前类的某个构造器 this.用来区分局部变量和对象的属性 this(),用来构造器,代码的复用 this()只能第一行;和super()不能同时使用 当发生继承的时候如何构造: 先运行super,再运行this 继承: 什么类可以继承另外一个类(什么时候应该使用继承) 当子类是父类 继承的实现,优缺点 java语法中一个类只要被extends 就能成为另一个类的父类;一个类只能有一个父类; 如果父类没有无参的构造器,子类则必须调用有参的super才可以不报错; 代码简洁,支持复用 不能任意代码都拷贝,子类语法受到父类的限制,只能使用1次继承,每次子类诞生其 实都同时诞生了一个父类对象,子类代码依赖父类代码 子类和父类的代码如何调用 子类实例化生成对象前需要先调用父类构造器,每一个子类对象的生产都伴随一个它 的父类对象诞生,通过super()实现父类对象的诞生 super的作用: 第一种作用,当"super." ,代表当前正在运行或者使用或者生产的对象的父类对象(当前对象)。 第二种作用,当"super()",代表当前类的父类的某个构造器 super()只能第一行;和this()不能同时使用 子类对象和父类对象的关系 每一个子类对象都有一个super指向他自己的父类对象,子类自身没有父类的任何代码,只能通过 父类对象取获取父类的资源 继承如何在封装中体现 继承如何实现多态 封装:隐藏某些细节或者内容。 利用访问权限控制符实现隐藏。 包: package:物理上文件夹,逻辑上功能相似的类 打包:package 告诉计算机当前类属于哪个包 引包:import 告诉计算机需要哪个包的类来帮助运行 默认引的包:java.lang 语言包(String ,Object,System) 访问权限控制符 private default protected public 私有的 默认的 受保护的 公有的 从小~~~~到 public:所有人都可以看到和使用 private:所有人都无法看到和使用除了自己,(子类也无法使用) default:同一个包中可以使用 protected:同一个包中可以使用,如果是别的包想用(别的包中的类必须是当前类的子类才能用) 把属性私有(private),同时提供公有(public)set(赋值)|get(获取值)的方法 多态:不修改代码,调整功能通过添加子类重写方法,调用父类引用传入子类对象来实现。 1.数据类型可以转换 2.子类是一个完美父类 3.子类可以选择自己的行为 一种事物多种形态 语法:一.方法的重写 重写和重载的相同点: 1.方法的名字都相同 不同点: 1.位置不同:重载一个类中 重写在父类和子类中, 2.参数列表:重载形参不一致(个数,类型) 重写形参一致 3.返回值:重载不看返回值 重写返回值必须相同 重写的两个方法的返回值和形参必须完全相等 二.引用数据类型的转换 引用数据类型部分能转,部分不能转。看继承 如果两个引用类型存在继承关系,编译不报错,如果是子类转父类可以,如果是父类转子类运行报错(除非父类对象原本是子类转的), ;如果不存在继承关系编译直接报错; 显示转换: char a = 'a'; (int) a ; (Boolean)a; Person p = new Person(); (Monkey)p 父类转子类需要显示转换 向下转型 隐式转换: 子类对象可以直接隐式转换成父类对象; 向上转型 其他多态: 接口: 抽象类的进阶:接口 ,没有构造器 what:不是类,是一种特殊的代码块(嵌套级别和类一样);本身是用来对java单继承的补充(利用接口多实现) 单继承(只能有一个父类),多实现(可以实现多个接口) [public] Interface interfaceName{ [public] [final] [static] datatype varname = value; [public] [abstract] [datatype|void] functionName(datatype varname [,...]); } where: 子类实现 (implements) how: 接口的成员: 常量和抽象方法 一个类如果实现一个接口,则必须实现这个接口的所有抽象方法,如果不实现则子类变成抽象类 why:为了不破坏java的单继承,(一个子类主继承谁?父类(父类继承资源),接口留下要求) 多继承问题: 内部类:类的成员 what: 内部类的分类: 1.成员内部类:正常的内部类 2.静态内部类:静态内部类只能访问外部类的静态资源 3.匿名内部类:用来实现接口类型的对象 4.局部内部类: public class TestInner { public static void main(String[] args) { Outer o = new Outer(); Outer.Inner in = new Outer().new Inner(); System.out.println(in.getA()); } } class Outer{ private int a = 1; class Inner{ public int getA(){ return a; } public void setA(int acopy){ a = acopy; } } } why:1.方便访问外部类的私有资源 2.不可见性 3.解决多继承冲突问题 public class Test1 { public static void main(String[] args) { Z z = new Z(); z.haha(); z.new zz().haha(); } } class Asd{ // int a = 1; void haha(){ } } interface f{ // int a = 2; int haha(); } class Z extends Asd { int a = 2; void haha(){ System.out.println("z拥有了Asd的haha无参方法"+a); } class zz implements f{ @Override public int haha() { // TODO Auto-generated method stub System.out.println("z的zz拥有了f的haha无参方法"+a); return 0; } } } 多态的运行: 继承问题: 1. 单纯的父类对象指向父类引用 只能调用父类的属性和父类的方法。 2. 单纯的子类对象指向子类引用 可以调用父类的属性和父类的方法,以及自己的属性和自己的方法 (如果自己的属性或者方法 和父类重复优先使用自己的),如果非要调用父类的属性或者方法需要+super. 多态问题: 3. 子类对象指向父类引用 只能调用父类有的属性和父类的方法;如果父类的属性和父类的方法自己也有; 属性优先调用父类的,但是方法如果自己有则优先调用子类自己的 (子类方法 中如果调用的属性子类有则调用子类的,子类没有再调用父类的) 4. 子类对象指向父类引用 如果非要使用子类自己的属性,需要先向下转型(把子类对象的引用指回子类自己) 5. 向下转型前需要通过instanceof来判断对象的实际类型是否满足子类引用 修饰符:static: what:静态的,类的 where:块,属性,方法,类 why:静态块一般用来给类进行初始化 静态属性:有一些属性我们希望他的值能统一,只存一份,一份改则全改。 静态方法:方便调用,适合设计一些不需要本类的数据但是应该归本类提供的方法 how: 语法: 静态块:不能使用非静态的属性 当第一次new所属类的对象或者通过类名调用静态资源的时候会运行静态块的代码 但是只运行一次,而且首先运行 静态方法:不能使用非静态的属性,可以使用非静态的局部变量; 可以被类名直接调用,也可以被对象直接调用 静态变量:在普通方法和构造器 中可以使用静态变量。没有静态的 局部变量,静态可以修饰的变量一定是属性,这种变量也 叫静态变量或者类变量(可以被类名直接调用)。 类变量也可以正常被对象调用; 静态变量在静态块执行之前已经存在 普通块:当生产对象的时候而且一定在构造器之前运行 内存使用情况: 当对象第一次被new的时候: 0.父类的静态变量(父类加载进方法区:java的反射) 1.先执行父类的静态块的代码, 1.2:子类的静态变量(子类加载进方法区) 1.3:再执行子类的静态块(静态块永远只执行一次,永远第一个执行) 1.5:父类的普通变量(父类对象诞生) 2.执行父类普通块的代码(永远在构造器之前执行,每次new对象都执行) 3.执行父类的构造器的代码 3.5:子类的普通变量(子类对象诞生) 4.执行子类的普通块 5.执行子类的构造器 所有的静态变量都保存在自己类的静态区中,所有对象公用一个静态变量 final: what:最终的最后的 where:变量,方法,类 how: final变量:常量,值一旦付给就不可再变 final方法:不可被重写的方法 final类:不可被继承 why:代码不希望改,锁内存 单例模式:特殊问题的方案(来源于23种特殊的面向对象的设计模式) 案例: 要求:私有构造器,私有静态本类的属性(赋值),公有的提供属性的方法 class Single{ private static Single s= new Single(); //封装 static:静态方法只能调用静态属性 任意类型都可以作为类的属性,总点new出来一个对象 private Single(){ //只有构造器私有,才能避免其他的类随便new构造器,生产对象 } public static Single getInstance(){ //方便其他类访问 只有静态的方法 才能不需要对象调用 return s; } } abstract:抽象的 where:类,方法 how: 抽象方法:没有代码块,在形参列表后用分号结尾; 一旦一个类中有抽象方法,则这个类也必须抽象, 注定永远不会被执行也无法执行, 不能被静态修饰, 不能被final修饰, 抽象类:不能被实例化,可以有构造器 抽象类可以全是抽象方法;抽象了也可以没有抽象方法 子类如何继承一个抽象类作为父类,则要不然实现所有的抽象方法,要不然自己变成抽象类 why:抽象方法为了被重写 抽象类为了被继承 抽象类的抽象方法可以看作父类对子类的要求,子类应该尽可能实现(覆盖)父类的要求 异常: 错误:int a ; 没有初始化的变量直接被使用报错,语法错误(书写错误) 异常:1.下标越界,/0 运行时异常,(逻辑上错误) 2.语法无误,但是编译出错(不想运行的异常,通过一场处理方案调整不错)检查性异常 异常处理的方案: 1.积极方案: try ..catch: try:监视问题代码,在try块中的代码如果出问题,会自动new一个异常的对象发送给catch进行匹配 一旦被try捕获则停止继续执行try块里的代码 catch:捕获try提供的异常,看是否和参数的类型匹配如果匹配则执行catch块的代码, catch可以提供多个,但是异常的类型必须从小到大(继承关系) finally:无论发生什么情况一定会执行,只要进入try肯定要执行finally的代码(函数跳出也要执行) 2.消极方案: throws:抛出(甩锅),throws一般放在方法的形参列表后面 + 异常的类型: 如果该方法中发现相同类型的异常,则把异常对象抛出给调用方, 两种结果:第一种,谁都不处理,交给java虚拟机。 第二种,中间使用trycatch 处理问题。 throw:抛(补全异常类型) 把异常对象抛给异常处理模块 public static void main(String[] args) throws NewException { int age = 10; if(age<18){ throw new NewException(); } } public class NewException extends Exception{ } API: UTIL: Object : toString:把对象转成字符串来方便表示,格式如下:getClass().getName() + "@" + Integer.toHexString(hashCode()) hashcode:哈希值不相等则对象一定不相等;反之不一定相等。 equals:Object类的equals比较两个对象的地址值,如果相等则true否则false, 如果自定义类想要使用equals建议重写。 如果重写equals应该一起重写hashcode finalize:当对象被垃圾回收器回收的时候由垃圾回收起运行。 1.需要引用赋值为null,2.所在类重写finalize方法,3.手动调用System.gc(); 包装类: Integer:int intValue:把包装类的值转成基本数据类型 !!!parseInt:把字符串转成对应的包装类 !!!高速缓存:建议如果要使用的包装类对象是-128~127之间通过valueOf来获取 常用API: Integer i1 = new Integer(10); System.out.println(i1.toString()); System.out.println(i1.compareTo(new Integer(0))); //比较两个Integer对象,相等=0,大于1小于-1 System.out.println(i1.hashCode()); System.out.println(Integer.max(1, 3)); System.out.println(Integer.toBinaryString(9)); System.out.println(Integer.toHexString(9)); System.out.println(Integer.toOctalString(9)); System.out.println(Integer.valueOf(10)); !!自动拆/装箱: Integer i3 = 111;//把一个基本数据类型直接当对象使用,自动装箱 System.out.println(i3-1);//把一个对象直接当基本数据类型来使用,自动拆箱 Character:char:无法把字符串转成字符 API: System.out.println(Character.isDigit('1'));//字母是否是数字内容 System.out.println(Character.isLetter('啊'));//是否是文字 System.out.println(Character.isWhitespace('\n'));//是否空格或者换行 System.out.println(Character.toLowerCase('C'));//大小写转换 System.out.println(Character.toUpperCase('a')); System.out.println(Character.isLetterOrDigit('c'));//是否字母或者数字 System.out.println(Character.isLowerCase('C'));//是否小写 System.out.println(Character.isUpperCase('c'));//是否大写 Boolean:boolean Boolean b = Boolean.valueOf("fasle"); //字符串非真全是假 Byte:byte Float:float :浮点型没有告诉缓存 Double:double Short:short Long:long String: 设计说明: 1.字符串的内容都保存在一个value引用指向的字符数组对象中,为了节省空间。 2.由于所有相同内容的字符串可能引用同一个value空间,所以不能随便修改,value要求常量,私有不允许随便改。 1.构造器: 1.无参 String s1 = new String(); String s2 = null; System.out.println(s2.length()); System.out.println(s1.length()); //生成了字符串对象,只不过内容没有,但是空间存在,可以正常使用方法。 2.参数为字符数组的 字面量的隐藏代码: char c1[] = {'a','b','c'}; String s3 = new String(c1); 3.参数为字符串的 String s5 = new String("abc"); 4.参数为字节数组的 字符串编码问题: String Client = new String("abc你我他".getBytes("utf-8"),"iso8859-1"); String Server = new String(Client.getBytes("iso8859-1"),"utf-8"); 2.字面量:"字符串类型的对象",所有字符串对象都是常量(字符串类型的引用不是) 字面量的字符串对象有系统优化,对象在常量池中诞生,有且仅有一份,所有内容相同的字面量是同一份内存 String s = "abc";//诞生了一个对象 String s1 = new String("abc");//诞生了new 的对象,如果“abc” 之前存在则不需要诞生,如果不存在则需要诞生 System.out.println(s1); intern : String s6 =s5.intern(); //返回一个常量池中的字符串对象,如果当前池中有对象则直接返回对象的地址, //如果没有则先把当前值放到常量池中去再返回当前的地址 //能够强行把堆空间的字符串升到常量池中去 3.(高效)字符串拼接: StringBuffer :可变字符序列,线程安全, 速度稍慢,append追加 , StringBuilder:可变字符序列,线程不安全,速度较快,append追加。 public static void main(String[] args) { String s1 = "abc"; StringBuffer sb = new StringBuffer(s1); for(int i =0;i<100000;i++){ sb.append(i); } s1 =sb.toString(); System.out.println(s1.length()); } 4.常用API: String s = ";AAab;cdef;abcd;"; String s1 = new String(s); System.out.println(s.charAt(5));//根据坐标返回对应的字母,拿他能取首字母 System.out.println(s.substring(5, 8));//对字符从开始坐标截取到终止坐标前一个 System.out.println(s.length());//求字符的个数 System.out.println(s.trim());//去两端空格 System.out.println(s.endsWith("bcd"));//判断是否以某个字符串结尾 System.out.println(s.equals(s1)); System.out.println(s.compareTo("abcdefabcd"));//根据字典顺序比较大小 0相等 正数大于 负数小于 System.out.println(s.concat("hahaha"));//字母串拼接 System.out.println(s.contains("wxy"));//是否包含字符串 System.out.println(s.indexOf("bc"));//获取字符串的位置 System.out.println("".isEmpty());//判断字符串内容是否为空字符串 System.out.println(s.lastIndexOf("bc"));//从后往前找字符串的位置(位置永远是从做往右算) System.out.println(s.replace("abc", "$"));//字符串替换 System.out.println(s.startsWith("abc")); System.out.println(s.toLowerCase()); //转小写 System.out.println(s.toUpperCase());//转大写 String sarr[]= s.split(";");//根据符号对字符串拆分,前有分隔符可以拆,后有不算,$不好使 System.out.println(sarr[3]); char c [] = s.toCharArray(); byte b[] =s.getBytes(); 邮箱: String mail = "[email protected]"; String []mailarr = mail.split("@"); char arr[] = mailarr[0].toCharArray(); char c = mail.charAt(0); if((c>=97&&c<=122) ||(c>=65&&c<=90)){ if((mail.endsWith(".com")||mail.endsWith(".cn"))){ if(mailarr.length==2){ if(mailarr[1].indexOf(".")==mailarr[1].lastIndexOf(".")){ for(int i =1 ;i if(!((arr[i]>=97&&arr[i]<=122) ||(arr[i]>=65&&arr[i]<=90)||Character.isDigit(arr[i]))){ System.out.println("@前只能由数字或者字母组成"); break; } } }else{ System.out.println(".符号在@之后有且仅能有一个"); } }else{ System.out.println("@规定只能有一个"); } }else{ System.out.println("结尾只能是.com或者.cn"); } }else{ System.out.println("首字符应该是字母"); } Math: System.out.println(Math.E); System.out.println(Math.PI); System.out.println(Math.abs(-13)); System.out.println(Math.ceil(13.9)); System.out.println(Math.floor(13.1)); System.out.println(Math.exp(3.0)); System.out.println(Math.log(10)); System.out.println(Math.log10(10)); System.out.println(Math.sqrt(4)); System.out.println(Math.round(13.4)); System.out.println(Math.pow(3, 4)); System.out.println(Math.random());//大于等于0 并且小于1 随机数: Random r = new Random(10); for(int i=0;i<10;i++){ // System.out.println(Math.floor(Math.random()*10)+1); System.out.println(r.nextInt(100)+1);//大于等于0,小于参数 } Date:日期 Date d = new Date(); //不支持时区 System.out.println(d); d.setYear(2018-1900); System.out.println(d.getYear()+1900);//1900年到现在多少年 System.out.println(d.getMonth());//0~11 System.out.println(d.getDate()); //一个月的第几天 System.out.println(d.getDay()); //一周的第几天 System.out.println(d.getHours()); System.out.println(d.getMinutes()); System.out.println(d.getSeconds()); System.out.println(d.getTime());//1970年到现在的毫秒数 Calendar:日历 ,抽象类,获取的永远是子类的对象 Calendar c = Calendar.getInstance(); System.out.println(c.get(Calendar.YEAR)); System.out.println(c.get(Calendar.MONTH)); System.out.println(c.get(Calendar.DATE)); System.out.println(c.get(Calendar.HOUR)); System.out.println(c.get(Calendar.MINUTE)); System.out.println(c.get(Calendar.SECOND)); System.out.println(c.get(Calendar.DAY_OF_YEAR)); System.out.println(c.get(Calendar.DAY_OF_WEEK)); System.out.println(c.getTime().getTime()); //1548729018840 c.setTime(new Date(1548729018840l)); SimpleDateFormat: Date d = new Date();//创造日期 System.out.println(d); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); //创造格式 String date = sdf.format(d); System.out.println(date); //通过格式转换日期 System.out.println(sdf.parse(date)); //把符合格式的字符串转回日期 集合: what:是一种存放使用数据的容器。 数组的长度是固定的,数组容器元素的类型是统一的 集合不需要固定长度,随用随涨;集合中可以存放任意类型的数据 why:替代数组的方案 how: 元素的存储,修改,提取 int arr [] = new int[5]; arr[0] = 1; arr[1] = 2; arr[2] = 3; arr[3] = 4; arr[4] = 5; System.out.println(arr); arr[0] = 10; System.out.println(arr[0]); ArrayList al = new ArrayList(); al.add(1); al.add(2); al.add(3); al.add(4); al.add(5); al.add(new Date()); System.out.println(al); al.set(0, 10); System.out.println(al.get(0)); 1.集合的框架: 背图 2.集合常用API list: al.isEmpty(); al.add(1); al.set(0, 10); al.size(); al.contains(2) al.remove(0); al.toArray(); al.indexOf(3) al.clear(); al.get(0); Map: HashMap hm = new HashMap(); hm.put("一", "haha");//把键值对放入容器 hm.put("一", "gaga"); hm.put("二", "hehe"); System.out.println(hm.remove("二")); System.out.println(hm.get("二")); System.out.println(hm.containsKey("一")); System.out.println(hm.size()); System.out.println(hm.isEmpty()); // System.out.println(hm.replace("一", "gaga")); System.out.println(hm.values()); System.out.println(hm); Map集合的遍历: //1.keySet Set s = hm.keySet(); Iterator it = s.iterator(); while(it.hasNext()){ System.out.println(hm.get(it.next())); } //2.entrySet Set s1 = hm.entrySet(); Iterator it1 =s1.iterator(); while(it1.hasNext()){ Entry entry=(Entry)it1.next(); System.out.println(entry.getKey()+" "+entry.getValue()); } 3.迭代器: Iterator it = hs.iterator(); //it=利用hs集合对象获取一个hs集合专用的迭代器 while(it.hasNext()){ System.out.println(it.next()); } 迭代器模式 4.集合的工具类 Collections 和Collection的区别? 一个是工具类,一个是线性集合的父接口 Collections.sort(al); System.out.println(Collections.max(al)); Collections.reverse(al); 5.集合中泛型的使用 泛型:集合中的泛型用来约束元素的数据类型 IO流 文件: File:路径 API: File f = new File("C:/test1"); // f.createNewFile(); //创建新文件 f.delete(); //删除路径上的资源 f.mkdir(); //创建文件夹 // f.mkdirs(); //创建指定路径的文件夹 System.out.println(f.exists()); //路径上是否有资源 System.out.println(f.getAbsolutePath()); //获取绝对路径 System.out.println(f.isDirectory()); //判断是否为文件夹 System.out.println(f.getParentFile()); //获取当前路径的父路径 System.out.println(f.getName()); //当前路径的文件名 System.out.println(f.canExecute()); //能否执行 System.out.println(f.canRead());//能不能读 System.out.println(f.canWrite());//能不能写 System.out.println(f.isHidden());//是否隐藏 File farr[] = f.listFiles();//返回当前路径的下一层子路径 System.out.println(farr[0]); System.out.println(farr[1]); 常用流:数据传输过程中形成的管道 三种流分类: 方向:输入,输出 内容:字节,字符 能力:节点,处理(低级,高级):高级流必须依赖低级流 FileWriter f = new FileWriter(filename, append) //append 决定输出文件是否覆盖源文件内容 文本文件的拷贝: //1.找到数据源 File fsr = new File("E:/timg.jpg"); //2.通过数据源获取文件名字 String filename = fsr.getName(); //3.通过名字在另一个空间生成新文件 File newFile = new File("D:/"+filename); newFile.createNewFile(); //4.把源数据复制新文件中 //4.1 读取源数据(1次读一个,往新文件中写一个),一直读写到源文件结束 FileReader fr = new FileReader(fsr); FileWriter fw = new FileWriter(newFile); int a = fr.read(); while(a!=-1){ fw.write(a); a = fr.read(); } fw.flush(); 二进制文件的拷贝: //1.找到数据源 File fsr = new File("E:/11.mp4"); //2.通过数据源获取文件名字 String filename = fsr.getName(); //4.1 读取源数据(1次读一个,往新文件中写一个),一直读写到源文件结束 FileInputStream fr = null; FileOutputStream fw = null; try { fr = new FileInputStream(fsr); fw = new FileOutputStream("D:/"+filename); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } BufferedInputStream bis = new BufferedInputStream(fr); BufferedOutputStream bos = new BufferedOutputStream(fw); byte[] b = new byte[4096]; //高速缓存 int a; try { a = bis.read(b); while(a!=-1){ bos.write(b,0,a); a = bis.read(b); } bos.flush(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { bis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { bos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { fr.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } 序列化: public class TestObject { public static void main(String[] args) throws IOException { People p1 = new People(); p1.name = "hehe"; p1.age = 18; File f = new File("C:/people.txt"); FileOutputStream fos = new FileOutputStream(f); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(p1); oos.flush(); oos.close(); fos.close(); } } class People implements Serializable{ String name; int age; void haha(){ System.out.println(name+"haha"); } } 反序列化: File f = new File("C:/people.txt"); FileInputStream fis = new FileInputStream(f); ObjectInputStream ois = new ObjectInputStream(fis); ((People)ois.readObject()).haha(); ois.close(); fis.close(); JDBC: mysql8.0 Class.forName("com.mysql.cj.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/scott?useSSL=FALSE&serverTimezone=UTC","root", "root"); Statement st = conn.createStatement(); ResultSet rs = st.executeQuery("select ename,job from emp where deptno = 10"); while (rs.next()) { System.out.println(rs.getString("ename")+","+rs.getString("job")); } Oracle: Class.forName("oracle.jdbc.driver.OracleDriver"); //加载驱动 Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger"); //通过驱动和信息创建连接通道 Statement stat = conn.createStatement(); //给管道匹配一个空的sql对象 ResultSet rs = stat.executeQuery("select ename,job from emp where deptno = 10"); //把sql语句绑定到对象上并且执行,并把结果返回给结果集resultset while(rs.next()){ //遍历一条数据,如果还有则返回true System.out.println(rs.getString("ename")+","+rs.getString("job")); //根据数据的类型获取对应数据 } preparestatment: Class.forName("oracle.jdbc.driver.OracleDriver"); //加载驱动 Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger"); //通过驱动和信息创建连接通道 // Statement stat = conn.createStatement(); PreparedStatement ps = conn.prepareStatement("select ename from emp where ename=? and deptno = ?"); ps.setString(1, "SMITH"); ps.setString(2, "9 or 1=1"); ResultSet rs = ps.executeQuery(); rs.next(); System.out.println(rs.getString("ename")); DButil: public class DButil { static{ try { Class.forName("oracle.jdbc.driver.OracleDriver"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block System.out.println("数据库蹦蹦了"); } } public static Connection getConn() throws ClassNotFoundException, SQLException{ //加载驱动 Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "usermanager", "abc123"); conn.setAutoCommit(false); return conn; } } 网络