1,取模:%:取余数. 结果的符号取决于被模数
int i3 = 12 % (-5); //2
int i4 = -12 % (-5); //-2
System.out.println(i3);
System.out.println(i4);
2,short s = 10; *******************
//s += 3;编译不通过
s = (short)(s + 1);//不建议如此实现
s += 1;//既可以实现运算,又不会更改s的数据类型
3,
System.out.println('*' + ' ' + '*'); //输出ASCII码的具体数值
System.out.println("*" + " " + "*"); //输出字符
4,//方法一:提供一个临时变量。
//int temp = m;
// m = n;
// n = temp;
//System.out.println("m:" + m + " n:" + n);
//方法二:当m和n较大时,有可能出现精度损失
//m = m + n;//m = 12 + 5;
//n = m - n;//n = 17 - 5;
//m = m - n;//m = 17- 12
//System.out.println("m:" + m + " n:" + n);
//方法三:优点:没有上面两种方法的缺点。 缺点:难!
m = m ^ n;
n = m ^ n;//(m ^ n) ^ n == m
m = m ^ n;//(m ^ n) ^ m == n
System.out.println("m:" + m + " n:" + n);
5, String binary = Integer.toBinaryString(i);
String hex = Integer.toHexString(i);
6, 条件判断之间可以嵌套
①如果多个条件之间是“互斥”关系,多个条件语句上下顺序是自由的。
②如果多个条件之间存在“包含”关系,要求范围小的写在范围大的上面。
7, import java.util.Scanner;
Scanner s = new Scanner(System.in);
int score = s.nextInt();
Scanner 使用分隔符模式将其输入分解为标记,默认情况下该分隔符模式与空白匹配。
然后可以使用不同的 next 方法将得到的标记转换为不同类型的值。
8, //& 与 && 的区别:&:不管左边是true还是false,右端都会进行运算。
// &&:当左端为false时,右端不再进行运算
//| 与 || 的区别:|:当左端为true时,右端照样做运算。
// ||:当左端为true时,右端不再进行运算。
7,三元运算符
//练习:如何使用三元运算符,输出三个数中的较大值。
int m = 12;
int n = 23;
int k = -9;
int max1 = (m > n)? m : n;
int max2 = (max1 > k)? max1 : k;
System.out.println(max2);
8,//1.如何定义一个数组
//1.1数组的声明
String[] names;
int scores[];
//1.2初始化
//第一种:静态初始化:初始化数组与给数组元素赋值同时进行。
names = new String[]{"周爽","郭强强","俞乾龙"};
//第二种:动态初始化:初始化数组与给数组元素赋值分开进行。
scores = new int[4];
//2.如何调用相应的数组元素:通过数组元素的下角标的方式来调用。
//下角标从0开始,到n -1 结束。其中n表示的数组的长度。
scores[0] = 87;
scores[1] = 89;
scores[3] = 98;
//3.数组的长度:通过数组的length属性。
System.out.println(names.length);//3
System.out.println(scores.length);//4
//4.如何遍历数组元素
// System.out.println(names[0]);
// System.out.println(names[1]);
// System.out.println(names[2]);
for(int i = 0;i < names.length;i++){
System.out.println(names[i]);
}
9,//在break和continue语句之后不能添加其他语句,应为永远也不可能被执行!
10,label:for(int i = 1;i < 5;i++){
for(int j = 1;j <= 10;j++){
if(j % 4 == 0){
//break;
//continue;
//break label;
continue label;
}
System.out.print(j);
}
System.out.println();
}
11,无限循环:
for(;;){}
或者
while(true){
}
说明:一般情况下,在无限循环内部要有程序终止的语句,使用break实现。若没有,那就是死循环!
12,class Test{
public static void main(String[] args){
boolean flag = false;
long start = System.currentTimeMillis();//获取系统当前的毫秒数
/*1:*/for(int i = 2;i <= 100000;i++){//实现100000以内的自然数的遍历
//如何判断i是否为一个质数
for(int j = 2;j <= Math.sqrt(i);j++){
if(i % j == 0){
flag = true;
break;
//continue l;
}
}
if(!flag){//if(flag == false){
System.out.println(i);
}
flag = false;
}
long end = System.currentTimeMillis();
System.out.println("所花费的时间为:" + (end - start));
//35535--加上break:10059--使用Math.sqrt():
}
}
13,int[] array1, array2;
array1 = new int[] { 2, 3, 5, 7, 11, 13, 17, 19 };
System.out.println(array1);
array2 = array1;
System.out.println(array2);//array1和array2代表的栈的地址一样,指向的堆也相同
14,杨辉三角
/*
* 使用二维数组打印一个 10 行杨辉三角.
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
....
【提示】
1. 第一行有 1 个元素, 第 n 行有 n 个元素
2. 每一行的第一个元素和最后一个元素都是 1
3. 从第三行开始, 对于非第一个元素和最后一个元素的元素.
yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
*/
public class Test {
public static void main(String[] args) {
int[][] yangHui = new int[10][];
//1.初始化二维数组
for(int i = 0;i < yangHui.length;i++){
yangHui[i] = new int[i + 1];
}
//2.显式的为二维数组的每个元素赋值
for(int i = 0;i < yangHui.length;i++){
for(int j = 0;j < yangHui[i].length;j++){
yangHui[i][0] = yangHui[i][i] = 1;
if(i > 1 && j > 0 && j < i){
yangHui[i][j] = yangHui[i-1][j] + yangHui[i-1][j-1];
}
}
}
//遍历二维数组
for(int i = 0;i < yangHui.length;i++){
for(int j = 0;j < yangHui[i].length;j++){
System.out.print(yangHui[i][j] + " ");
}
System.out.println();
}
}
}
15,//1.二维数组的初始化
scores2 = new int[][]{{1,2,3},{3,4,5},{6}};//静态初始化
//names = new String[6][5];//动态初始化的方式一
names = new String[6][];//动态初始化的方式二
names[0] = new String[5];
names[1] = new String[4];
names[2] = new String[7];
names[3] = new String[5];
names[4] = new String[8];
names[5] = new String[5];
//错误的初始化方式
//names = new String[][];
//names = new String[][5];
//2.如何来引用具体的某一个元素
int[][] i = new int[3][2];//int[] i[] = new int[3][2];
i[1][0] = 90;
i[2][1] = 100;
//3.数组的长度
//二维数组的长度:length属性
System.out.println(i.length);//3
//二维数组中元素的长度
System.out.println(i[0].length);//2
System.out.println(names.length);//6
System.out.println(names[4].length);//8
System.out.println();
//4.如何遍历二维数组
for(int m = 0;m < scores2.length;m++){//控制行数
for(int n = 0;n < scores2[m].length;n++){
System.out.print(scores2[m][n] + " ");
}
System.out.println();
}
//5.内存结构
int[] x,y[];
//int[] x;//一维
//int[] y[];//二维
y = new int[3][2];
x = y[0];
//x[0] = y[1][2];
System.out.print(y);
System.out.print(x);
16,// 数组元素的反转
for (int x = 0, y = arr.length - 1; x < y; x++, y--) {
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
17,// // 使用冒泡排序使数组元素从小到大排列
// for (int i = 0; i < arr.length - 1; i++) {
// for (int j = 0; j < arr.length - 1 - i; j++) {
// if (arr[j] > arr[j + 1]) {
// int temp = arr[j];
// arr[j] = arr[j + 1];
// arr[j + 1] = temp;
// }
// }
// }
// //使用直接选择排序使数组元素从小到大排列
// for(int i = 0; i < arr.length - 1; i++){
// int t = i;//默认i处是最小的
// for(int j = i;j < arr.length;j++){
// //一旦在i后发现存在比其小的元素,就记录那个元素的下角标
// if(arr[t] > arr[j]){
// t = j;
// }
// }
// if(t != i){
// int temp = arr[t];
// arr[t] = arr[i];
// arr[i] = temp;
// }
// }
import java.util.Arrays
Arrays.sort(arr);
18,异常
//1.数组下标越界的异常:java.lang.ArrayIndexOutOfBoundsException
int[] i = new int[10];
// i[0] = 90;
// i[10] = 99;
// for(int m = 0;m <= i.length;m++){
// System.out.println(i[m]);
// }
//2.空指针的异常:NullPointerException
//第一种:
// boolean[] b = new boolean[3];
// b = null;
// System.out.println(b[0]);
//第二种:
// String[] str = new String[4];
// //str[3] = new String("AA");//str[3] = "AA";
// System.out.println(str[3].toString());
//第三种:
int[][] j = new int[3][];
j[2][0] = 12;
//对于基于基本数据类型的变量创建的数组:byte short int long float double char boolean
//1.对于byte short int long 而言:创建数组以后,默认值为0
//2.对于float double而言:默认值是0.0
//3.对于char而言:默认为空格
//4.对于boolean而言:默认为false
//5.对于引用类型的变量构成的数组而言:默认初始化值为null。以String为例
19,//关于数组在内存中的结构(看ppt) ??????????
int[] myInt = {12,13,14};
int[] myInt1;
myInt1 = new int[]{12,1,3,14};
20,排序集合:
21,/*
* 方法的重载(overload)
* 要求:1.同一个类中 2.方法名必须相同 3.方法的参数列表不同(①参数的个数不同②参数类型不同)
* 补充:方法的重载与方法的返回值类型没有关系!
*/
22,三、类的属性(成员变量)
* 成员变量 vs 局部变量
* 相同点:1.遵循变量声明的格式: 数据类型 变量名 = 初始化值
* 2.都有作用域
* 不同点:1.声明的位置的不同 :成员变量:声明在类里,方法外
* 局部变量:声明在方法内,方法的形参部分,代码块内
* 2.成员变量的修饰符有四个:public private protected 缺省
* 局部变量没有修饰符,与所在的方法修饰符相同。
* 3.初始化值:一定会有初始化值。
* 成员变量:如果在声明的时候,不显式的赋值,那么不同数据类型会有不同的默认初始化值。
* byte short int long ==>0
* float double ==>0.0
* char ==>空格
* boolean ==>false
* 引用类型变量==>null
* 局部变量:一定要显式的赋值。(局部变量没有默认初始化值)
* 4.二者在内存中存放的位置不同:成员变量存在于堆空间中;局部变量:栈空间中
*
* 总结:关于变量的分类:1)按照数据类型的不同:基本数据类型(8种) & 引用数据类型
* 2)按照声明的位置的不同:成员变量 & 局部变量
23,四、类的方法:提供某种功能的实现
* 1)实例:public void eat(){//方法体}
* public String getName(){}
* public void setName(String n){}
* 格式:权限修饰符 返回值类型(void:无返回值/具体的返回值) 方法名(形参){}
*
* 2)关于返回值类型:void:表明此方法不需要返回值
* 有返回值的方法:在方法的最后一定有return + 返回值类型对应的变量
* 记忆:void 与return不可以同时出现一个方法内。像一对“冤家”。
*
* 3)方法内可以调用本类的其他方法或属性,但是不能在方法内再定义方法!
24,一、类的第三个成员:构造器(constructor 构造方法) construction CCB ICBC oop
* constructor:建造者
* 构造器的作用:①创建对象 ②给创建的对象的属性赋值
*
* 1.设计类时,若不显式声明类的构造器的话,程序会默认提供一个空参的构造器
* 2.一旦显式的定义类的构造器,那么默认的构造器就不再提供。
* 3.如何声明类的构造器。格式:权限修饰符 类名(形参){ }
* 4.类的多个构造器之间构成重载
*
*
* 二、类对象的属性赋值的先后顺序:①属性的默认初始化 ②属性的显式初始化③通过构造器给属性初始化
* ④通过"对象.方法"的方式给属性赋值
25,/*
* 方法的参数传递(重点、难点)
* 1.形参:方法声明时,方法小括号内的参数
* 实参:调用方法时,实际传入的参数的值
*
* 2.规则:java中的参数传递机制:值传递机制
* 1)形参是基本数据类型的:将实参的值传递给形参的基本数据类型的变量
* 2)形参是引用数据类型的:将实参的引用类型变量的值(对应的堆空间的对象实体的首地址值)传递给形参的引用类型变量。
*
*/
26,/*
* 可变个数的形参的方法:
* 1.格式:对于方法的形参: 数据类型 ... 形参名
* 2.可变个数的形参的方法与同名的方法之间构成重载
* 3.可变个数的形参在调用时,个数从0开始,到无穷多个都可以。
* 4.使用可变多个形参的方法与方法的形参使用数组是一致的。
* 5.若方法中存在可变个数的形参,那么一定要声明在方法形参的最后。
* 6.在一个方法中,最多声明一个可变个数的形参。
*/
27.public void sayHello(String ... args){
for(int i = 0;i < args.length;i++){
System.out.println(args[i] + "$");
}
System.out.println("=====");
}
结果:hello China$
hello BeiJing$
=====
28, 3.子类继承父类以后,父类中声明的属性、方法,子类就可以获取到。
* 明确:当父类中有私有的属性或方法时,子类同样可以获取得到,只是由于封装性的设计,使得子类不可以直接
* 调用罢了。
* 子类除了通过继承,获取父类的结构之外,还可以定义自己的特有的成分。
*
* extends:子类是对父类功能的“扩展”,明确子类不是父类的子集。
29,/*
* this:
* 1.可以用来修饰属性、方法、构造器
* 2.this理解为当前对象或当前正在创建的对象.比如:this.name,this.show();
*
* 3.可以在构造器中通过“this(形参)”的方式显示的调用本类中其它重载的指定的构造器。
* 要求:1.在构造器内部必须声明在首行!
* 2.若一个类中有n个构造器,那么最多有n-1个构造器中使用了this(形参);
*
*/
30,* import:
* 1)显式导入指定包下的类或接口
* 2)写在包的声明和源文件之间
* 3)如果需要引入多个类或接口,那么就并列写出
* 4)如果导入的类是java.lang包下的,如:System String Math等,就不需要显式的声明。
* 5)理解.*的概念。比如java.util.*;
* 6)如何处理同名类的导入。如:在util包和sql包下同时存在Date类。
* 7)import static 表示导入指定类的static的属性或方法
* 8)导入java.lang.*只能导入lang包下的所有类或接口,不能导入lang的子包下的类或接口
*/
//import java.util.Scanner;
//import java.util.Date;
//import java.util.List;
//import java.util.ArrayList;
31,if (p instanceof Graduate) {
System.out.println("a graduate");
}
判断是否包含
32,* super:可以用来修饰属性、方法、构造器
*
* 1)当子类与父类中有同名的属性时,可以通过"super.此属性"显式的调用父类中声明的属性.
* 若想调用子类的同名的属性“this.此属性”
*
* 2)当子类重写父类的方法以后,在子类中若想再显式的调用父类的被重写的方法,就需要使用“super.方法”
*
* 3)super修饰构造器:通过在子类中使用“super(形参列表)”来显式的调用父类中指定的构造器。
* >在构造器内部,“super(形参列表)”必须要声明在首行!
* >在构造器内部,“this(形参列表)”或“super(形参列表)”只能出现一个!
* >当构造器中,不显式的调用“this(形参列表)”或“super(形参列表)”其中任何一个,默认调用的是
* 父类空参的构造器!
* 建议:设计一个类时,尽量要提供一个空参的构造器! *****************************
33,/*
* 面向对象的特征三:多态性
* 1.多态性指的是什么?多态性,可以理解为一个事物的多种表型形态。
* 1)方法的重载与重写 2)子类对象的多态性
*
* 2.子类对象的多态性使用的前提:①要有类的继承②要有子类对父类方法的重写
*
* 3.程序运行分为编译状态和运行状态。
* 对于多态性来说,编译时,"看左边",将此引用变量理解为父类的类型
* 运行时,"看右边",关注于真正对象的实体:子类的对象。那么执行的方法就是子类重写的。
*
* 4.子类对象的多态性,并不使用于属性。
*/
34,Person p1 = new Man();// 向上转型
//子类对象的多态性:父类的引用指向子类对象Person p1 = new Man();// 向上转型
Woman w = (Woman) p2;// 向下转型,使用强转符:()
w.shopping();
35,if (p1 instanceof Woman) {
System.out.println("hello!");
Woman w1 = (Woman) p1;
w1.shopping();
}
if (p1 instanceof Man) {
Man m1 = (Man) p1;
m1.entertainment();
}
if (p1 instanceof Person) {
System.out.println("你好!");
}
36,// 1.基本数据类型:根据基本数据类型的值判断是否相等。相等返回true,反之返回false
// 注:两端数据类型可以不同,在不同的情况下,也可以返回true。
// 2.引用数据类型:比较引用类型变量的地址值是否相等。
37,int i = 12;
int j = 12;
System.out.println(i == j);// true
char c = 12;
System.out.println(i == c);// true
float f = 12.0F;
System.out.println(i == f);// true
int k = 65;
char a = 'A';
System.out.println(k == a);// true
Object obj1 = new Object();
Object obj2 = new Object();
System.out.println(obj1);
System.out.println(obj2);
System.out.println(obj1 == obj2);// false
Person p1 = new Person();
Person p2 = new Person();
Person p3 = p1;
System.out.println(p1 == p2);// false
System.out.println(p1 == p3);// true
38,//equals():
//①只能处理引用类型变量②在Object类,发现equals()仍然比较的两个引用变量的地址值是否相等
********//①像String 包装类 File类 Date类这些重写Object类的equals()方法,比较是两个对象的"实体内容"是否完全相同。
39,import java.util.Vector;
/*
* 利用Vector代替数组处理:从键盘读入学生成绩(以负数代表输入结束),找出最高分,并输出学生成绩等级。
提示:数组一旦创建,长度就固定不变,所以在创建数组前就需要知道它的长度。
而向量类java.util.Vector可以根据需要动态伸缩。
创建Vector对象:Vector v=new Vector();
给向量添加元素:v.addElement(obj); //obj必须是对象
取出向量中的元素:Object obj=v.elementAt(0);
注意第一个元素的下标是0,返回值是Object类型的。
计算向量的长度:v.size();
若与最高分相差10分内:A等;20分内:B等;
30分内:C等;其它:D等
*/
40,//依次将学生成绩村放入v中
Integer score1 = new Integer(score);
v.addElement(score1);
41,//4.通过v.elementAt(i)依次获取填入v中的元素,同时判断一下各个分数的等级并输出。
for(int i = 0;i < v.size();i++){
Integer score = (Integer)v.elementAt(i);
42,* static,静态的,可以用来属性、方法、*代码块(或初始化块)、*内部类
*
* static修饰属性(类变量):
* 1.由类创建的所有的对象,都共用这一个属性
* 2.当其中一个对象对此属性进行修改,会导致其他对象对此属性的一个调用。vs 实例变量(非static修饰的属性,各个对象各自拥有一套副本)
* 3.类变量随着类的加载而加载的,而且独一份
* 4.静态的变量可以直接通过“类.类变量”的形式来调用
* 5.类变量的加载是要早于对象。所以当有对象以后,可以“对象.类变量”使用。但是"类.实例变量"是不行的。
* 6.类变量存在于静态域中。
*
* static修饰方法(类方法):
* 1.随着类的加载而加载,在内存中也是独一份
* 2.可以直接通过“类.类方法”的方式调用
* 3.内部可以调用静态的属性或静态的方法,而不能调用非静态的属性或方法。反之,非静态的方法是可以调用静态的属性或静态的方法
* >静态的方法内是不可以有this或super关键字的!
* 注:静态的结构(static的属性、方法、代码块、内部类)的生命周期要早于非静态的结构,同时被回收也要晚于非静态的结构
*/
43,重写equals方法
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
44,import org.junit.Test;
/*
* Junit单元测试类
* 1.当前工程下-右键build path-add libraries-Junit4
* 2.在主类中,创建一个空参的无返回值的方法,(如:public void test1())用于代码的测试,方法上声明:@Test
* 3.导入import org.junit.Test;
* 4.在test1()方法中,进行代码的编写。
* 5.测试:双击方法名,右键run as-junit Test即可。
*/
45,/*
* toString()方法:
* java.lang.Object类的toString()方法的定义如下:
* public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
1.当我们打印一个对象的引用时,实际上默认调用的就是这个对象的toString()方法
2. 当我们打印的对象所在的类没有重写Object中的toString()方法时,那么调用的就是Object中定义的toString()方法,
返回此对象所在的类及对应的堆空间对象实体的首地址值
3.当我们打印的对象所在的类重写了toString()方法时,调用的就是我们自己重写的toString()方法。
常常这样重写:将对象的属性信息返回。
*/
46,//包装类:8种基本数据类型对应着一个类,此类即为包装类。
//基本数据类型 包装类 及String之间的相互转换
//基本数据类型、包装类 --->String类:调用String类的重载的valueOf(Xxx x)方法
Integer i2 = i1;
String str2 = String.valueOf(i2);
String str3 = String.valueOf(true);//"true"
//String类--->基本数据类型、包装类:调用包装类的parseXxx(String str)方法
int i3 = Integer.parseInt(str2);
System.out.println(i3);
boolean b1 = Boolean.parseBoolean(str3);
System.out.println(b1);
//基本数据类型与包装类之间的转化
int i = 10;
//基本数据类型--->对应的包装类:调用包装类的构造器
Integer i1 = new Integer(i);//对于Boolean来讲,当形参是"true"返回true,除此之外返回false。
Boolean b1 = new Boolean("false");
//包装类--->基本数据类型:调用包装类Xxx的XxxValue()方法。
int i2 = i1.intValue();
System.out.println(i2);
//JDK5.0以后,自动装箱和拆箱
int i4 = 12;
Integer i3 = i4;//自动装箱
Boolean bb = false;
int i5 = i3;//自动拆箱
47,/*
* 类的第四个成员:初始化块(或代码块)
* 1.代码块如果有修饰的话,那么只能使用static。
* 2.分类:
* 静态代码块:
* 1.里面可以有输出语句
* 2.随着类的加载而加载,而且只被加载一次
* 3.多个静态代码块之间按照顺序结构执行
* 4.静态代码块的执行要早于非静态代码块的执行。
* 5.静态的代码块中只能执行静态的结构(类属性,类方法)
*
* 非静态代码块:
* 1.可以对类的属性(静态的 & 非静态的)进行初始化操作,同时也可以调用本类声明的方法(静态的 & 非静态的)
* 2.里面可以有输出语句
* 3.一个类中可以有多个非静态的代码块,多个代码块之间按照顺序结构执行
* 4.每创建一个类的对象,非静态代码块就加载一次。
* 5.非静态代码块的执行要早于构造器
*
* 关于属性赋值的操作:①默认的初始化②显式的初始化或代码块初始化(此处两个结构按照顺序执行) ③构造器中;④通过方法对对象的相应属性进行修改
*/
48,//只能创建Singleton的单个实例
class Singleton{
恶汉方式
//1.私有化构造器,使得在类的外部不能够调用此构造器
private Singleton(){
}
//2.在类的内部创建一个类的实例
private static Singleton instance = new Singleton();
//3.私有化此对象,通过公共的方法来调用
//4.此公共的方法,只能通过类来调用,因为设置为static的,同时类的实例也必须为static声明的
public static Singleton getInstance(){
return instance;
}
}
懒汉方式
class Singleton1{
//1.
private Singleton1(){
}
//2.
private static Singleton1 instance = null;
//3.
public static Singleton1 getInstance(){
if(instance == null){
instance = new Singleton1();
}
return instance;
}
}
49,/*
* abstract:抽象的,可以用来修饰类、方法
*
* 1.abstract修饰类:抽象类
* 1)不可被实例化
* 2)抽象类有构造器 (凡是类都有构造器)
* 3)抽象方法所在的类,一定是抽象类。
* 4)抽象类中可以没有抽象方法。
*
* 2.abstract修饰方法:抽象方法
* 1)格式:没有方法体,包括{}.如:public abstract void eat();
* 2)抽象方法只保留方法的功能,而具体的执行,交给继承抽象类的子类,由子类重写此抽象方法。
* 3)若子类继承抽象类,并重写了所有的抽象方法,则此类是一个"实体类",即可以实例化
* 4)若子类继承抽象类,没有重写所有的抽象方法,意味着此类中仍有抽象方法,则此类必须声明为抽象的!
*
*/
//abstract 不能用来修饰属性、构造器、private、final、static
50,/*
* final:最终的 ,可以用来修饰类、属性、方法
*
* 1.final修饰类:这个类就不能被继承。如:String类、StringBuffer类、System类
*
* 2.final修饰方法:不能被重写。如:Object类的getClass()
*
* 3.final修饰属性:此属性就是一个常量,一旦初始化后,不可再被赋值。习惯上,常量用大写字符表示。
* 此常量在哪里赋值:①此常量不能使用默认初始化 ②可以显式的赋值、代码块、构造器。
*
* 变量用static final修饰:全局常量
*
* >与finally finalize()区分开
*
*/
51,/*
* 接口(interface) 是与类并行的一个概念
* 1.接口可以看做是一个特殊的抽象类。是常量与抽象方法的一个集合,不能包含变量、一般的方法。
* 2.接口是没有构造器的。
* 3.接口定义的就是一种功能。此功能可以被类所实现(implements)。
* 比如:class CC extends DD implements AA
* 4.实现接口的类,必须要重写其中的所有的抽象方法,方可实例化。若没有重写所有的抽象方法,则此类仍为一个抽象类
* 5.类可以实现多个接口。----java 中的类的继承是单继承的
* 6.接口与接口之间也是继承的关系,而且可以实现多继承
* >5,6描述的是java中的继承的特点。
*
*/
52,interface AA{
//常量:所有的常量都用public static final修饰
int I = 12;
boolean FLAG = false;
// int i;
//抽象方法:所有的都用public abstract修饰
void method1();
void method2();
}
53,模板设计模式
//模板方法设计模式
public class TestTemplate {
public static void main(String[] args) {
new SubTemplate().spendTime();
}
}
abstract class Template {
public abstract void code();
public void spendTime() {
long start = System.currentTimeMillis();
this.code();
long end = System.currentTimeMillis();
System.out.println("花费的时间为:" + (end - start));
}
}
class SubTemplate extends Template {
public void code() {
boolean flag = false;
for(int i = 2;i <= 10000;i++){
for(int j = 2;j <= Math.sqrt(i);j++){
if(i % j == 0){
flag = true;
break;
}
}
if(!flag){
System.out.println(i);
}
flag = false;
}
}
}
54,/*一、异常的体系结构
* java.lang.Throwable
* |-----Error:错误,程序中不进行处理
* |-----Exception:异常,要求在编写程序时,就要考虑到对这些异常的处理
* |-----编译时异常:在编译期间会出现的异常(执行javac.exe命令时,出现异常)
* |-----运行时异常:在运行期间出现的异常(执行java.exe命令时,出现异常)
*
* 当执行一个程序时,如果出现异常,那么异常之后的代码就不再执行!
*/
//1.数组下标越界的异常:ArrayIndexOutOfBoundsException
//2.算术异常:ArithmeticException
//3.类型转换异常:ClassCastException
//4.空指针异常:NullPointerExcetion
/*
* 二、如何处理Exception的异常
* Java提供的是异常处理的抓抛模型
* 1."抛":当我们执行代码时,一旦出现异常,就会在异常的代码处生成一个对应的异常类型的对象,并
* 将此对象抛出。(自动抛出 / 手动抛出)
* >一旦抛出此异常类的对象,那么程序就终止执行
* >此异常类的对象抛给方法的调用者。
* 2."抓":抓住上一步抛出来的异常类的对象。如何抓?即为异常处理的方式
* java 提供了两种方式用来处理一个异常类的对象。
* 处理的方式一:
* try{
* //可能出现异常的代码
* }catch(Exception1 e1){
* //处理的方式1
* }catch(Exception2 e2){
* //处理的方式2
* }finally{
* //一定要执行的代码
* }
* 注:1.try内声明的变量,类似于局部变量,出了try{}语句,就不能被调用
* 2.finally是可选的。
* 3.catch语句内部是对异常对象的处理:
* >getMessage(); printStackTrace();
* 4.可以有多个catch语句,try中抛出的异常类对象从上往下去匹配catch中的异常类的类型,一旦满足
* 就执行catch中的代码。执行完,就跳出其后的多条catch语句
* 5.如果异常处理了,那么其后的代码继续执行。
* 6.若catch中多个异常类型是"并列"关系,孰上孰下都可以。
* 若catch中多个异常类型是"包含"关系,须将子类放在父类的上面,进行处理。否则报错!
* 7.finally中存放的是一定会被执行的代码,不管try中、catch中是否仍有异常未被处理,以及是否有return语句。
* 8.try-catch是可以嵌套的。
*
* 三、对于运行时异常来说,可以不显式的进行处理。
* 对于编译时异常来说,必须要显式的进行处理。
55, * 类的第5个成员:内部类
* 1.相当于说,我们可以在类的内部再定义类。外面的类:外部类。里面定义的类:内部类
* 2.内部类的分类:成员内部类(声明在类内部且方法外的) vs 局部内部类(声明在类的方法里)
* 3.成员内部类:
* 3.1是外部类的一个成员:①可以有修饰符(4个)②static final ③可以调用外部类的属性、方法
*
* 3.2具体类的特点:①abstract ②还可以在其内部定义属性、方法、构造器
*
* 4.局部内部类:
*
* 5.关于内部类,大家掌握三点:
* ①如何创建成员内部类的对象(如:创建Bird类和Dog类的对象)
* ②如何区分调用外部类、内部类的变量(尤其是变量重名时)
* ③局部内部类的使用 (见TestInnerClass1.java)
*
*/
56,class Person{
String name = "韩梅梅";
int age;
//成员内部类(非static的)
class Bird{
String name = "黄鹂";
int id;
public Bird(){
}
public void setName(String name){
System.out.println(name);//杜鹃
System.out.println(this.name);//黄鹂
System.out.println(Person.this.name);//韩梅梅
}
public void info(){
show();
}
}
//成员内部类(静态内部类)
static class Dog{
}
public void show(){
System.out.println("我是show()方法");
}
public void method1(){
class A{
}
}
}
public class TestInnerClass {
public static void main(String[] args) {
//创建静态内部类的对象:可以直接通过外部类调用静态内部类的构造器
Person.Dog d = new Person.Dog();//Person.new Dog();
//Person.Bird b = new Person.Bird();
//创建非静态的内部类的对象:必须先创建外部类的对象,通过外部类的对象调用内部类的构造器
Person p = new Person();
Person.Bird b = p.new Bird();//new p.Bird();
b.info();
b.setName("杜鹃");
}
}
57,/*
* 关于局部内部类的使用
*/
public class TestInnerClass1 {
}
class OuterClass{
//局部内部类
//如下的使用方式较少
public void method1(){
class InnnerClass{
}
}
//常常使用一个方法,使其返回值为某个类或接口的对象。而这个类或接口在方法内部创建
//使用方式一
public Comparable getComparable(){
//1.创建一个实现Comparable接口的类:局部内部类
class MyComparable implements Comparable{
@Override
public int compareTo(java.lang.Object o) {
return 0;
}
}
//2.返回一个实现类的对象
return new MyComparable();
}
//使用方式二
public Comparable getComparable1(){
//返回一个实现Comparable接口的匿名内部类的对象
return new Comparable(){
@Override
public int compareTo(java.lang.Object o) {
// TODO Auto-generated method stub
return 0;
}
};
}
}
58,//ArrayList:List的主要实现类
/*
* List中相对于Collection,新增加的方法
* void add(int index, Object ele):在指定的索引位置index添加元素ele
boolean addAll(int index, Collection eles)
Object get(int index):获取指定索引的元素
Object remove(int index):删除指定索引位置的元素
Object set(int index, Object ele):设置指定索引位置的元素为ele
int indexOf(Object obj):返回obj在集合中首次出现的位置。没有的话,返回-1
int lastIndexOf(Object obj):返回obj在集合中最后一次出现的位置.没有的话,返回-1
List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex结束的左闭右开一个子list
List常用的方法:增(add(Object obj)) 删(remove) 改(set(int index,Object obj))
查(get(int index)) 插(add(int index, Object ele)) 长度(size())
*/
/*
* 1.存储对象可以考虑:①数组 ②集合
* 2.数组存储对象的特点:Student[] stu = new Student[20]; stu[0] = new Student();....
* >弊端:①一旦创建,其长度不可变。②真实的数组存放的对象的个数是不可知。
* 3.集合
* /*
* Collection接口 :
* |------List接口:
* |------ArrayList(主要的实现类)、
* |------LinkedList(对于频繁的插入、删除操作)、
* |------Vector(古老的实现类、线程安全的,但效率要低于ArrayList)
* |------Set接口:存储无序的,不可重复的元素.Set中常用的方法都是Collection下定义的。
* |------HashSet(主要实现类)
|------LinkedHashSet
|------TreeSet
* Map接口
* |-----HashMap:Map的主要实现类
* |-----LinkedHashMap:使用链表维护添加进Map中的顺序。故遍历Map时,是按添加的顺序遍历的。
* |-----TreeMap:按照添加进Map中的元素的key的指定属性进行排序。要求:key必须是同一个类的对象!
* 针对key:自然排序 vs 定制排序
* |-----Hashtable:古老的实现类,线程安全,不建议使用。
* |----Properties:常用来处理属性文件。键和值都为String类型的
*/
59,package com.atguigu.exer;
/*
* 编写应用程序EcmDef.java,接收命令行的两个参数,要求不能输入负数,计算两数相除。
对数据类型不一致(NumberFormatException)、缺少命令行参数(ArrayIndexOutOfBoundsException、
除0(ArithmeticException)及输入负数(EcDef 自定义的异常)进行异常处理。
提示:
(1)在主类(EcmDef)中定义异常方法(ecm)完成两数相除功能。
(2)在main()方法中使用异常处理语句进行异常处理。
(3)在程序中,自定义对应输入负数的异常类(EcDef)。
(4)运行时接受参数 java EcmDef 20 10
//args[0]=“20” args[1]=“10”
(5)Interger类的static方法parseInt(String s)将s转换成对应的int值。如int a=Interger.parseInt(“314”); //a=314;
*/
public class EcmDef {
public static void main(String[] args) {
try{
int i = Integer.parseInt(args[0]);//被除数
int j = Integer.parseInt(args[1]);//除数
ecm(i,j);
}catch(NumberFormatException e){
System.out.println("输入的数据类型不一致");
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("缺少命令行参数");
}catch(ArithmeticException e){
System.out.println("分母为零了");
}catch(EcDef e){
System.out.println(e.getMessage());
}
}
public static void ecm(int i,int j) throws EcDef{
if(i < 0 || j < 0){
throw new EcDef("您输入的数值存在负数!");
}
System.out.println(i / j);
}
}
//自定义异常类
class EcDef extends Exception{
static final long serialVersionUID = -3387524229948L;
public EcDef(){
}
public EcDef(String msg){
super(msg);
}
}
60,/如何自定义一个异常类
//1.自定义的异常类继承现有的异常类
//2.提供一个序列号,提供几个重载的构造器
public class MyException extends Exception{
static final long serialVersionUID = -70348975766939L;
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
61,/*
* 异常处理的方式二:在方法的声明处,显式的抛出该异常对象的类型
* 格式:如:public static void method2() throws FileNotFoundException,IOException{}
* 当在此方法内部出现异常的时候,会抛出一个异常类的对象,抛给方法的调用者。
* 异常的对象可以逐层向上抛,直至main中。当然在向上抛的过程中,可以再通过try-catch-finally进行处理。
*
* java的异常处理:抓抛模型
* 1.抓:异常的处理,有两种方式(①try-catch-finally② throws + 异常的类型)
* 2.抛:一旦执行过程中,出现异常,会抛出一个异常类的对象。(自动的抛出 vs 手动的抛出(throw + 异常类的对象))
* >异常类,既可以是现成的异常类,也可以是自己创建的异常类
*/
62,/*
* 定义个泛型类 DAO<T>,在其中定义一个Map 成员变量,Map 的键为 String 类型,值为 T 类型。
分别创建以下方法:
public void save(String id,T entity): 保存 T 类型的对象到 Map 成员变量中
T get(String id):从 map 中获取 id 对应的对象
void update(String id,T entity):替换 map 中key为id的内容,改为 entity 对象
List<T> list():返回 map 中存放的所有 T 对象
void delete(String id):删除指定 id 对象
*/
63,//自定义的注解
@Target({TYPE,FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
/*
* 注解
* 1.JDK提供的常用的注解
* @Override: 限定重写父类方法, 该注释只能用于方法
@Deprecated: 用于表示某个程序元素(类, 方法等)已过时
@SuppressWarnings: 抑制编译器警告
2.如何自定义一个注解
3.元注解
*/
64,/*
* 一、枚举类
* 1.如何自定义枚举类
* 2.如何使用enum关键字定义枚举类
* >常用的方法:values() valueOf(String name)
* >如何让枚举类实现接口:可以让不同的枚举类的对象调用被重写的抽象方法,执行的效果不同。(相当于让每个对象重写抽象方法)
*/
//枚举类
enum Season1 implements Info{
SPRING("spring", "春暖花开"){
public void show(){
System.out.println("春天在哪里?");
}
},
SUMMER("summer", "夏日炎炎"){
public void show(){
System.out.println("生如夏花");
}
},
AUTUMN("autumn", "秋高气爽"){
public void show(){
System.out.println("秋天是用来分手的季节");
}
},
WINTER("winter", "白雪皑皑"){
public void show(){
System.out.println("冬天里的一把火");
}
};
private final String seasonName; //1.提供类的属性,声明为private final
private final String seasonDesc;
private Season1(String seasonName,String seasonDesc){//2.声明为final的属性,在构造器中初始化。
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
public String getSeasonName() {//3.通过公共的方法来调用属性
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
@Override
public String toString() {
return "Season [seasonName=" + seasonName + ", seasonDesc="
+ seasonDesc + "]";
}
//4.创建枚举类的对象:将类的对象声明public static final
public static final Season SPRING = new Season("spring", "春暖花开");
public static final Season SUMMER = new Season("summer", "夏日炎炎");
public static final Season AUTUMN = new Season("autumn", "秋高气爽");
public static final Season WINTER = new Season("winter", "白雪皑皑");
//1.values()
Season1[] seasons = Season1.values();
for(int i = 0;i < seasons.length;i++){
System.out.println(seasons[i]);
}
//2.valueOf(String name):要求传入的形参name是枚举类对象的名字。
//否则,报java.lang.IllegalArgumentException异常
String str = "WINTER";
Season1 sea = Season1.valueOf(str);
System.out.println(sea);
65,/*
* java.io.File类
* 1.凡是与输入、输出相关的类、接口等都定义在java.io包下
* 2.File是一个类,可以有构造器创建其对象。此对象对应着一个文件(.txt .avi .doc .ppt .mp3 .jpg)或文件目录
* 3.File类对象是与平台无关的。
* 4.File中的方法,仅涉及到如何创建、删除、重命名等等。只要涉及文件内容的,File是无能为力的,必须由io流来完成。
* 5.File类的对象常作为io流的具体类的构造器的形参。
*/
/*
* createNewFile()
delete()
mkDir():创建一个文件目录。只有在上层文件目录存在的情况下,才能返回true
mkDirs():创建一个文件目录。若上层文件目录不存在,一并创建
list()
listFiles()
*/
/*
* exists()
canWrite()
canRead()
isFile()
isDirectory()
lastModified()
length()
*/
/*
* 路径:
* 绝对路径:包括盘符在内的完整的文件路径
* 相对路径:在当前文件目录下的文件的路径
*
* getName()
getPath()
getAbsoluteFile()
getAbsolutePath()
getParent()
renameTo(File newName)
*/
//renameTo(File newName):重命名
//file1.renameTo(file2):file1重命名为file2.要求:file1文件一定存在,file2一定不存在
66,/*
* 使用FileReader、FileWriter 可以实现文本文件的复制。
* 对于非文本文件(视频文件、音频文件、图片),只能使用字节流!
*/
//1.输入流对应的文件src一定要存在,否则抛异常。
//输出流对应的文件dest可以不存在,执行过程中会自动创建
FileReader fr = null;
FileWriter fw = null;
File src = new File("dbcp.txt");
File dest = new File("dbcp1.txt");
//2.
fr = new FileReader(src);
fw = new FileWriter(dest);
//3.
char[] c = new char[24];
int len;
while((len = fr.read(c)) != -1){
fw.write(c, 0, len);
}
fr.close();
67,/*
* 1.流的分类:
* 按照数据流向的不同:输入流 输出流
* 按照处理数据的单位的不同:字节流 字符流(处理的文本文件)
* 按照角色的不同:节点流(直接作用于文件的) 处理流
*
* 2.IO的体系
* 抽象基类 节点流(文件流) 缓冲流(处理流的一种)
* InputStream FileInputStream BufferedInputStream
* OutputStream FileOutputStream BufferedOutputStream
* Reader FileReader BufferedReader
* Writer FileWriter BufferedWriter
*/
// 1.提供读入、写出的文件
File file1 = new File("C:\Users\shkstart\Desktop\1.jpg");
File file2 = new File("C:\Users\shkstart\Desktop\2.jpg");
// 2.提供相应的流
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(file1);
fos = new FileOutputStream(file2);
// 3.实现文件的复制
byte[] b = new byte[20];
int len;
while ((len = fis.read(b)) != -1) {
// fos.write(b);//错误的写法两种: fos.write(b,0,b.length);
fos.write(b, 0, len);
}
67,//使用缓冲流实现文件的复制的方法
public void copyFile(String src,String dest){
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//1.提供读入、写出的文件
File file1 = new File(src);
File file2 = new File(dest);
//2.想创建相应的节点流:FileInputStream、FileOutputStream
FileInputStream fis = new FileInputStream(file1);
FileOutputStream fos = new FileOutputStream(file2);
//3.将创建的节点流的对象作为形参传递给缓冲流的构造器中
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
//4.具体的实现文件复制的操作
byte[] b = new byte[1024];
int len;
while((len = bis.read(b)) != -1){
bos.write(b, 0, len);
bos.flush();
}
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//5.关闭相应的流
if(bos != null){
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(bis != null){
try {
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//使用BufferedInputStream和BufferedOutputStream实现非文本文件的复制
@Test
public void testBufferedInputOutputStream(){
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//1.提供读入、写出的文件
File file1 = new File("1.jpg");
File file2 = new File("2.jpg");
//2.想创建相应的节点流:FileInputStream、FileOutputStream
FileInputStream fis = new FileInputStream(file1);
FileOutputStream fos = new FileOutputStream(file2);
//3.将创建的节点流的对象作为形参传递给缓冲流的构造器中
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
//4.具体的实现文件复制的操作
byte[] b = new byte[1024];
int len;
while((len = bis.read(b)) != -1){
bos.write(b, 0, len);
bos.flush();
}
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//5.关闭相应的流
if(bos != null){
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(bis != null){
try {
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
68,/*
* 标准的输入输出流:
* 标准的输出流:System.out
* 标准的输入流:System.in
*
* 题目:
* 从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续进行输入操作,
* 直至当输入“e”或者“exit”时,退出程序。
*/
/*
* 如何实现字节流与字符流之间的转换:
* 转换流:InputStreamReader OutputStreamWriter
* 编码:字符串 --->字节数组
* 解码:字节数组--->字符串
*/
//解码
File file = new File("dbcp.txt");
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis, "GBK");
br = new BufferedReader(isr);
//编码
File file1 = new File("dbcp4.txt");
FileOutputStream fos = new FileOutputStream(file1);
OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
bw = new BufferedWriter(osw);
String str;
while((str = br.readLine()) != null){
bw.write(str);
bw.newLine();
bw.flush();
}
69,
/*
* RandomAccessFile:支持随机访问
* 1.既可以充当一个输入流,有可以充当一个输出流
* 2.支持从文件的开头读取、写入
* 3.支持从任意位置的读取、写入(插入)
*/
public void test4(){
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(new File("hello1.txt"),"rw");
raf.seek(4);
byte[] b = new byte[10];
int len;
StringBuffer sb = new StringBuffer();
while((len = raf.read(b)) != -1){
sb.append(new String(b,0,len));
}
raf.seek(4);
raf.write("xy".getBytes());
raf.write(sb.toString().getBytes());
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(raf != null){
try {
raf.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}}
70,/*
* Thread的常用方法:
* 1.start():启动线程并执行相应的run()方法
* 2.run():子线程要执行的代码放入run()方法中
* 3.currentThread():静态的,调取当前的线程
* 4.getName():获取此线程的名字
* 5.setName():设置此线程的名字
* 6.yield():调用此方法的线程释放当前CPU的执行权
* 7.join():在A线程中调用B线程的join()方法,表示:当执行到此方法,A线程停止执行,直至B线程执行完毕,
* A线程再接着join()之后的代码执行
* 8.isAlive():判断当前线程是否还存活
* 9.sleep(long l):显式的让当前线程睡眠l毫秒
* 10.线程通信:wait() notify() notifyAll()
*
* 设置线程的优先级
* getPriority() :返回线程优先值
setPriority(int newPriority) :改变线程的优先级
*/
/*
* 创建一个子线程,完成1-100之间自然数的输出。同样地,主线程执行同样的操作
* 创建多线程的第一种方式:继承java.lang.Thread类
*/
//1.创建一个继承于Thread的子类
class SubThread extends Thread{
//2.重写Thread类的run()方法.方法内实现此子线程要完成的功能
public void run(){
for(int i = 1;i <= 100;i++){
System.out.println(Thread.currentThread().getName() +":" + i);
}
}
}
public class TestThread {
public static void main(String[] args) {
//3.创建子类的对象
SubThread st1 = new SubThread();
SubThread st2 = new SubThread();
//4.调用线程的start():启动此线程;调用相应的run()方法
//一个线程只能够执行一次start()
//不能通过Thread实现类对象的run()去启动一个线程
st1.start();
//st.start();
//st.run();
st2.start();
for(int i = 1;i <= 100;i++){
System.out.println(Thread.currentThread().getName() +":" + i);
}
}
}
71,class PrintNum extends Thread{
public void run(){
//子线程执行的代码
for(int i = 1;i <= 100;i++){
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
public PrintNum(String name){
super(name);
}
}
/*
* 创建多线程的方式二:通过实现的方式
*
* 对比一下继承的方式 vs 实现的方式
* 1.联系:public class Thread implements Runnable
* 2.哪个方式好?实现的方式优于继承的方式
* why? ① 避免了java单继承的局限性
* ② 如果多个线程要操作同一份资源(或数据),更适合使用实现的方式
*/
72,//线程通信。如下的三个关键字使用的话,都得在同步代码块或同步方法中。
//wait():一旦一个线程执行到wait(),就释放当前的锁。
//notify()/notifyAll():唤醒wait的一个或所有的线程
//使用两个线程打印 1-100. 线程1, 线程2 交替打印
//死锁的问题:处理线程同步时容易出现。
//不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁
//写代码时,要避免死锁!
//关于懒汉式的线程安全问题:使用同步机制
//对于一般的方法内,使用同步代码块,可以考虑使用this。
//对于静态方法而言,使用当前类本身充当锁。
73,常用类
/*
* 与时间相关的类:
* 1.System 类下的currentTimeMillis();
* 2.Date类:java.util.Date
* 如何创建其实例;其下的方法:toString()、getTime()
* (以及其子类java.sql.Date)
* 3.SimpleDateFormat类
* 4.Calendar类
*/
/*
* 1.字符串 与基本数据类型、包装类之间转换
* ①字符串 --->基本数据类型、包装类:调用相应的包装类的parseXxx(String str);
* ①基本数据类型、包装类--->字符串:调用字符串的重载的valueOf()方法
*
* 2.字符串与字节数组间的转换
* ①字符串---->字节数组:调用字符串的getBytes()
* ②字节数组---->字符串:调用字符串的构造器
*
* 3.字符串与字符数组间的转换
* ①字符串---->字符数组:调用字符串的toCharArray();
* ②字符数组---->字符串:调用字符串的构造器
*/
/*
* java.lang.StringBuffer:可变的字符序列
* java.lang.StringBuilder:可变的字符序列,是jdk5.0新加入的,线程不安全,效率要高于StringBuffer.
* 对比String,StringBuffer,StringBuilder三者在添加上的效率:
* 效率从高到底: StringBuilde > StringBuffer > String
*/
public class TestBigDecimal {
@Test
public void testBigInteger() {
BigInteger bi = new BigInteger("12433241123");
BigDecimal bd = new BigDecimal("12435.351");
BigDecimal bd2 = new BigDecimal("11");
System.out.println(bi);
// System.out.println(bd.divide(bd2));
System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP));
System.out.println(bd.divide(bd2, 15, BigDecimal.ROUND_HALF_UP));
}
}
74,package com.atguigu.exer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/*
* 1.模拟一个trim方法,去除字符串两端的空格。
2.将一个字符串进行反转。将字符串中指定部分进行反转。比如将“abcdefg”反转为”abfedcg”
3.获取一个字符串在另一个字符串中出现的次数。
比如:获取“ab”在 “abkkcadkabkebfkabkskab”
中出现的次数
4.获取两个字符串中最大相同子串。比如:
str1 = "abcwerthelloyuiodef";str2 = "cvhellobnm"
5.对字符串中字符进行自然顺序排序。
练习:I am a student! 写一个方法:实现输出 !student a am I
*/
public class StringDemo {
public static void main(String[] args) {
String str = " abc de ";
//str = " ";
String str1 = myTrim(str);
System.out.println(str1);
String str2 = "abcdefg";
String str3 = reverseString(str2,2,5);
String str4 = reverseString1(str2,2,5);
System.out.println(str3);//abfedcg
System.out.println(str4);
int i = getTime("abkkcadkabkebfkabkskab","abk");
System.out.println(i);
List<String> strs5 = getMaxSubString("abcwerthelloyuiodef","abcwecvhellobnm");
System.out.println(strs5);
String str6 = "aediewfn";
String str7 = sort(str6);
System.out.println(str7);
}
//5.对字符串中字符进行自然顺序排序。
public static String sort(String str){
char[] c = str.toCharArray();
Arrays.sort(c);
return new String(c);
}
//4.获取两个字符串中最大相同子串。
public static List<String> getMaxSubString(String str1,String str2){
String maxStr = (str1.length() > str2.length())? str1 : str2;
String minStr = (str1.length() < str2.length())? str1 : str2;
int len = minStr.length();
List<String> list = new ArrayList<>();
for(int i = 0;i < len;i++){
for(int x = 0,y = len - i;y <= len;x++,y++){
String str = minStr.substring(x, y);
if(maxStr.contains(str)){
list.add(str);
}
}
if(list.size() != 0){
return list;
}
}
return null;
}
//3.获取一个字符串在另一个字符串中出现的次数。判断str2在str1中出现的次数
public static int getTime(String str1,String str2){
int count = 0;
int len;
while((len = str1.indexOf(str2)) != -1){
count++;
str1 = str1.substring(len + str2.length());
}
return count;
}
//将一个字符串进行反转。将字符串中指定部分进行反转。(法二) 在考虑使用StringBuffer将此算法优化!
public static String reverseString1(String str,int start,int end){
String str1 = str.substring(0, start);
for(int i = end;i >= start;i--){
char c = str.charAt(i);
str1 += c;
}
str1 += str.substring(end + 1);
return str1;
}
//2.将一个字符串进行反转。将字符串中指定部分进行反转。比如将“abcdefg”反转为”abfedcg”
public static String reverseString(String str,int start,int end){
char[] c = str.toCharArray();//字符串--->字符数组
return reverseArray(c,start,end);
}
public static String reverseArray(char[] c,int start,int end){
for(int i = start,j = end;i < j;i++,j--){
char temp = c[i];
c[i] = c[j];
c[j] = temp;
}
//字符数组--->字符串
return new String(c);
}
//1.模拟一个trim方法,去除字符串两端的空格。
public static String myTrim(String str){
int start = 0;
int end = str.length() - 1;
while(start < end && str.charAt(start) == ' '){
start++;
}
while(start < end && str.charAt(end) == ' '){
end--;
}
return str.substring(start, end + 1);
}
}
75,反射机制
//调用指定的方法
@Test
public void test4() throws Exception{
Class clazz = Class.forName("com.atguigu.review.Animal");
Object obj = clazz.newInstance();
Animal a = (Animal)obj;
//调用非public的方法
Method m1 = clazz.getDeclaredMethod("getAge");
m1.setAccessible(true);
int age = (Integer)m1.invoke(a);
System.out.println(age);
//调用public的方法
Method m2 = clazz.getMethod("show", String.class);
Object returnVal = m2.invoke(a,"金毛");
System.out.println(returnVal);
//调用static的方法
Method m3 = clazz.getDeclaredMethod("info");
m3.setAccessible(true);
// m3.invoke(Animal.class);
m3.invoke(null);
}
//调用指定属性
@Test
public void test3() throws Exception{
Class clazz = Class.forName("com.atguigu.review.Animal");
Object obj = clazz.newInstance();
Animal a = (Animal)obj;
//调用非public的属性
Field f1 = clazz.getDeclaredField("name");
f1.setAccessible(true);
f1.set(a, "Jerry");
//调用public的属性
Field f2 = clazz.getField("age");
f2.set(a, 9);
System.out.println(f2.get(a));
System.out.println(a);
//调用static的属性
Field f3 = clazz.getDeclaredField("desc");
System.out.println(f3.get(null));
}
//调用指定的构造器创建运行时类的对象
@Test
public void test2() throws Exception{
Class clazz = Animal.class;
Constructor cons = clazz.getDeclaredConstructor(String.class,int.class);
cons.setAccessible(true);
Animal a = (Animal)cons.newInstance("Tom",10);
System.out.println(a);
}
//获取运行时类的对象:方法一
@Test
public void test1() throws Exception{
Class clazz = Class.forName("com.atguigu.review.Animal");
Object obj = clazz.newInstance();
Animal a = (Animal)obj;
System.out.println(a);
}
76,网络编程
/*
* 网络通信的第一个要素:IP地址。通过IP地址,唯一的定位互联网上一台主机
* InetAddress:位于java.net包下
* 1.InetAddress用来代表IP地址。一个InetAdress的对象就代表着一个IP地址
* 2.如何创建InetAddress的对象:getByName(String host)
* 3.getHostName(): 获取IP地址对应的域名
* getHostAddress():获取IP地址
*/
public class TestInetAddress {
public static void main(String[] args) throws Exception {
//创建一个InetAddress对象:getByName()
InetAddress inet = InetAddress.getByName("www.atguigu.com");
//inet = InetAddress.getByName("42.121.6.2");
System.out.println(inet);
//两个方法
System.out.println(inet.getHostName());
System.out.println(inet.getHostAddress());
//获取本机的IP:getLocalHost()
InetAddress inet1 = InetAddress.getLocalHost();
System.out.println(inet1);
System.out.println(inet1.getHostName());
System.out.println(inet1.getHostAddress());
}
}
//TCP
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import org.junit.Test;
//客户端给服务端发送文本,服务端会将文本转成大写在返回给客户端。
//如下程序为了保证相应的流及socket的关闭(即使在关闭之前出现异常,也一定要保证相应的资源的关闭),要求是用
//try-catch-finally进行操作。要求将关闭的信息写在finally里!
public void client() {
// 1.
Socket socket = null;
// 2.
OutputStream os = null;
Scanner scanner = null;
// 4.接收来自于服务端的数据
InputStream is = null;
try {
socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
os = socket.getOutputStream();
// 3.向服务端发送数据
// os.write("abc".getBytes());
System.out.println("请输入多个字符:");
scanner = new Scanner(System.in);
String str = scanner.next();
os.write(str.getBytes());
socket.shutdownOutput();
is = socket.getInputStream();
byte[] b = new byte[10];
int len;
while ((len = is.read(b)) != -1) {
String str1 = new String(b, 0, len);
System.out.print(str1);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 5.
if(is != null){
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(scanner != null){
scanner.close();
}
if(os != null){
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
@Test
public void server() {
// 1.
ServerSocket ss = null;
// 2.
Socket s = null;
// 3.接收来自于客户端的信息
InputStream is = null;
// 4.返回给客户端
OutputStream os = null;
try {
ss = new ServerSocket(9090);
s = ss.accept();
is = s.getInputStream();
byte[] b = new byte[10];
int len;
String str = new String();
while ((len = is.read(b)) != -1) {
String str1 = new String(b, 0, len);
str += str1;
}
String strUpperCase = str.toUpperCase();
os = s.getOutputStream();
os.write(strUpperCase.getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(os != null){
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(is != null){
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(s != null){
try {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(ss != null){
try {
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// 5.
}
}
//UDP编程的实现
public class TestUDP {
// 发送端
@Test
public void send() {
DatagramSocket ds = null;
try {
ds = new DatagramSocket();
byte[] b = "你好,我是要发送的数据".getBytes();
//创建一个数据报:每一个数据报不能大于64k,都记录着数据信息,发送端的IP、端口号,以及要发送到
//的接收端的IP、端口号。
DatagramPacket pack = new DatagramPacket(b, 0, b.length,
InetAddress.getByName("127.0.0.1"), 9090);
ds.send(pack);
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(ds != null){
ds.close();
}
}
}
// 接收端
@Test
public void rceive() {
DatagramSocket ds = null;
try {
ds = new DatagramSocket(9090);
byte[] b = new byte[1024];
DatagramPacket pack = new DatagramPacket(b, 0, b.length);
ds.receive(pack);
String str = new String(pack.getData(), 0, pack.getLength());
System.out.println(str);
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(ds != null){
ds.close();
}
}
}
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
//URL:统一资源定位符,一个URL的对象,对应着互联网上一个资源。
//我们可以通过URL的对象调用其相应的方法,将此资源读取(“下载”)
public class TestURL {
public static void main(String[] args) throws Exception {
//1.创建一个URL的对象
URL url = new URL("http://127.0.0.1:8080/examples/HelloWorld.txt?a=b");//File file = new File("文件的路径");
/*
* public String getProtocol( ) 获取该URL的协议名
public String getHost( ) 获取该URL的主机名
public String getPort( ) 获取该URL的端口号
public String getPath( ) 获取该URL的文件路径
public String getFile( ) 获取该URL的文件名
public String getRef( ) 获取该URL在文件中的相对位置
public String getQuery( ) 获取该URL的查询名
*/
// System.out.println(url.getProtocol());
// System.out.println(url.getHost());
// System.out.println(url.getPort());
// System.out.println(url.getFile());
// System.out.println(url.getRef());
// System.out.println(url.getQuery());
//如何将服务端的资源读取进来:openStream()
InputStream is = url.openStream();
byte[] b = new byte[20];
int len;
while((len = is.read(b)) != -1){
String str = new String(b,0,len);
System.out.print(str);
}
is.close();
//如果既有数据的输入,又有数据的输出,则考虑使用URLConnection
URLConnection urlConn = url.openConnection();
InputStream is1 = urlConn.getInputStream();
FileOutputStream fos = new FileOutputStream(new File("abc.txt"));
byte[] b1 = new byte[20];
int len1;
while((len1 = is1.read(b1)) != -1){
fos.write(b1, 0, len1);
}
fos.close();
is1.close();
}
}
77,
String为引用类型,如果对象为null,也就是说这个对象都不存在了,
再去调用对象的相关方法,肯定会报空指针异常。这里调用了String类的length()方法
&&和||具有短路的效果,在进行&&时,如果&&前的是false,
那么&&后的不再执行,直接返回false,同理||也一样。