德昊德浩
DOS 磁盘操作系统
windows 图形化界面GUI
命令行方式 CLI
JVM java虚拟机-在操作系统上解析emmm
/*
Asdsad
Asdasd
*/
多行注释
/**
文档注释
asdsa
*/
Javadoc.exe 生成说明书-放在网页文件中
Set path =asdasda;%path%(增加path,保留原来)
Set classpath= asdawsad; //分号-----在指定目录下找完,在当前目录再找一遍
DAY 2
Demo1_Test
Demo2_Eate
注释!
Byte-8位、1字节-8位
进制转换
八进制—二进制的三位是八进制的一位
十六.。。。。。四位 0xAE----10 14–10101110
负数的二进制–正数取反加1
0000 0110
取反1111 1001
+0000 0001
1111 1010------ -6
负数的二进制的最高位是1
Byte short int long
1 2 4 8
BYTE的范围
-2(7)-----2(7)-1
Float 4
Double 8默认
Char 2
强制类型转换
Byte b=3;
B=(byte)(b+4);
0000-0000 0000-0000 0000-0000 0000-0111
前三位扔了
0000-0111
ASC表
A-65
A-97
Byte b1=3; 3整数,4个字节,而BYTE一个字节
Byte b2=7;
Byte b;
B=b1+b2;
WRONG!
因为后面是两个不确定的变量,如果超了
-128^127 就gg
3+“2” 32 字符串+是连接
DAY3
^ 异或 相同为0不同为1
&& 短路,左面假右面就不运算,效率高
和与运算结果一样。
& 无论左面是啥,右面都参与运算
|| 短路 左面为真,右面不运算
位运算
6&3-------=2
110
& 011
010
异或同一个数据两次,结果还是一样
加密
移位
3<<2=12 3<<3=24 (11000)
32(2)=12 32(3)=24
0000000000000000000000000000-0011
0000000000000000000000000000-1100
左移就是乘以2的次幂运算
6>>1=3
0110-------0011
(最高位是啥就那啥补,负数就拿1补)
右移就是除以2的次幂
无符号右移:数据进行右移时,高位出现的空位,
无论原高位是什么,空位都用0补
class OperateTest//输出2乘8的最有效率的方法–位运算
{
public static void main(String []args)
{
System.out.println(2<<3);
}
}
class Change//第三方变量chang
{
public static void main(String []args)
{
int a =3,b=4;
int c;
c=a;
a=b;
b=c;
System.out.println("a="+a+",b="+b);
}
}
class Chang2//不用第三方变量
a=a+b;
b=a-b;
a=a-b;
//这种方式不用,数值过大超出int范围,强制转化
class Chang3//位运算方法
{
public static void main(String []args)
{
int a =3,b=5;
a=a^b; //a=3^5
b=a^b; //b=(35)5;b=3
a=a^b; //a=(35)3;a=5
System.out.println(“a=”+a+",b="+b);
}
}
三元运算符
class OperateDemo5//
{
public static void main(String []args)
{
intx=3,y;
y=(x>1)?100:200;
System.out.println(y);
}
}
三元运算符就是if else 语句的简写格式
当if else 运算后有个具体的结果时可以用简化
Int a ,b;
Int max = (a>b)?a:b;//获取两个整数中最大的
Int a,b,c;//获取三个数中最大的
Int temp=O>p?o:p;
Int max2=temp>q?temp:q;
如果if语句中只有一条语句可以不写{}
但只能控制哦这一条语句
class OperateDemo8//
{
public static void main(String []args)
{
int x=3;
switch(x)
{
case 4:
System.out.println(“a”);
break;
case 1:
System.out.println(“b”);
break;
case 3:
System.out.println(“c”);
break;
default:
System.out.println(“d”);
break;
}
}
}
Switch 只有四种类型能用
Byte short int char
如果遇到没有break的条,直接执行知道遇到break或者{}终止
遇到一样的,避免复杂
For里的变量在循环结束就释放------y
So
如果需要通过变量来对循环进行 控制
改变量只作为循环增量,用while
(下面还能再用这个变量)
内存的问题emmmmm
//乘法表
public static void printCFB(int num)
{
for(int x=1;x<=num;x++)
{
for(int y=1;y<=x;y++)
System.out.print(y+""+x+"="+yx);
}
System.out.println();
}
//重载 个数问题一般可以复用
public static void printCFB()
{
printCFB(9);
}
内存的划分
\n :回车
\t: 制表符(tab)
\b:退格
\r:按下回车键
windows中回车符由两个符号组成\r\n
linux中回车符是\n
Break 用于swtich 和循环
Continue 用于循环
错误!!!!!!
直接继续循环,输出语句无法执行
用法!!!!!!!!!!!!!
Continue 结束本次循环,继续下次循环
Continue 和if配合emmm、
函数名 第一个单词首字母小写,以后都大写首字母
Public static void myPrint()
{
System.out.println(“hello”);
}
Public static void main(String [] args)
{
myPrint();
}
不用return
函数的结果应该给调用者处理
返回值类型和参数类型无关
栈 先进后出
重载----同一个类,允许存在一个以上的同名函数
只要他们的参数个数或者参数类型 不同
/*函数的重载
1.同一个类
2.同名
3.参数个数不同or参数类型不同
*/
//加法运算 两个整数
public static int add(int a ,int b)
{
return a+b;
}
//两个 小数
public static double add(double a ,double b)
{
return a+b;
}
//三个整数
public static int add(int a ,int b,int c)
{
return a+b+c;
}
数组的遍历
/*
数组有个语句可以看长度arr.length
class ArrayDemo3
{
public static void main(String [] args)
{
int[] arr=new int[]{89,35,270,17};
//int [] arr={89,35,270,17};
For(int x =0; x
System.out.println(“arr[“+x+”]=”+arr[x]+”;”);
}
}
}
获取最值,数组
选择排序
class ArrayDemo4
{
public static void main(String []args)
{
int [] arr={34,19,11,109,3,56};
for(int x=0;x
System.out.println(arr[x])
}
}
public static void xuanZe(int[]arr)
{
for(int x=0;x
for(int y=x+1;y
if(arr[x]>arr[y])
{
int temp=arr[x];
arr[x]=arr[y];
arr[y]=temp;
}
}
}
}
}
冒泡排序
相邻的比较,大的往上冒
//冒泡排序
for(int x=0;x
for(int y=0;y
if(arr[y]>arr[y+1])
{
int temp=arr[y];
arr[y]=arr[y+1];
arr[y+1]=temp;
}
}
}
//或者
for(int x=arr.length-1;x>0;x–)
{
for(int y=0;y
if(arr[y]>arr[y+1])
{
Swap(arr,y,y+1);//看下面的函数
}
}
}
Public static void swap(int [] arr,int a,int b)
{
Int temp =arr[a];
Arr[a]=arr[b];
Arr[b]=temp;
}
二分查找————————有序的数据//
class ArrayDemo5
{
public static void main(String []args)
{
System.out.println("index="+index);
}
public static int halfSearch(int key,int[] arr)
{
Int max,min,mid;
Min=0;
Max=arr.length-1;
While (min<=max)
{
Mid=(max+min)/2;
If(key>arr[mid])
Min=mid+1;
Else If(key
Else
Return mid;
}
Return -1;/给定一个有序的数组,王数组中存个元素,保证还是有序的
Return min;/
}
Int index1=Arrays.binarySearch(arr,5);
//如果存在返回具体位置 不存在的话,返回的是-插入点-1
获取一个整数的16进制表现形式
0000-0000 0000-0000 0000-0000 0011-1100–>60
& 0000-0000 0000-0000 0000-0000 0000-1111–>15
0000-0000 0000-0000 0000-0000 0000-1100–>12
取末位值,4位二进制是一个16进制位
然后60>>>4再&15----->3
–>3c
查表法------数组—映射关系,两组对照
有对应关系,一组有序
//定义一个容器临时放数据 转换16进制
public static void toHex(int num)
{
if(num==0)
{
System.out.println(“0”);
return;
}
char[]chs={“0”,“1”,“2”,“3”,“4”,“5”,“6”,“7”,“8”,“9”,“A”,“B”,“C”,“D”,“E”,“F”};//定义一个对应关系表
char []arr= new char[8];
int pos =arr.length;
while(num!=0)
{
int temp=num&15;
arr[–pos]=chs[temp]
num =num>>>4;
}
for(int x=pos;x
//定义一个容器临时放数据 转换进制
class ArrayTest3
{
public static void main(String[]args)
{
toHex(26);
toBinary(26);
toOctal(26);
}
//十进制--------》十六进制
public static void toHex(int num)
{
trans(num,15,4);
}
//十进制--------》2进制
public static void toBinary(int num)
{
trans(num,1,1);
}
//十进制--------》八进制
public static void toOctal(int num)
{
trans(num,7,3);
}
public static void trans(int num,int base,int offset)
{
if(num==0)
{
System.out.println(“0”);
return;
}
char[]chs={“0”,“1”,“2”,“3”,“4”,“5”,“6”,“7”,“8”,“9”,“A”,“B”,“C”,“D”,“E”,“F”};//定义一个对应关系表
char []arr= new char[32];
int pos =arr.length;
while(num!=0)
{
int temp=num&base;
arr[–pos]=chs[temp]
num =num>>>offset;
}
for(int x=pos;x
}
/*
二维数组的格式
Int [] arr=new int[3];一维数组
Int[][] arr=new int[3][2]; 2wei
System.out.println(arr[0][0]);
*/
int [][]arr=new int [3][];
分别对二维数组每一个小数组初始化
arr[0]=new int[2];
arr[1]=new int[1];
arr[2]=new int[3];
System.out.println(arr[1].length);打印二维数组中角标为1的数组的长度
Int[][] arr= { {3,1,7},{5,4,4,5},{3,1}};
For(int x=0;x
For(int y=0;y
System.out.println(arr[x][y]+”,”);
}
}
面向过程------强调动作(函数)
面向对象。
强调的是对象。(实体)。
三个特征:封装 继承 多态
Class::描述 事物的 属性 行为
对象 是该类事物存在的个体(实例)
通过new创建
//在计算机中创建一个car的实例。通过new关键字
Car c =new Car (); /c是一个类类型的引用变量
指向了该类的对象/
c.run();//使用对象中的内容 对象.成员
c.num =4;
c.color=”red”;
定义类就是定义类中的成员
成员:成员变量—》属性,成员函数----》行为
class Car
{
int num;
String color;
void run()
{
System.out.println(num+”…”+color);
}
}
new------在堆内存 默认初始化值
栈。方法存地址指向堆
对象----封装数据
成员变量和局部变量的区别
1成员变量定义在类中,整个类都可以访问
局部变量定义在函数,语句,局部代码块中,只在所属的区域有效
2
成员变量存在于堆内存的对象中
局部变量存在于栈内存的方法中
3,
成员变量随着对象的创建而存在,随着对象的消失而消失
局部所属区域
4成员变量you默认初始化值
局部没有默认初始化值
public static void show(Car c)//类类型变量指向对象
{
c.num=4;
c.color=”black”
System.out…
}
show(c1);
匿名对象 :new car(); 定义对象的简写格式然而好像没啥用
正常:Car c=new Car();
c.run();
new Car() .run();
1当对象对方法仅进行一次调用的时候可以简化成匿名对象
注意只是对方法
2匿名对象可以作为实际参数进行传递
class Demo
{
public static void main(String []args)
{
int x=3;
show(x);
System.out.println(x);
}
public static void show (int x)
{
x=4;
}
}
结果为3
封装:隐藏对象的实现细节和属性 仅对外提供公共访问方式
安全,可控性—提供方法不直接访问成员
private私有只在本类中有效,用于修饰成员
注意:私有仅仅是封装的一种体现
class Person
{
private int age;//成员变量弄成私有的
public void setAge(int a)//一个成员变量对应俩方法 规范
{
age =a;
}
public int getAge()
{
return age;
}
void speak()
{
System.out.println(“age=”+age);
}
}
封装原则
将不需要对外提供内容隐藏
把属性都隐藏,提供公共方法对其访问
构造函数:函数名与类名相同
不用定义返回值类型
没有具体的返回值
作用:
给对象进行初始化,创建对象就要用构造函数初始化
注意:
class Person
{
private String name;
private int age;
//定义一个构造函数
Person ()
{
System.out.println(“person run”)
}
public void speak()
{
Stystem.out.println(name+":"+age)
}
}
class ConsDemo
{
public static void main(String []args)
{
Person p = new Person();
}
}
结果是 person run
什么时候定义构造函数?
在描述对象时该对象就已经具备了一些内容,这些内容
都定义在构造函数里
class Person
{
private String name;
private int age;
}
Person()
{
name =”baby”
age =1;
}
Person (String n)
{
name =n;
}
Person(String n ,int a)
{
name =n;
age =a;
}
public void speak()
{
System.out.println(name+”:”+age);
}
public void setName(String n)// 封装
{
name=n;
}
class Demo3
{
Person p=new Person();
p.speak();
Person p1=new Person(“WANG”);//难听老子要改名字
p1.setName(”王蕊”);
p1.speak();
Person p2=new Person(“WANGG”,13);
p2.speak();}
this关键字:党成员变量和局部变量重名,用
this来区分--------this:代表对象。
this就是所在函数所属的对象的引用
(那个对象调用了this所在的函数,this就代表那个对象)
Person(String name)
{
this.name =name;
}
Person(String name,int age)
{
this(name);//调用上面的构造函数,用这样的
//this可以用于在构造函数中调用其他的构造函数
注意:只能定义在构造函数的第一行!!!!!!!
因为初始化动作要先执行
(构造)
this.age=age;
}
public boolean compare(Person p)
{
/*
if(this.agep.age)//谁调用this就是谁
return true;
else
return false;
*/
return this.agep.age;
}
static 关键字静态
1.static是一个修饰符,用于修饰成员
2.static修饰的成员被所有的对象所共享
3.static优先于对象存在,因为static的成员随着类的加载就存在了
4.也可以被类访问,------- 类名。静态成员
5.static是共享数据,对象中存储的是特有数据
class Person
{
String name;//成员变量,实例变量
static String country=”CN”;//静态变量,类变量
public void show
{
System.out.println(country+”:”=name);
}
}
class StaticDemo
{
public static void main(String []args)
{
Person p=new Person();
p.name=”HH”;
p.show();
System.out.println(p.country);
System.out.println(Person.country);
}
}
成员变量和静态变量的区别
一.两个变量的生命周期不同,静态的弊端,占地方
1.成员变量随着对象的创建而存在,随着对象的回收而释放
2.静态变量随着类的加载而存在,随着类的消失而消失
二.调用方式不同
成员变量只能被对象调用
静态变量可以被对象调用,还可以被类名调用,建议用类名
三,数据的存储位置不同
成员变量存储在对内存的对象中,也叫对象的特有数据
静态变量的数据存储在方法区 (共享数据区)的静态区,所以也叫对象的共享数据
静态使用的注意事项!!!!!!
1.静态方法只能访问静态成员!!!
2.静态方法中不可以使用this或者super关键字(静态在对象之前)(没有对象咧!)
3.主函数是静态的
class StaticDemo
{
int num=4;
new StaticDemo().show();//因为主函数是静态的,不能直接调用非静态方法和成员,用对象调用
}
public void show()
{
System.out.println(num);
}
主函数:
public:是因为权限必须是最大的
static:不需要对象的 ,直接用主函数所属类名调用
void:主函数没有具体的返回值
main:函数名,不是关键字,是一个jvm是别的固定的名字
String【】args:这是主函数的参数列表,是一个数组类型的参数,而且元素都是字符串类型
//new String[0]
静态区没有this
什么时候用静态?
1.静态变量static int num = 9;
当分析对象中所具备的成员变量的值都是相同的,可以用静态修饰,以后也不要改的那种值,不能改哦!
只要数据在对象中都是不同的,那么就是对象的特有数据,必须存在对象中,是非静态的
如果是相同的数据,对象不需要修改,只需要使用,不需要存储在对象中,定义成静态的
2.静态函数
是否用静态------该函数功能是否访问到对象中的特有数据
简单说,该功能是否需要访问非静态的成员变量
如果要,改功能救是非静态的,
不需要,就可以将功能定义成静态的 /也可以定义成非静态
但是非静态需要被对象调用,而仅为了创建对象调用非静态的
没有访问对象的特有数据的方法,该对象的创建没有意义)/
3.静态代码块-----代码块(独立的代码区间{})
随着类的加载而执行!!!而且只执行一次
作用:
用于给类进行初始化。(用不到特有数据)
一般来说类里都是静态成员用静态代码块(不用对象)
class StaticCode
{
static int num;
static
{
num=10;
System.out.println(“hahahhaha”)
}
void show()
{
System.out.println(num);
}
}
class StaticCodeDemo
{
public static void main(String[] args)
{
new StaticCodeDemo().show;
}
}
面试。
class Person
{
private String name;
{//构造代码块,,,可以给所有对象初始化
System.out.println(“person run”);
}
Person ()//是给对应的对象进行针对性的初始化
{
name = “xxx”;
}
Person(String name)
{
this.name=name;
}
public void speak()
{
System.out.println(“name:”+name);
}
}
一个非静态方法都没有的类—工具类
没有特有成员,不要创建对象直接用类名调用
该类的方法都是静态的,所以该类不需要创建对象
为了保证不让其他程序创建该类对象,可以将该类的构造函数私有化
class ArrayTool
{
private ArryaTool(){}//私有化构造函数
/** 文档注释!
@param arr (参数的意思)接受一个元素为int类型的数组
@return (返回值的意思)该数组的最大元素值
*/
pubic static int getMax(int [] arr)
{
int maxIndex = 0;
for (int x=1;x
if (arr[x]>arr[maxIndex])
maxIndex=x;
}
return arr[maxIndex];
}
}
文档注释:
/**
建立一个用于操作数组的工具类,其中包含常见的对数组操作的函数如:最值,排序等
@ author 张三 (作者)
@version V1.0 (版本)
*/
public class 文件名和类名必须一致当public时
文档注释提供的公有的,私有的不提供
设计模式:对问题行之有效的解决方式
是一种思想
1.单例设计模式
解决的问题:可以保证一个类在内存中的对象唯一性
比如对于多个程序使用同一个配置信息对象时,就要保证该对象的唯一性
如何保证对象的唯一性?
1.不允许其他程序用new创建该类对象
2.在该类中创建个本类实例
3.对外提供一个方法,让其他程序可以获取该对象
步骤
1.私有化该类的构造函数
2.通过new在本类中创建一个本类对象
3.定义一个共有的方法,将创建的对象返回
class Single
{
private static Single s= new Single;//成员变量,私有可控
private Single(){}
public static Single getInstance()
{
return s;
}
}
class SingleDemo
{
public static void main(String [] args)
{
Single s1 =Single.getInstance();
Single s2 =Single.getInstance();
System.out.println(s1==s2);
Test t1=new Test();
Test t2=new Test();
t1.setNum(10);
t2.setNum(20);
System.out.println(t1.getNum());
System.out.println(t2.getNum());
}
}
class Test
{
private int num;
private Test(){};
private static Test t=new Test();
public static Single getInstance()
{
return s;
}
public void setNum(int num)
{
this.num=num;
}
public int getNum()
{
return num;
}
}
成员变量–私有-可控
例子
//懒汉式 多线程访问可能不能保证唯一性
class Singel2//类加载进来没有对象,调用getInstance方法时,创建对象。
{ //延迟加载模式,面试
private static Single2 s= null;
Private Single2(){}
public static Single2 getInstance()
{
if(snull)
s=new Single2();
return s;
}
}
Class Single3
{
private static Single3 s=null;
private Single3(){}
public static Single getInstance()
{
if(snull)//提高效率,减少同步代码块的执行
synchronized(Single.class)
{
if(s==null)//延迟加载
s=new Single();
}
}
return s;
}
}
//饿汉试—开发常用
class Singel//类一加载,对象就已经存在
{
private static Single s= new Single;
Private Single(){}
public static Single getInstance()
{
return s;
}
}
继承的好处
1.提高代码的复用性
2.让类与类产生关系
3.给多态产生前提
java中支持单继承,不直接支持多继承,但对c++中的多继承机制进行改良
单继承:一个子类只能有一个直接父类
多继承:一个子类可以有多个直接父类(java中不允许,进行改良)
不直接支持,因为多个父类中有相同成员,是因为会产生调用的不确定性
是通过多实现的方式体现。
java支持多层(多重)继承。
C继承B,B继承A。
就会出现继承体系。
当要使用一个继承体系时,
1,查看该体系中的顶层类,了解该体系的基本功能。
2,创建体系中的最子类对象,完成功能的使用
class Person
{
String name;
int age;
}
class Sdudent extends Person//继承
{
//String name;
//int age;
void study()
{
System.out.println(“student work”);
}
}
class Worker extends Person
{
//String name;
//int age;
void work()
{
System.out.println(“worker work”);
}
}
class ExtendsDemo
{
Student s =new Student();
s.name=”wang”
s.age=20;
s.study();
}
什么时候定义继承呢?
当类与类之间存在着所属关系的时候,就定义继承。xxx是yyy中的一种。 xxx extends yyy
在子父类中,成员的特点体现。
1,成员变量。
2,成员函数。
3,构造函数。
/*
当本类的成员和局部变量同名用this区分。
当子父类中的成员变量同名用super区分父类。
super–父类
this和super的用法很相似。
this:代表一个本类对象的引用。
super:代表一个父类空间。
*/
class Fu
{
private int num = 4;
public int getNum()
{
return num;
}
}
class Zi extends Fu
{
private int num = 5;
void show()
{
System.out.println(this.num+"....."+super.getNum());
}
}
(私有的继承不了哦哦哦哦哦哦哦哦哦哦)
子类不能直接访问父类中私有的内容
所以要间接访问,getNum
/成员函数。
/*
当子父类中出现成员函数一模一样的情况,会运行子类的函数。
这种现象,称为覆盖操作。这时函数在子父类中的特性。
函数两个特性:
1,重载。同一个类中。overload
2,覆盖。子类中。覆盖也称为重写,覆写。override
覆盖注意事项:
1,子类方法覆盖父类方法时,子类权限必须要大于等于父类的权限。public private 默认
2,静态只能覆盖静态,或被静态覆盖。
/*
什么时候使用覆盖操作?
当对一个类进行子类的扩展时,子类需要保留父类的功能声明,
但是要定义子类中该功能的特有内容时,就使用覆盖操作完成.
*/
class ExtendsDemo3
{
public static void main(String[] args)
{
// Zi z = new Zi();
// z.show();
NewPhone p = new NewPhone();
p.show();
p.call();
}
}
class honeP
{
void call()
{}
void show()
{
System.out.println(“number”);
}
}
class NewPhone extends Phone
{
void show()
{
System.out.println(“name”);
System.out.println(“pic”);
super.show();
}
}
/*
子父类中的构造函数的特点。
在子类构造对象时,发现,访问子类构造函数时,父类也运行了。
为什么呢?
原因是:在子类的构造函数中第一行有一个默认的隐式语句。 super();
(构造函数没有继承哦)
子类的实例化过程:子类中所有的构造函数默认都会访问父类中的空参数的构造函数。
为什么子类实例化的时候要访问父类中的构造函数呢?
那是因为子类继承了父类,获取到了父类中内容(属性),所以在使用父类内容之前,
要先看父类是如何对自己的内容进行初始化的。
所以子类在构造对象时,必须访问父类中的构造函数。
为完成这个必须的动作,就在子类的构造函数中加入了super();语句。
如果父类中没有定义空参数构造函数,那么子类的构造函数必须用super明确要调用
父类中哪个构造函数super(22);同时子类构造函数中如果使用this调用了本类构造函数时,
那么super就没有了,因为super和this都只能定义第一行。所以只能有一个。
但是可以保证的是,子类中肯定会有其他的构造函数访问父类的构造函数。
注意:supre语句必须要定义在子类构造函数的第一行。因为父类的初始化动作要先完成。
//–>通过super初始化父类内容时,子类的成员变量并未显示初始化。等super()父类初始化完毕后,
*/
class Fu
{
int num ;
Fu()
{
num =10;
System.out.println(“A fu run”);
}
Fu(int x)
{
System.out.println(“B fu run…”+x);
}
}
class Zi extends Fu
{
int num;
Zi()
{
//super();//调用的就是父类中的空参数的构造函数。
System.out.println("C zi run"+num);
}
Zi(int x)
{
this();
//super();
// super(x);
System.out.println("D zi run "+x);
}
}
class ExtendsDemo4
{
public static void main(String[] args)
{
new Zi(6);
}
}
class Demo//extends Object
{
/*
Demo()
{
super();
return;
}
*/
}
!!!!!这个程序好好看看!
class Fu
{
Fu()
{
super();
show();
return;
}
void show()
{
System.out.println("fu show");
}
}
class Zi extends Fu
{
int num = 8;
Zi()
{
super();
//–>通过super初始化父类内容时,子类的成员变量并未显示初始化。等super()父类初始化完毕后,
//才进行子类的成员变量显示初始化。
System.out.println("zi cons run...."+num);
return;
}
void show()
{
System.out.println("zi show..."+num);
}
}
class ExtendsDemo5
{
public static void main(String[] args)
{
Zi z = new Zi();
z.show();
}
}
//zi show …0
//zi cons run
//zi show …8
/*
一个对象实例化过程:
Person p = new Person();
1,JVM会读取指定的路径下的Person.class文件,并加载进内存,
并会先加载Person的父类(如果有直接的父类的情况下).
2,在堆内存中的开辟空间,分配地址。
3,并在对象空间中,对对象中的属性进行默认初始化。
4,调用对应的构造函数进行初始化。
5,在构造函数中,第一行会先到调用父类中构造函数进行初始化。
6,父类初始化完毕后,在对子类的属性进行显示初始化。
7,在进行子类构造函数的特定初始化。
8,初始化完毕后,将地址值赋值给引用变量.
*/
变量第一个首字母小写,第二个单词首字母大写
常量 所有字幕都大写,单词不唯一,用下划线连接final double MY_PI=3.14;
成员一旦被final 通常静态
public static final double PI=3.14;
//继承弊端:打破了封装性。
/*
final关键字:
1,final是一个修饰符,可以修饰类,方法,变量。
2,final修饰的类不可以被继承。
3,final修饰的方法不可以被覆盖。
4,final修饰的变量是一个常量,只能赋值一次。
为什么要用final修饰变量。其实在程序如果一个数据是固定的,
那么直接使用这个数据就可以了,但是这样阅读性差,所以它该数据起个名称。
而且这个变量名称的值不能变化,所以加上final固定。
写法规范:常量所有字母都大写,多个单词,中间用_连接。
*/
class Fu
{
void method()
{
//调用了底层系统的资源。
}
}
class Zi extends Fu
{
public static final double MY_PI = 3.14;
static final int x = 7;
void method()
{
// final int x = 9;
// x = 9;
final int NUMBER = 9;
System.out.println(MY_PI);
}
}
class FinalDemo
{
public static void main(String[] args)
{
System.out.println(“Hello World!”);
}
}
/*
抽象类:
抽象:笼统,模糊,看不懂!不具体。
特点:
1,方法只有声明没有实现时,该方法就是抽象方法,需要被abstract修饰。
抽象方法必须定义在抽象类中。该类必须也被abstract修饰。
2,抽象类不可以被实例化。为什么?因为调用抽象方法没意义。
3,抽象类必须由其子类覆盖了所有的抽象方法后,该子类才可以实例化。
否则,这个子类还是抽象类。
1,抽象类中有构造函数吗?
有,用于给子类对象进行初始化。
2,抽象类可以不定义抽象方法吗?
可以的。 但是很少见,目的就是不让该类创建对象。AWT的适配器对象就是这种类。
通常这个类中的方法有方法体,但是却没有内容。
abstract class Demo
{
void show1()
{}
void show2()
{}
}
3,抽象关键字不可以和那些关键字共存?
private 不行 子类要覆盖呀
static 不行 没有方法体呀
final 不行 子类要覆盖呀
4,抽象类和一般类的异同点。
相同点:
抽象类和一般类都是用来描述事物的,都在内部定了成员。
不同:
1,一般类有足够的信息描述事物。
抽象类描述事物的信息有可能不足。
2,一般类中不能定义抽象方法,只能定非抽象方法。
抽象类中可定义抽象方法,同时也可以定义非抽象方法。
3,一般类可以被实例化。
抽象类不可以被实例化。
5,抽象类一定是个父类吗?
是的。因为需要子类覆盖其方法后才可以对子类实例化。
*/
abstract class Demo
{
abstract /抽象/ void show();
}
/*
class DemoA extends Demo
{
void show()
{
System.out.println(“demoa show”);
}
}
class DemoB extends Demo
{
void show()
{
System.out.println(“demob show”);
}
}
*/
abstract class 犬科
{
abstract void 吼叫();
}
class 狗 extends 犬科
{
void 吼叫()
{
System.out.println("汪汪");
}
}
class 狼 extends 犬科
{
void 吼叫()
{
System.out.println(“嗷嗷”);
}
}
class AbstractDemo
{
public static void main(String[] args)
{
System.out.println(“Hello World!”);
}
}
/*
abstract class AbsDemo
{
abstract void show1();
abstract void show2();
}
当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用
另一种形式定义和表示,就是 接口 interface。
*/
//定义接口使用的关键字不是class,是interface.
/*
对于接口当中常见的成员:而且这些成员都有固定的修饰符。
1,全局常量: public static final
2,抽象方法。public abstract
由此得出结论,接口中的成员都是公共的权限.
*/
interface Demo
{
public static final int NUM = 4;
public abstract void show1();
public abstract void show2();
}
//类与类之间是继承关系,类与接口直接是实现关系。
/*
接口不可以实例化。
只能由实现了接口的子类并覆盖了接口中所有的抽象方法后,该子类才可以实例化。
否则,这个子类就是一个抽象类。
*/
class DemoImpl implements /实现/Demo
{
public void show1()
{}
public void show2()
{
}
}
/*
在java中不直接支持多继承,因为会出现调用的不确定性。方法体重复
所以java将多继承机制进行改良,在java中变成了多实现。
一个类可以实现多个接口。
*/
interface A
{
public void show();
}
interface Z
{
public int add(int a,int b);
}
class Test implements A,Z//多实现
{
public int add(int a,int b)
{
return a+b+3;
}
/**/
public void show(){}
}
/*
一个类在继承另一个类的同时,还可以实现多个接口。
*/
class Q
{
public void method()
{}
}
abstract class Test2 extends Q implements A,Z
{
}
/*
接口的出现避免了单继承的局限性。
*/
interface CC
{
void show();
}
interface MM
{
void method();
}
interface QQ extends CC,MM//接口与接口之间是继承关系,而且接口可以多继承。
{
void function();
}
class WW implements QQ
{
//覆盖3个方法。
public void show(){}
public void method(){}
public void function(){}
}
class InterfaceDemo
{
public static void main(String[] args)
{
Test t = new Test();
t.show();
// DemoImpl d = new DemoImpl();
// System.out.println(d.NUM);
// System.out.println(DemoImpl.NUM);
// System.out.println(Demo.NUM);
}
}
接口是对外暴露的规则
接口是程序的功能扩展
接口降低耦合性
接口可以多实现
/*
抽象类和接口的异同点:
相同点:
都是不断向上抽取而来的。
不同点:
1,抽象类需要被继承,而且只能单继承。
接口需要被实现,而且可以多实现。
2,抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法。
接口中只能定义抽象方法,必须由子类去实现。
3,抽象类的继承,是is a关系,在定义该体系的基本共性内容。
接口的实现是 like a 关系,在定义体系额外功能。
犬按功能分:有导盲犬,搜爆犬。
abstract class 犬 //基本功能
{
abstract void 吼叫();
}
//abstract class 导盲
interface 导盲 //额外功能
{
abstract void 导盲();
}
class 导盲犬 extends 犬 implements 导盲
{
public void 吼叫()
{
}
/*
笔记本电脑使用。
为了扩展笔记本的功能,但日后出现什么功能设备不知道。
定义一个规则,只要日后出现的设备都符合这个规则就可以了。
规则在java中就是接口。
*/
interface USB// 暴露的规则。
{
public void open();
public void close();
}
class BookPC
{
public static void main(String[] args)
{
useUSB(new UPan());//功能扩展了。
useUSB(new UsbMouse());
}
//使用规则。
public static void useUSB(USB u)//接口类型的引用,用于接收(指向)接口的子类对象。//USB u= new UPan();
{
if(u!=null)
{
u.open();
u.close();
}
}
}
//一年后。------------------------------
//实现规则。
//这些设备和电脑的耦合性降低了。
class UPan implements USB
{
public void open()
{
System.out.println(“upan open”);
}
public void close()
{
System.out.println(“upan close”);
}
}
class UsbMouse implements USB
{
public void open()
{
System.out.println(“UsbMouse open”);
}
public void close()
{
System.out.println(“UsbMouse close”);
}
}
/*
class Mouse
{
}
class BookPC
{
public static void main(String[] args)
{
useMouse(new Mouse());
}
public static void useMOuse(Mouse m)
{
m.open();
}
public static void useMOuse(Mouse m)
{
m.open();
}
}
*/
/*
对象的多态性。
class 动物
{}
class 猫 extends 动物
{}
class 狗 extends 动物
{}
猫 x = new 猫();
动物 x = new 猫();//一个对象,两种形态。
猫这类事物即具备者猫的形态,又具备着动物的形态。
这就是对象的多态性。
简单说:就是一个对象对应着不同类型.
多态在代码中的体现:
父类或者接口的引用指向其子类的对象。
多态的好处:
提高了代码的扩展性,前期定义的代码可以使用后期的内容。
多态的弊端:
前期定义的内容不能使用(调用)后期子类的特有内容。
多态的前提:
1,必须有关系,继承,实现。
2,要有覆盖。
*/
abstract class Animal
{
abstract void eat();
}
class Dog extends Animal
{
void eat()
{
System.out.println(“啃骨头”);
}
void lookHome()
{
System.out.println(“看家”);
}
}
class Cat extends Animal
{
void eat()
{
System.out.println(“吃鱼”);
}
void catchMouse()
{
System.out.println(“抓老鼠”);
}
}
class Pig extends Animal
{
void eat()
{
System.out.println(“饲料”);
}
void gongDi()
{
System.out.println(“拱地”);
}
}
class DuoTaiDemo
{
public static void main(String[] args)
{
// Cat c = new Cat();
// c.eat();
// c.catchMouse();
Animal a = new Cat(); //自动类型提升,猫对象提升了动物类型。但是特有功能无法s访问。 提高扩展性
//作用就是限制对特有功能的访问。
//专业讲:向上转型。将子类型隐藏。就不用使用子类的特有方法。
// a.eat();
//如果还想用具体动物猫的特有功能。
//你可以将该对象进行向下转型。
// Cat c = (Cat)a;//向下转型的目的是为了使用子类中的特有方法。
// c.eat();
// c.catchMouse();
// 注意:对于转型,自始自终都是子类对象在做着类型的变化。
// Animal a1 = new Dog();
// Cat c1 = (Cat)a1;//ClassCastException
/*
Cat c = new Cat();
// Dog d = new Dog();
// c.eat();
method©;
// method(d);
// method(new Pig());
*/
method(new Dog());
}
public static void method(Animal a)//Animal a = new Dog();
{
a.eat();
if(a instanceof Cat)//instanceof:用于判断对象的具体类型。只能用于引用数据类型判断
// //通常在向下转型前用于健壮性的判断。
{
Cat c = (Cat)a;
c.catchMouse();
}
else if(a instanceof Dog)
{
Dog d = (Dog)a;
d.lookHome();
}
else
{
}
}
/*
public static void method(Cat c)
{
c.eat();
}
public static void method(Dog d)
{
}
*/
}
覆盖指发生在函数上哦和变量没关系哦
/*
多态时,
成员的特点:
1,成员变量。
编译时:参考引用型变量所属的类中的是否有调用的成员变量,有,编译通过,没有,编译失败。
运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成员变量。
简单说:编译和运行都参考等号的左边。哦了。
作为了解。
2,成员函数(非静态)。
编译时:参考引用型变量所属的类中的是否有调用的函数。有,编译通过,没有,编译失败。
运行时:参考的是对象所属的类中是否有调用的函数。
简单说:编译看左边,运行看右边。
因为成员函数存在覆盖特性。
3,静态函数。
编译时:参考引用型变量所属的类中的是否有调用的静态方法。
运行时:参考引用型变量所属的类中的是否有调用的静态方法。
简单说,编译和运行都看左边。
其实对于静态方法,是不需要对象的。直接用类名调用即可。
*/
class Fu
{
// int num = 3;
void show()
{
System.out.println(“fu show”);
}
static void method()
{
System.out.println("fu static method");
}
}
class Zi extends Fu
{
// int num = 4;
void show()
{
System.out.println(“zi show”);
}
static void method()
{
System.out.println("zi static method");
}
}
class DuoTaiDemo3
{
public static void main(String[] args)
{
Fu.method();
Zi.method();
Fu f = new Zi();//
// f.method();
// f.show();
// System.out.println(f.num);
// Zi z = new Zi();
// System.out.println(z.num);
}
}
/*
内部类访问特点:
1,内部类可以直接访问外部类中的成员。
2,外部类要访问内部类,必须建立内部类的对象。
一把用于类的设计。
分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容。
这时就是还有的事物定义成内部类来描述。
*/
class Outer
{
private static int num = 31;
class Inner// 内部类。
{
void show()
{
System.out.println("show run..."+num);
}
/*static void function()//如果内部类中定义了静态成员,该内部类也必须是静态的。
{
System.out.println("function run ...."+num);
}
*/
}
public void method()
{
Inner in = new Inner();
in.show();
}
}
class InnerClassDemo
{
public static void main(String[] args)
{
// Outer out = new Outer();
// out.method();
//直接访问外部类中的内部类中的成员。
// Outer.Inner in = new Outer().new Inner();
// in.show();
//如果内部类是静态的。 相当于一个外部类
// Outer.Inner in = new Outer.Inner();
// in.show();
//如果内部类是静态的,成员是静态的。
// Outer.Inner.function();
}
}
/*
为什么内部类能直接访问外部类中成员呢?
那是因为内部类持有了外部类的引用。 外部类名.this
*/
class Outer
{
int num = 3;
class Inner
{
int num = 4;
void show()
{
int num = 5;
System.out.println(Outer.this.num);//了解了解 是外部类
//this.num 是内部类
}
}
void method()
{
new Inner().show();
}
}
class InnerClassDemo2
{
public static void main(String[] args)
{
new Outer().method();
}
}
/*
内部类可以存放在局部位置上。
内部类在局部位置上只能访问局部中被final修饰的局部变量。
*/
//因为方法用完释放了,但是对象的引用还在,生命周期不同
class Outer
{
int num = 3;
Object method()
{
final int x = 9;
class Inner
{
public String toString()
{
return "show ..."+x;
}
}
Object in = new Inner();
return in;//0x0045
// in.show();
}
}
class InnerClassDemo3
{
public static void main(String[] args)
{
Outer out = new Outer();
Object obj = out.method();
System.out.println(obj);
}
}
/*
class Fu extends Object
{
}
class zi extends Fu
{
}
Fu f = new zi();
Object o = new Fu();
*/
/*
匿名内部类。就是内部类的简写格式。
必须有前提:
内部类必须继承或者实现一个外部类或者接口。
匿名内部类:其实就是一个匿名子类对象。
格式:new 父类or接口(){子类内容}
*/
abstract class Demo
{
abstract void show();
}
class Outer
{
int num = 4;
/*
class Inner extends Demo
{
void show()
{
System.out.println(“show …”+num);
}
}
*/
public void method()
{
//new Inner().show();
new Demo()//匿名内部类。
{
void show()
{
System.out.println(“show …”+num);
}
}.show();
}
}
class InnerClassDemo4
{
public static void main(String[] args)
{
new Outer().method();
}
}
interface Inter
{
void show1();
void show2();
}
class Outer
{
/*
class Inner implements Inter
{
public void show1()
{
}
public void show2()
{
}
}
*/
public void method()
{
// Inner in = new Inner();
// in.show1();
// in.show2();
Inter in = new Inter()
{
public void show1()
{
}
public void show2()
{
}
};
in.show1();
in.show2();
}
}
/*
通常的使用场景之一:
当函数参数是接口类型时,而且接口中的方法不超过三个。
可以用匿名内部类作为实际参数进行传递
*/
class InnerClassDemo5
{
class Inner
{
}
public static void main(String[] args)
{
System.out.println("Hello World!");
/*
show(new Inter()
{
public void show1(){}
public void show2(){}
});
*/
{
void method()
{
Object obj = new Object()
{
public void show()
{
System.out.println(“show run”);
}
};
obj.show();//因为匿名内部类这个子类对象被向上转型为了Object类型。
//这样就不能在使用子类特有的方法了。
}
}
class InnerClassDemo6
{
public static void main(String[] args)
{
new Outer().method();
}
}
顺序!!
2完后,进行父类的显示初始化,然后父类的代码块,然后父类的构造
/*
异常:是在运行时期发生的不正常情况。。
在java中用类的形式对不正常情况进行了描述和封装对象。
描述不正常的情况的类,就称为异常类。
以前正常流程代码和问题处理代码相结合,
现在将正常流程代码和问题处理代码分离。提高阅读性.
其实异常就是java通过面向对象的思想将问题封装成了对象.
用异常类对其进行描述。
不同的问题用不同的类进行具体的描述。 比如角标越界。空指针等等。
问题很多,意味着描述的类也很多,
将其共性进行向上抽取,形成了异常体系。
最终问题(不正常情况)就分成了两大类。
Throwable:无论是error,还是异常,问题,问题发生就应该可以抛出,让调用者知道并处理。
//该体系的特点就在于Throwable及其所有的子类都具有可抛性。
可抛性到底指的是什么呢?怎么体现可抛性呢?
其实是通过两个关键字来体现的。
throws throw ,凡是可以被这两个关键字所操作的类和对象都具备可抛性.
|–1,一般不可处理的。Error
特点:是由jvm抛出的严重性的问题。
这种问题发生一般不针对性处理。直接修改程序
|–2,可以处理的。Exception
该体系的特点:
子类的后缀名都是用其父类名作为后缀,阅读性很强。
*/
class ExceptionDemo
{
public static void main(String[] args)
{
int[] arr = new int[10241024800];//java.lang.OutOfMemoryError: Java heap space
// arr = null;
// System.out.println(arr[3]);
//
//
// sleep(-5);
}
public static void sleep2(int time)
{
if(time<0)
{
// 处理办法。
// 处理办法。
// 处理办法。
// 处理办法。
// 处理办法。
}
if(time>100000)
{
// 处理办法。
// 处理办法。
// 处理办法。
// 处理办法。
// 处理办法。
// 处理办法。
}
System.out.println(“我睡。。。”+time);
// sleep(-5);
}
public static void sleep(int time)
{
if(time<0)
{
// 抛出 new FuTime();//就代码着时间为负的情况,这个对象中会包含着问题的名称,信息,位置等信息。
}
if(time>100000)
{
// 抛出 new BigTime();
}
System.out.println(“我睡。。。”+time);
}
}
/*
class FuTime
{
}
class BigTime
{
}
*/
/*
*/
class Demo
{
public int method(int[] arr,int index)
{
if(arr==null)
throw new NullPointerException("数组的引用不能为空!");
if(index>=arr.length)
{
throw new ArrayIndexOutOfBoundsException("数组的角标越界啦,哥们,你是不是疯了?:"+index);
}
if(index<0)
{
throw new ArrayIndexOutOfBoundsException("数组的角标不能为负数,哥们,你是真疯了!:"+index);
}
return arr[index];
}
}
class ExceptionDemo2
{
public static void main(String[] args)
{
int[] arr = new int[3];
Demo d = new Demo();
int num = d.method(null,-30);
System.out.println("num="+num);
System.out.println("over");
}
}
/*
对于角标是整数不存在,可以用角标越界表示,
对于负数为角标的情况,准备用负数角标异常来表示。
负数角标这种异常在java中并没有定义过。
那就按照java异常的创建思想,面向对象,将负数角标进行自定义描述。并封装成对象。
这种自定义的问题描述成为自定义异常。
注意:如果让一个类称为异常类,必须要继承异常体系,因为只有称为异常体系的子类才有资格具备可抛性。
才可以被两个关键字所操作,throws throw
异常的分类:
1,编译时被检测异常:只要是Exception和其子类都是,除了特殊子类RuntimeException体系。
这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式。
这样的问题都可以针对性的处理。
2,编译时不检测异常(运行时异常):就是Exception中的RuntimeException和其子类。
这种问题的发生,无法让功能继续,运算无法进行,更多是因为调用者的原因导致的而或者引发了内部状态的改变导致的。
那么这种问题一般不处理,直接编译通过,在运行时,让调用者调用时的程序强制停止,让调用者对代码进行修正。
所以自定义异常时,要么继承Exception。要么继承RuntimeException。
throws 和throw的区别。
1,throws使用在函数上。
throw使用在函数内。
2,throws抛出的是异常类,可以抛出多个,用逗号隔开。
throw抛出的是异常对象。
*/
class FuShuIndexException extends Exception
{
FuShuIndexException()
{}
FuShuIndexException(String msg)
{
super(msg);
}
}
class Demo
{
public int method(int[] arr,int index)//throws NullPointerException//FuShuIndexException
{
if(arr==null)
throw new NullPointerException("数组的引用不能为空!");
if(index>=arr.length)
{
throw new ArrayIndexOutOfBoundsException("数组的角标越界啦,哥们,你是不是疯了?:"+index);
}
if(index<0)
{
throw new FuShuIndexException("角标变成负数啦!!");
}
return arr[index];
}
}
class ExceptionDemo3
{
public static void main(String[] args) //throws FuShuIndexException
{
int[] arr = new int[3];
Demo d = new Demo();
int num = d.method(null,-30);
System.out.println("num="+num);
System.out.println("over");
}
}
/*
class Person
{
private String name;
Person(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
class Student extends Person
{
Student(String name)
{
super(name);
}
}
*/
RuntimeException 可以处理液可以不处理
多catch父类catch放在最下面
/*
异常处理的捕捉形式:
这是可以对异常进行针对性处理的方式。
具体格式是:
try
{
//需要被检测异常的代码。
}
catch(异常类 变量)//该变量用于接收发生的异常对象
{
//处理异常的代码。
}
finally
{
//一定会被执行的代码。
}
异常处理的原则:
1,函数内容如果抛出需要检测的异常,那么函数上必须要声明。
否则必须在函数内用trycatch捕捉,否则编译失败。
2,如果调用到了声明异常的函数,要么trycatch要么throws,否则编译失败。
3,什么时候catch,什么时候throws 呢?
功能内容可以解决,用catch。
解决不了,用throws告诉调用者,由调用者解决 。
4,一个功能如果抛出了多个异常,那么调用时,必须有对应多个catch进行针对性的处理。
内部又几个需要检测的异常,就抛几个异常,抛出几个,就catch几个。
*/
class FuShuIndexException extends Exception
{
FuShuIndexException()
{}
FuShuIndexException(String msg)
{
super(msg);
}
}
class Demo
{
public int method(int[] arr,int index)//throws NullPointerException,FuShuIndexException
{
if(arr==null)
throw new NullPointerException(“没有任何数组实体”);
if(index<0)
throw new FuShuIndexException();
return arr[index];
}
}
class ExceptionDemo4
{
public static void main(String[] args)
{
int[] arr = new int[3];
Demo d = new Demo();
try
{
int num = d.method(null,-1);
System.out.println(“num=”+num);
}
catch(NullPointerException e)
{
System.out.println(e.toString());
}
catch (FuShuIndexException e)
{
System.out.println("message:"+e.getMessage());
System.out.println("string:"+e.toString());
e.printStackTrace();//jvm默认的异常处理机制就是调用异常对象的这个方法。
System.out.println("负数角标异常!!!!");
}
/*
catch(Exception e)//多catch父类的catch放在最下面。
{
}
*/
System.out.println("over");
}
}
/*
毕老师用电脑上课。
问题领域中涉及两个对象。
毕老师,电脑。
分析其中的问题。
比如电脑蓝屏啦。冒烟啦。
*/
class LanPingException extends Exception
{
LanPingException(String msg)
{
super(msg);
}
}
class MaoYanException extends Exception
{
MaoYanException(String msg)
{
super(msg);
}
}
class NoPlanException extends Exception
{
NoPlanException(String msg)
{
super(msg);
}
}
class Computer
{
private int state = 2;
public void run()throws LanPingException,MaoYanException
{
if(state1)
throw new LanPingException(“电脑蓝屏啦!!”);
if(state2)
throw new MaoYanException(“电脑冒烟啦!!”);
System.out.println("电脑运行");
}
public void reset()
{
state = 0;
System.out.println("电脑重启");
}
}
class Teacher
{
private String name;
private Computer comp;
Teacher(String name)
{
this.name = name;
comp = new Computer();
}
public void prelect()throws NoPlanException
{
try
{
comp.run();
System.out.println(name+"讲课");
}
catch (LanPingException e)
{
System.out.println(e.toString());
comp.reset();
prelect();
}
catch (MaoYanException e)
{
System.out.println(e.toString());
test();
//可以对电脑进行维修。
// throw e;
throw new NoPlanException(“课时进度无法完成,原因:”+e.getMessage());
}
}
public void test()
{
System.out.println("大家练习");
}
}
class ExceptionTest
{
public static void main(String[] args)
{
Teacher t = new Teacher(“毕老师”);
try
{
t.prelect();
}
catch (NoPlanException e)
{
System.out.println(e.toString()+"......");
System.out.println("换人");
}
}
}
/*
class NoAddException extends Exception
{}
void addData(Data d)throws NoAddException
{
连接数据库
try
{
添加数据。出现异常 SQLException();
}
catch(SQLException e)
{
//处理代码。
throw new NoAddException();
}
fianlly
{
关闭数据库。
}
}
*/异常的注意事项:
1,子类在覆盖父类方法时,父类的方法如果抛出了异常,
那么子类的方法只能抛出父类的异常或者该异常的子类。
2,如果父类抛出多个异常,那么子类只能抛出父类异常的子集。
简单说:子类覆盖父类只能抛出父类的异常或者子类或者子集。
注意:如果父类的方法没有抛出异常,那么子类覆盖时绝对不能抛,就只能try .
interface Inter
{
void function();
}
class D implements Inter
{
public void function()//throws Exception
{}
}
class A extends Exception
{
}
class B extends A
{
}
class C extends Exception
{
}
Exception
|–A
|–B
|–C
class Fu
{
void show()throws A
{}
}
class Test
{
void method(Fu f)//Fu f = new Zi();
{
try
{
f.show();
}
catch (A a)
{
}
}
}
class Zi extends Fu
{
void show()throws C
{
}
}
class
{
public static void main(String[] args)
{
Test t = new Test();
t.show(new Zi());
}
}
/*
Object:所有类的根类。
Object是不断抽取而来,具备着所有对象都具备的共性内容。
常用的共性功能:
/
/
class Fu // extends Object
{
Fu()
{
super();
}
}
class Zi extends Fu
{
Zi()
{
super();
}
}
*/
class Person extends Object
{
private int age;
Person(int age)
{
this.age = age;
}
/*
//比较Person的年龄。是否是同龄人
public boolean compare(Person p)
{
return this.age == p.age;
}
*/
/*
一般都会覆盖此三个方法,根据对象的特有内容,建立判断对象是否相同的依据。
*/
public boolean equals(Object obj)//Object obj = p2;,复写,多态,扩展性
{
if(!(obj instanceof Person))
{
// return false;
throw new ClassCastException(“类型错误”);
}
Person p = (Person)obj;
return this.age == p.age;
}
/*
public int hashCode()
{
return age;
}
*/
public String toString()//对象才能调用
{
return "Person :"+age;
}
}
class Demo
{
}
class ObjectDemo
{
public static void main(String[] args)
{
Person p1 = new Person(60);
Person p2 = new Person(20);
Demo d = new Demo();
// System.out.println(p1.equals(p2));
// System.out.println(p1);
// System.out.println(Integer.toHexString(p1.hashCode()));
// Class clazz1 = p1.getClass();
// Class clazz2 = p2.getClass();
// System.out.println(clazz1==clazz2);
// System.out.println(clazz1.getName());
System.out.println(p1.toString());//Person@61de33
System.out.println(p1.getClass().getName()+"$"+Integer.toHexString(p1.hashCode()));//Person@61de33
// Person p3 = p1;
// Demo d = new Demo();
// System.out.println(p1==p2);
// System.out.println(p1.equals(p2));
}
}
Integer.toHexString() 转成十六进制
对象相同?哈希值相同,内容相同
所以重写equals时,得重写hashCode
(toString一般来说也要重写)
class Class{} 描述字节码文件的类 ,只有一个哦
//
包名的所有字母要小写
javac -d . PackageDemo.java 有包,指定文件位置
. 是当前文件夹的意思
配置classpath弄到包所在文件夹就行
package mypack;
//import packa.DemoA;//导入了packa包中的DemoA类。
//import packa.DemoAA;
//import packa.DemoAAA;
/*
import packa.;//导入了packa包中所有的类。不包括文件夹
开发的时候不要全导包
import packa.abc.;
packa\DemoA.class
packa\abc\DemoAbc.class
*/
//导包的原则:用到哪个类,就导入哪个类。
//import 干嘛用的啊?为了简化类名书写。
class PackageDemo
{
public static void main(String[] args)
{
//packa.DemoA d = new packa.DemoA();
DemoAbc d = new DemoA();
d.show();
packb.DemoB b = new packb.DemoB();
b.method();
System.out.println("Hello Package!");
}
}
/*
PackageDemo.java:8: 找不到符号
符号: 类 DemoA
位置: 类 mypack.PackageDemo
DemoA d = new DemoA();
^
PackageDemo.java:8: 找不到符号
符号: 类 DemoA
位置: 类 mypack.PackageDemo
DemoA d = new DemoA();
^
2 错误
原因:类名写错。
PackageDemo.java:8: 软件包 packa 不存在
packa.DemoA d = new packa.DemoA();
^
PackageDemo.java:8: 软件包 packa 不存在
packa.DemoA d = new packa.DemoA();
^
2 错误
原因是在当前目录下没找到,因为packa存放在其他目录下,
应该配置一个classpath。配置classpath弄到包所在文件夹就行
PackageDemo.java:9: show() 在 packa.DemoA 中不是公共的;无法从外部软件包中对其进
行访问
d.show();
^
1 错误
总结:
包与包之间的类进行访问,被访问的包中的类必须是public的,被访问的包中的类的方法也必须是public的。
public protected default private
同一类中 ok ok ok ok
同一包中 ok ok ok
子类中 ok ok
不同包中 ok
*/
protected,你得继承我,我才让你用,必须子父类
多态,编译看左面,运行看右面
A a=new B();
a.func();
编译时看A里面有没有func没有就失败
&&左错,短路
int i=4 是局部变量
非静态的内部类中不能定义静态的成员
成员变量看左边,编译运行都左面
成员函数编译看左面,运行看右面
setName,getName 为的是把局部变量存到堆里,可以随时访问,生命周期变长
别忘了super();
编译失败,无论怎么运行都执行不了该语句
throws 的作用是不在本方法中进行异常处理,而是抛给吊用此方法的类中进行处理
因为是static的 所以一直存在,第二个output的时候捕捉到异常,1342,然后return前finally13423,然后return,结束
/*
进程:正在进行中的程序(直译).
线程:就是进程中一个负责程序执行的控制单元(执行路径)
一个进程中可以多执行路径,称之为多线程。
一个进程中至少要有一个线程。
开启多个线程是为了同时运行多部分代码。
每一个线程都有自己运行的内容。这个内容可以称为线程要执行的任务。
多线程好处:解决了多部分同时运行的问题。
多线程的弊端:线程太多回到效率的降低。
其实应用程序的执行都是cpu在做着快速的切换完成的。这个切换是随机的。
JVM启动时就启动了多个线程,至少有两个线程可以分析的出来。
1,执行main函数的线程,
该线程的任务代码都定义在main函数中。
2,负责垃圾回收的线程。
/*
如何创建一个线程呢?
创建线程方式一:继承Thread类。
步骤:
1,定义一个类继承Thread类。
2,覆盖Thread类中的run方法。
3,直接创建Thread的子类对象创建线程。
4,调用start方法开启线程并调用线程的任务run方法执行。
可以通过Thread的getName获取线程的名称 Thread-编号(从0开始)
主线程的名字就是main。
*/
class Demo extends Thread
{
private String name;
Demo(String name)
{
super(name);
//this.name = name;
}
public void run()
{
for(int x=0; x<10; x++)
{
//for(int y=-9999999; y<999999999; y++){}
System.out.println(name+"…x="+x+"…name="+Thread.currentThread().getName());
}
}
}
class ThreadDemo2
{
public static void main(String[] args)
{
/*
创建线程的目的是为了开启一条执行路径,去运行指定的代码和其他代码实现同时运行。
而运行的指定代码就是这个执行路径的任务。
jvm创建的主线程的任务都定义在了主函数中。
而自定义的线程它的任务在哪儿呢?
Thread类用于描述线程,线程是需要任务的。所以Thread类也对任务的描述。
这个任务就通过Thread类中的run方法来体现。也就是说,run方法就是封装自定义线程运行任务的函数。
run方法中定义就是线程要运行的任务代码。
开启线程是为了运行指定代码,所以只有继承Thread类,并复写run方法。
将运行的代码定义在run方法中即可。
*/
//
// Thread t1 = new Thread();
Demo d1 = new Demo("旺财");
Demo d2 = new Demo("xiaoqiang");
d1.start();//开启线程,调用run方法。
d2.start();
System.out.println("over...."+Thread.currentThread().getName());
}
}
//调用run和调用start有什么区别?
class Demo extends Thread
{
private String name;
Demo(String name)
{
// super(name);
this.name = name;
}
public void run()
{
int[] arr = new int[3];
System.out.println(arr[3]);
for(int x=0; x<10; x++)
{
System.out.println("…x="+x+"…name="+Thread.currentThread().getName());
}
}
}
class ThreadDemo3
{
public static void main(String[] args)
{
Demo d1 = new Demo(“旺财”);
Demo d2 = new Demo(“xiaoqiang”);
d1.start();
d2.start();
System.out.println(4/0);//throw new ArithmeticException();
for(int x=0; x<20; x++)
{
System.out.println(x+"...."+Thread.currentThread().getName());
}
}
}
/*
创建线程的第一种方式:继承Thread类。
创建线程的第二种方式:实现Runnable接口。
1,定义类实现Runnable接口。
2,覆盖接口中的run方法,将线程的任务代码封装到run方法中。
3,通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递。
为什么?因为线程的任务都封装在Runnable接口子类对象的run方法中。
所以要在线程对象创建时就必须明确要运行的任务。
4,调用线程对象的start方法开启线程。
实现Runnable接口的好处:
1,将线程的任务从线程的子类中分离出来,进行了单独的封装。
按照面向对象的思想将任务的封装成对象。
2,避免了java单继承的局限性。
所以,创建线程的第二种方式较为常用。
*/
class Demo implements Runnable//extends Fu //准备扩展Demo类的功能,让其中的内容可以作为线程的任务执行。
//通过接口的形式完成。
{
public void run()
{
show();
}
public void show()
{
for(int x=0; x<20; x++)
{
System.out.println(Thread.currentThread().getName()+"…"+x);
}
}
}
class ThreadDemo
{
public static void main(String[] args)
{
Demo d = new Demo();
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();
t2.start();
// Demo d1 = new Demo();
// Demo d2 = new Demo();
// d1.start();
// d2.start();
}
}
/*
class Thread
{
private Runnable r;
Thread()
{
}
Thread(Runnable r)
{
this.r = r;
}
public void run()
{
if(r!=null)
r.run();
}
public void start()
{
run();
}
}
class ThreadImpl implements Runnable
{
public void run()
{
System.out.println(“runnable run”);
}
}
ThreadImpl i = new ThreadImpl();
Thread t = new Thread(i);
t.start();
class SubThread extends Thread
{
public void run()
{
System.out.println(“hahah”);
}
}
//SubThread s = new SubThread();
//s.start();
*/
sleep只能try catch
多线程的安全性问题:
/*
需求:卖票。
*/
/*
线程安全问题产生的原因:
1,多个线程在操作共享的数据。
2,操作共享数据的线程代码有多条。
当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算。
就会导致线程安全问题的产生。
解决思路;
就是将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,
其他线程时不可以参与运算的。
必须要当前线程把这些代码都执行完毕后,其他线程才可以参与运算。
在java中,用同步代码块就可以解决这个问题。
同步代码块的格式:!!!!!!!!!
synchronized(对象)
{
需要被同步的代码 ;
}
同步的好处:解决了线程的安全问题。
同步的弊端:相对降低了效率,因为同步外的线程的都会判断同步锁。
同步的前提:同步中必须有多个线程并使用同一个锁。
*/
class Ticket implements Runnable//extends Thread
{
private int num = 100;
Object obj = new Object();
public void run()
{
while(true)
{
synchronized(obj)
{
if(num>0)
{
try{Thread.sleep(10);}catch (InterruptedException e){}
System.out.println(Thread.currentThread().getName()+".....sale...."+num--);
}
}
}
}
}
class TicketDemo
{
public static void main(String[] args)
{
Ticket t = new Ticket();//创建一个线程任务对象。
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
/*
Ticket t1 = new Ticket();
// Ticket t2 = new Ticket();
// Ticket t3 = new Ticket();
// Ticket t4 = new Ticket();
t1.start();
t1.start();//一个线程不能开启两次,会抛出无效线程状态异常
t1.start();
t1.start();
*/
}
}
线程安全隐患!!!!!
/*
需求:储户,两个,每个都到银行存钱每次存100,,共存三次。
*/
class Bank
{
private int sum;
// private Object obj = new Object();
public synchronized void add(int num)//同步函数
{
// synchronized(obj)
// {
sum = sum + num;
// -->
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(“sum=”+sum);
// }
}
}
class Cus implements Runnable
{
private Bank b = new Bank();
public void run()
{
for(int x=0; x<3; x++)
{
b.add(100);
}
}
}
class BankDemo
{
public static void main(String[] args)
{
Cus c = new Cus();
Thread t1 = new Thread©;
Thread t2 = new Thread©;
t1.start();
t2.start();
}
}
/*
同步函数的使用的锁是this;
同步函数和同步代码块的区别:
同步函数的锁是固定的this。当前对象
同步代码块的锁是任意的对象。
建议使用同步代码块。
*/
class Ticket implements Runnable
{
private int num = 100;
// Object obj = new Object();
boolean flag = true;
public void run()
{
// System.out.println(“this:”+this);
if(flag)
while(true)
{
synchronized(this)
{
if(num>0)
{
try{Thread.sleep(10);}catch (InterruptedException e){}
System.out.println(Thread.currentThread().getName()+".....obj...."+num--);
}
}
}
else
while(true)
this.show();
}
public synchronized void show()
{
if(num>0)
{
try{Thread.sleep(10);}catch (InterruptedException e){}
System.out.println(Thread.currentThread().getName()+".....function...."+num--);
}
}
}
class SynFunctionLockDemo
{
public static void main(String[] args)
{
Ticket t = new Ticket();
// System.out.println(“t:”+t);
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
try{Thread.sleep(10);}catch( InterruptedException e){}
t.flag = false;
t2.start();
}
}
this.getClass:获取当前字节码对象,非静态
/*
静态的同步函数使用的锁是 该函数所属字节码文件对象
可以用 getClass方法获取,也可以用当前 类名.class 表示。
*/
class Ticket implements Runnable
{
private static int num = 100;
// Object obj = new Object();
boolean flag = true;
public void run()
{
// System.out.println(“this:”+this.getClass());
if(flag)
while(true)
{
synchronized(Ticket.class)//(this.getClass())
{
if(num>0)
{
try{Thread.sleep(10);}catch (InterruptedException e){}
System.out.println(Thread.currentThread().getName()+".....obj...."+num--);
}
}
}
else
while(true)
this.show();
}
public static synchronized void show()
{
if(num>0)
{
try{Thread.sleep(10);}catch (InterruptedException e){}
System.out.println(Thread.currentThread().getName()+".....function...."+num--);
}
}
}
class StaticSynFunctionLockDemo
{
public static void main(String[] args)
{
Ticket t = new Ticket();
// Class clazz = t.getClass();
//
// Class clazz = Ticket.class;
// System.out.println(“t:”+t.getClass());
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
try{Thread.sleep(10);}catch(InterruptedException e){}
t.flag = false;
t2.start();
}
}
/*
死锁:常见情景之一:同步的嵌套。
*/
class Ticket implements Runnable
{
private int num = 100;
Object obj = new Object();
boolean flag = true;
public void run()
{
if(flag)
while(true)
{
synchronized(obj)
{
show();
}
}
else
while(true)
this.show();
}
public synchronized void show()
{
synchronized(obj)
{
if(num>0)
{
try{Thread.sleep(10);}catch (InterruptedException e){}
System.out.println(Thread.currentThread().getName()+".....sale...."+num--);
}
}
}
}
class DeadLockDemo
{
public static void main(String[] args)
{
Ticket t = new Ticket();
// System.out.println(“t:”+t);
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
try{Thread.sleep(10);}catch(InterruptedException e){}
t.flag = false;
t2.start();
}
}
class Test implements Runnable
{
private boolean flag;
Test(boolean flag)
{
this.flag = flag;
}
public void run()
{
if(flag)
{
while(true)
synchronized(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+"..if locka....");
synchronized(MyLock.lockb) {
System.out.println(Thread.currentThread().getName()+"..if lockb....");
}
}
}
else
{
while(true)
synchronized(MyLock.lockb)
{
System.out.println(Thread.currentThread().getName()+"..else lockb....");
synchronized(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+"..else locka....");
}
}
}
}
}
class MyLock
{
public static final Object locka = new Object();
public static final Object lockb = new Object();
}
class DeadLockTest
{
public static void main(String[] args)
{
Test a = new Test(true);
Test b = new Test(false);
Thread t1 = new Thread(a);
Thread t2 = new Thread(b);
t1.start();
t2.start();
}
}
一创建对象就有资源–构造函数
while(true) //无限切换
{
if(x==0)
{
r.name=”mike”;
r.sex=”male”;
}
else
{
r.name=”Tom”;
r.sex=”female”;
}
x=(x+1)%2 //在0和1之间切换
}
同步的前提:多线程 一个锁
/*
线程间通讯:
多个线程在处理同一资源,但是任务却不同。
*/
//资源
class Resource
{
String name;
String sex;
}
//输入
class Input implements Runnable
{
Resource r ;
// Object obj = new Object();
Input(Resource r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized®
{
if(x==0)
{
r.name = “mike”;
r.sex = “nan”;
}
else
{
r.name = “丽丽”;
r.sex = “女女女女女女”;
}
}
x = (x+1)%2;//1和0切换
}
}
}
//输出
class Output implements Runnable
{
Resource r;
// Object obj = new Object();
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r)
{
System.out.println(r.name+"....."+r.sex);
}
}
}
}
class ResourceDemo
{
public static void main(String[] args)
{
//创建资源。
Resource r = new Resource();
//创建任务。
Input in = new Input®;
Output out = new Output®;
//创建线程,执行路径。
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
//开启线程
t1.start();
t2.start();
}
}
run方法不能throws,因为父类没有声明
sleep wait都要捕捉异常
同步代码块对锁的操作是隐式的
/*
等待/唤醒机制。
涉及的方法:
1,wait(): 让线程处于冻结状态,被wait的线程会被存储到线程池中。
2,notify():唤醒线程池中一个线程(任意).
3,notifyAll():唤醒线程池中的所有线程。
这些方法都必须定义在同步中。
因为这些方法是用于操作线程状态的方法。
必须要明确到底操作的是哪个锁上的线程。
为什么操作线程的方法wait notify notifyAll定义在了Object类中?
因为这些方法是监视器的方法。监视器其实就是锁。
锁可以是任意的对象,任意的对象调用的方式一定定义在Object类中。
*/
//资源
class Resource
{
String name;
String sex;
boolean flag = false;
}
//输入
class Input implements Runnable
{
Resource r ;
// Object obj = new Object();
Input(Resource r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized®
{
if(r.flag)
try{r.wait();}catch(InterruptedException e){}
if(x==0)
{
r.name = “mike”;
r.sex = “nan”;
}
else
{
r.name = “丽丽”;
r.sex = “女女女女女女”;
}
r.flag = true;
r.notify();
}
x = (x+1)%2;
}
}
}
//输出
class Output implements Runnable
{
Resource r;
// Object obj = new Object();
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r)
{
if(!r.flag)
try{r.wait();}catch(InterruptedException e){}
System.out.println(r.name+"....."+r.sex);
r.flag = false;
r.notify();
}
}
}
}
class ResourceDemo2
{
public static void main(String[] args)
{
//创建资源。
Resource r = new Resource();
//创建任务。
Input in = new Input®;
Output out = new Output®;
//创建线程,执行路径。
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
//开启线程
t1.start();
t2.start();
}
}
class Resource
{
private String name;
private String sex;
private boolean flag = false;
public synchronized void set(String name,String sex)
{
if(flag)
try{this.wait();}catch(InterruptedException e){}
this.name = name;
this.sex = sex;
flag = true;
this.notify();
}
public synchronized void out()
{
if(!flag)
try{this.wait();}catch(InterruptedException e){}
System.out.println(name+"...+...."+sex);
flag = false;
notify();
}
}
//输入
class Input implements Runnable
{
Resource r ;
// Object obj = new Object();
Input(Resource r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
if(x==0)
{
r.set(“mike”,“nan”);
}
else
{
r.set(“丽丽”,“女女女女女女”);
}
x = (x+1)%2;
}
}
}
//输出
class Output implements Runnable
{
Resource r;
// Object obj = new Object();
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
}
class ResourceDemo3
{
public static void main(String[] args)
{
//创建资源。
Resource r = new Resource();
//创建任务。
Input in = new Input®;
Output out = new Output®;
//创建线程,执行路径。
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
//开启线程
t1.start();
t2.start();
}
}
/*
生产者,消费者。
多生产者,多消费者的问题。
if判断标记,只有一次,会导致不该运行的线程运行了。出现了数据错误的情况。
while判断标记,解决了线程获取执行权后,是否要运行!
notify:只能唤醒一个线程,如果本方唤醒了本方,没有意义。而且while判断标记+notify会导致死锁。
notifyAll解决了本方线程一定会唤醒对方线程的问题。
*/
class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
public synchronized void set(String name)//
{
while(flag)
try{this.wait();}catch(InterruptedException e){}// t1 t0
this.name = name + count;//烤鸭1 烤鸭2 烤鸭3
count++;//2 3 4
System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);//生产烤鸭1 生产烤鸭2 生产烤鸭3
flag = true;
notifyAll();
}
public synchronized void out()// t3
{
while(!flag)
try{this.wait();}catch(InterruptedException e){} //t2 t3
System.out.println(Thread.currentThread().getName()+"...消费者........"+this.name);//消费烤鸭1
flag = false;
notifyAll();
}
}
class Producer implements Runnable
{
private Resource r;
Producer(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.set(“烤鸭”);
}
}
}
class Consumer implements Runnable
{
private Resource r;
Consumer(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
}
class ProducerConsumerDemo
{
public static void main(String[] args)
{
Resource r = new Resource();
Producer pro = new Producer®;
Consumer con = new Consumer®;
Thread t0 = new Thread(pro);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
/*
jdk1.5以后将同步和锁封装成了对象。
并将操作锁的隐式方式定义到了该对象中,
将隐式动作变成了显示动作。
Lock接口: 出现替代了同步代码块或者同步函数。将同步的隐式锁操作变成现实锁操作。
同时更为灵活。可以一个锁上加上多组监视器。
lock():获取锁。
unlock():释放锁,通常需要定义finally代码块中。
Condition接口:出现替代了Object中的wait notify notifyAll方法。
将这些监视器方法单独进行了封装,变成Condition监视器对象。
可以任意锁进行组合。
await();
signal();
signalAll();
*/
import java.util.concurrent.locks.*;
class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
// 创建一个锁对象。
Lock lock = new ReentrantLock();
//通过已有的锁获取该锁上的监视器对象。
// Condition con = lock.newCondition();
//通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者。
Condition producer_con = lock.newCondition();
Condition consumer_con = lock.newCondition();
public void set(String name)// t0 t1
{
lock.lock();
try
{
while(flag)
// try{lock.wait();}catch(InterruptedException e){}// t1 t0
try{producer_con.await();}catch(InterruptedException e){}// t1 t0
this.name = name + count;//烤鸭1 烤鸭2 烤鸭3
count++;//2 3 4
System.out.println(Thread.currentThread().getName()+"...生产者5.0..."+this.name);//生产烤鸭1 生产烤鸭2 生产烤鸭3
flag = true;
// notifyAll();
// con.signalAll();
consumer_con.signal();
}
finally
{
lock.unlock();
}
}
public void out()// t2 t3
{
lock.lock();
try
{
while(!flag)
// try{this.wait();}catch(InterruptedException e){} //t2 t3
try{cousumer_con.await();}catch(InterruptedException e){} //t2 t3
System.out.println(Thread.currentThread().getName()+"…消费者.5.0…"+this.name);//消费烤鸭1
flag = false;
// notifyAll();
// con.signalAll();
producer_con.signal();
}
finally
{
lock.unlock();
}
}
}
class Producer implements Runnable
{
private Resource r;
Producer(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.set(“烤鸭”);
}
}
}
class Consumer implements Runnable
{
private Resource r;
Consumer(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
}
class ProducerConsumerDemo2
{
public static void main(String[] args)
{
Resource r = new Resource();
Producer pro = new Producer®;
Consumer con = new Consumer®;
Thread t0 = new Thread(pro);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
wait 和 sleep 区别?
1,wait可以指定时间也可以不指定。
sleep必须指定时间。
2,在同步中时,对cpu的执行权和锁的处理不同。
wait:释放执行权,释放锁。
sleep:释放执行权,不释放锁。
class Demo
{
void show()
{
synchronized(this)//
{
wait();//t0 t1 t2
}
}
void method()
{
synchronized(this)//t4
{
//wait();
notifyAll();
}//t4
}
}
class
{
public static void main(String[] args)
{
System.out.println(“Hello World!”);
}
}
class Demo implements Runnable
{
public void run()
{
for(int x=0; x<50; x++)
{
System.out.println(Thread.currentThread().toString()+"…"+x);
Thread.yield();
}
}
}
class JoinDemo
{
public static void main(String[] args) throws Exception
{
Demo d = new Demo();
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();
t2.start();
// t2.setPriority(Thread.MAX_PRIORITY);
// t1.join();//t1线程要申请加入进来,运行。临时加入一个线程运算时可以使用join方法。
for(int x=0; x<50; x++)
{
// System.out.println(Thread.currentThread()+"…"+x);
}
}
}
package src;
/*
多线程总结:
1,进程和线程的概念。
|–进程:
|–线程:
2,jvm中的多线程体现。
|–主线程,垃圾回收线程,自定义线程。以及他们运行的代码的位置。
3,什么时候使用多线程,多线程的好处是什么?创建线程的目的?
|–当需要多部分代码同时执行的时候,可以使用。
4,创建线程的两种方式。★★★★★
|–继承Thread
|–步骤
|–实现Runnable
|–步骤
|–两种方式的区别?
5,线程的5种状态。
对于执行资格和执行权在状态中的具体特点。
|–被创建:
|–运行:
|–冻结:
|–临时阻塞:
|–消亡:
6,线程的安全问题。★★★★★
|–安全问题的原因:
|–解决的思想:
|–解决的体现:synchronized
|–同步的前提:但是加上同步还出现安全问题,就需要用前提来思考。
|–同步的两种表现方法和区别:
|–同步的好处和弊端:
|–单例的懒汉式。
|–死锁。
7,线程间的通信。等待/唤醒机制。
|–概念:多个线程,不同任务,处理同一资源。
|–等待唤醒机制。使用了锁上的 wait notify notifyAll. ★★★★★
|–生产者/消费者的问题。并多生产和多消费的问题。 while判断标记。用notifyAll唤醒对方。 ★★★★★
|–JDK1.5以后出现了更好的方案,★★★
Lock接口替代了synchronized
Condition接口替代了Object中的监视方法,并将监视器方法封装成了Condition
和以前不同的是,以前一个锁上只能有一组监视器方法。现在,一个Lock锁上可以多组监视器方法对象。
可以实现一组负责生产者,一组负责消费者。
|–wait和sleep的区别。★★★★★
8,停止线程的方式。
|–原理:
|–表现:–中断。
9,线程常见的一些方法。
|–setDaemon()
|–join();
|–优先级
|–yield();
|–在开发时,可以使用匿名内部类来完成局部的路径开辟。
class
{
public static void main(String[] args)
{
System.out.println(“Hello World!”);
}
}
*/
/class Test implements Runnable
{
public void run(Thread t)
{}
}/
//如果错误 错误发生在哪一行?错误在第一行,应该被abstract修饰
class ThreadTest
{
public static void main(String[] args)
{
new Thread(new Runnable()
{
public void run()
{
System.out.println("runnable run");
}
})
{
public void run()
{
System.out.println("subThread run");
}
}.start();
/*
new Thread()
{
public void run()
{
for(int x=0; x<50; x++)
{
System.out.println(Thread.currentThread().getName()+"....x="+x);
}
}
}.start();
for(int x=0; x<50; x++)
{
System.out.println(Thread.currentThread().getName()+"....y="+x);
}
Runnable r = new Runnable()
{
public void run()
{
for(int x=0; x<50; x++)
{
System.out.println(Thread.currentThread().getName()+"....z="+x);
}
}
};
new Thread(r).start();
*/
}
}
String类已经覆盖了equals方法
比较的只是内容
package cn.itcast.p1.string.demo;
public class StringDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
* String类的特点:
* 字符串对象一旦被初始化就不会被改变。
*
*/
stringDemo2();
}
public static void stringDemo2() {
// TODO Auto-generated method stub
String s = "abc";//创建一个字符串对象在常量池中。
String s1 = new String("abc");//创建两个对象一个new一个字符串对象在堆内存中。
System.out.println(s==s1);//false
System.out.println(s.equals(s1));
//string类中的equals复写Object中的equals建立了string类自己的判断字符串对象是否相同的依据。
//其实就是比较字符串内容。
// System.out.println(“s=”+s);
// System.out.println(“s1=”+s1);
}
/**
* 演示字符串定义的第一种方式,并明确字符串常量池的特点.
* 池中没有就建立,池中有,直接用。
*/
private static void stringDemo1() {
String s = "abc";//"abc"存储在字符串常量池中。
// s = “nba”;
String s1 = “abc”;
System.out.println(s==s1);//true?
// System.out.println(“s=”+s);
}
}
package cn.itcast.p1.string.demo;
public class StringConstructorDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
* 将字节数组或者字符数组转成字符串可以通过String类的构造函数完成。
*/
stringConstructorDemo2();
}
private static void stringConstructorDemo2() {
char[] arr = {'w','a','p','q','x'};
String s = new String(arr,1,3);//输出//apq arr,第几个元素开始,长度为几
System.out.println("s="+s);
}
public static void stringConstructorDemo() {
String s = new String();//等效于String s = ""; 不等效String s = null;
byte[] arr = {97,66,67,68};
String s1 = new String(arr);
System.out.println("s1="+s1);
}
trim();去掉前后空白
package cn.itcast.p1.string.demo;
public class StringMethodDemo {
/**
* @param args
*/
public static void main(String[] args) {
/*
* 按照面向对象的思想对字符串进行功能分类。
* "abcd"
*
* 1,获取:
* 1.1 获取字符串中字符的个数(长度).
* int length();
* 1.2 根据位置获取字符。
* char charAt(int index);
* 1.3 根据字符获取在字符串中的第一次出现的位置.
* int indexOf(int ch)
* int indexOf(int ch,int fromIndex):从指定位置进行ch的查找第一次出现位置
* int indexOf(String str);
* int indexOf(String str,int fromIndex);
* 根据字符串获取在字符串中的第一次出现的位置.
* int lastIndexOf(int ch)
* int lastIndexOf(int ch,int fromIndex):从指定位置进行ch的查找第一次出现位置
* int lastIndexOf(String str);
* int lastIndexOf(String str,int fromIndex);
* 1.4 获取字符串中一部分字符串。也叫子串.
* String substring(int beginIndex, int endIndex)//包含begin 不包含end 。
* String substring(int beginIndex);
*
*
*
* 2,转换。
* 2.1 将字符串变成字符串数组(字符串的切割)
* String[] split(String regex):涉及到正则表达式.
* 2.2 将字符串变成字符数组。
* char[] toCharArray();
* 2.3 将字符串变成字节数组。
* byte[] getBytes();
* 2.4 将字符串中的字母转成大小写。
* String toUpperCase():大写
* String toLowerCase():小写
* 2.5 将字符串中的内容进行替换
* String replace(char oldch,char newch);
* String replace(String s1,String s2);
* 2.6 将字符串两端的空格去除。
* String trim();
* 2.7 将字符串进行连接 。
* String concat(string);
*
* 3,判断
* 3.1 两个字符串内容是否相同啊?
* boolean equals(Object obj);
* boolean equalsIgnoreCase(string str);忽略大写比较字符串内容。
* 3.2 字符串中是否包含指定字符串?
* boolean contains(string str);
* 3.3 字符串是否以指定字符串开头。是否以指定字符串结尾。
* boolean startsWith(string);
* boolean endsWith(string);
*
* 4,比较。
*
*/
stringMethodDemo_4();
// System.out.println(“abc”.concat(“kk”));
// System.out.println(“abc”+“kk”);
// System.out.println(String.valueOf(4)+1);
// System.out.println(""+4+1);
}
private static void stringMethodDemo_4() {
System.out.println("abc".compareTo("aqz"));
}
private static void stringMethodDemo_3() {
String s = "abc";
System.out.println(s.equals("ABC".toLowerCase()));
System.out.println(s.equalsIgnoreCase("ABC"));
System.out.println(s.contains("cc"));
String str = "ArrayDemo.java";
System.out.println(str.startsWith("Array"));
System.out.println(str.endsWith(".java"));
System.out.println(str.contains("Demo"));
}
private static void stringMethodDemo_2() {
String s = "张三,李四,王五";
String[] arr = s.split(",");
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
char[] chs = s.toCharArray();
for (int i = 0; i < chs.length; i++) {
System.out.println(chs[i]);
}
s = "ab你";
byte[] bytes = s.getBytes();
for (int i = 0; i < bytes.length; i++) {
System.out.println(bytes[i]);
}
System.out.println("Abc".toUpperCase());
String s1 = "java";
String s2 = s1.replace('q', 'z');
System.out.println(s1==s2);//true
System.out.println("-"+" ab c ".trim()+"-");
}
private static void stringMethodDemo_1() {
String s = "abcdae";
System.out.println("length:"+s.length());//6
System.out.println("char:"+s.charAt(2));//c//StringIndexOutOfBoundsException
System.out.println("index:"+s.indexOf('k'));//0//-1 我们可以根据-1,来判断该字符或者字符串是否存在。
System.out.println("lastIndex:"+s.lastIndexOf('a'));//4
System.out.println("substring:"+s.substring(2,4));
}
}
package cn.itcast.p2.stringbuffer.demo;
public class StringBufferDemo {
/**
* @param args
*/
public static void main(String[] args) {
/*
* StringBuffer:就是字符串缓冲区。
* 用于存储数据的容器。
* 特点:
* 1,长度是可变的。
* 2,可以存储不同类型数据。
* 3,最终要转成字符串进行使用。
* 4,可以对字符串进行修改。
*
*
* 既然是一个容器对象。应该具备什么功能呢?
* 1,添加:
* StringBuffer append(data);
* StringBuffer insert(index,data);
* 2,删除:
* StringBuffer delete(start,end):包含头,不包含尾。
* StringBuffer deleteCharAt(int index):删除指定位置的元素
* 3,查找:
* char charAt(index);
* int indexOf(string);
* int lastIndexOf(string);
* 4,修改:
* StringBuffer replace(start,end,string);
* void setCharAt(index,char);
*
* 增删改查 C(create)U(update)R(read)D(delete)
*
*
*
*/
bufferMethodDemo_2();
}
private static void bufferMethodDemo_2() {
StringBuffer sb = new StringBuffer("abce");
// sb.delete(1, 3);//ae
//清空缓冲区。
// sb.delete(0,sb.length());
// sb = new StringBuffer();
// sb.replace(1, 3, “nba”);
// sb.setCharAt(2, ‘q’);
// sb.setLength(10);
// System.out.println(“sb:”+sb);
// System.out.println(“len:”+sb.length());
System.out.println(sb.reverse());
}
private static void bufferMethodDemo_1() {
StringBuffer sb = new StringBuffer("abce");
// sb.append(“xixi”);
sb.insert(2, “qq”);
System.out.println(sb.toString());
}
public static void bufferMethodDemo(){
//创建缓冲区对象。
StringBuffer sb = new StringBuffer();
sb.append(4).append(false);//.append("haha");
sb.insert(1, "haha");
// sb.append(true);
System.out.println(sb);
}
}
append(data);
默认16个字符–缓冲区
reverse();反转,头尾互调
for(int x=0,y=arr.length-1;x
swap(x,y);
}
把整数变成字符串
valueof() 或者把一个整数和一个空字符串相连接—————— +
package cn.itcast.p2.stringbuffer.demo;
public class StringBuilderDemo {
/**
* @param args
*/
public static void main(String[] args) {
/*
* jdk1.5以后出现了功能和StringBuffer一模一样的对象。就是StringBuilder
*
* 不同的是:
* StringBuffer是线程同步的。通常用于多线程。
* StringBuilder是线程不同步的。通常用于单线程。 它的出现提高效率。
*
* jdk升级:
* 1,简化书写。
* 2,提高效率。
* 3,增加安全性。
*/
}
}
/*
class StringBuffer jdk1.0
{
object lock;
public StirngBuffer append(int x)
{
synchronized(lock)
{
}
}
public synchronized StringBuffer delete(int start,int end)
{
synchronized(lock)
{
}
}
}
*/
package cn.itcast.p2.stringbuffer.test;
public class StringBuilderTest {
/**
* @param args
*/
public static void main(String[] args) {
int[] arr = {3,1,5,3,8};
String s = arrayToString_2(arr);
System.out.println(s);
}
public static String arrayToString_2(int[] arr){
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < arr.length; i++) {
if(i!=arr.length-1)
sb.append(arr[i]+", ");
else
sb.append(arr[i]+"]");
}
return sb.toString();
}
/**
* 将一个int数组变成字符串。
*/
public static String arrayToString(int[] arr){
String str = "[";
for (int i = 0; i < arr.length; i++) {
if(i!=arr.length-1)
str+=arr[i]+", ";
else
str+=arr[i]+"]";
}
return str;
}
}
package cn.itcast.p2.wrapper.demo;
public class WrapperDemo {
/**
* @param args
*/
public static void main(String[] args) {
/*
* 基本数据类型对象包装类。
* 为了方便操作基本数据类型值,将其封装成了对象,在对象中定义了属性和行为丰富了该数据的操作。
* 用于描述该对象的类就称为基本数据类型对象包装类。
*
* byte Byte
* short Short
* int Integer
* long Long
* float Float
* double Double
* char Character
* boolean Boolean
*
* 该包装对象主要用基本类型和字符串之间的转换。
*
* 基本类型--->字符串
* 1,基本类型数值+""
* 2,用String类中的静态方法valueOf(基本类型数值);
* 3,用Integer的静态方法valueOf(基本类型数值);
*
* 字符串--->基本类型
* 1,使用包装类中的静态方法 xxx parseXxx("xxx类型的字符串");*****
* int parseInt("intstring");
* long parseLong("longstring");
* boolean parseBoolean("booleanstring");
* 只有Character没有parse方法
* 2,如果字符串被Integer进行对象的封装。
* 可使用另一个非静态的方法,intValue();
* 将一个Integer对象转成基本数据类型值。
*
*
*/
// System.out.println(Integer.MAX_VALUE);
// System.out.println(Integer.toBinaryString(-6));
// int num = 4;
// Integer i = new Integer(5);
// int x = Integer.parseInt(“123”);
// System.out.println(Integer.parseInt(“123”)+1);
// Integer i = new Integer(“123”);
// System.out.println(i.intValue());
/*
* 整数具备不同的进制体现。
*
* 十进制-->其他进制。
* toBinaryString
* toOctalString
* toHexString
*
* 其他进制-->十进制。
* parseInt("string",radix)
*
*/
// 十进制–>其他进制。
System.out.println(Integer.toBinaryString(60));
System.out.println(Integer.toOctalString(60));
System.out.println(Integer.toHexString(60));
// System.out.println(Integer.toString(60,16));
// 其他进制–>十进制。
// System.out.println(Integer.parseInt(“3c”,16));
Integer a = new Integer("89");
Integer b = new Integer(300);
System.out.println(a==b);
System.out.println(a.equals(b));
// System.out.println(3>3);
System.out.println(a.compareTo(b));
}
}
Integer i=null; //Integer i=new Integer(null);
i=i+6; NullPointerExeption
//i=new Integer(i.intValue()+6) NullPointerExeption
package cn.itcast.p2.wrapper.test;
import java.util.Arrays;
/*
*/
public class WrapperTest {
private static final String SPACE_SEPARATOR = " ";
/**
* @param args
*/
public static void main(String[] args) {
String numStr = "20 78 9 -7 88 36 29";
System.out.println(numStr);
numStr = sortStringNumber(numStr);
System.out.println(numStr);
}
/**
*
* @param numStr
* @return
*/
public static String sortStringNumber(String numStr) {
//1,将字符串变成字符串数组。
String[] str_arr = stringToArray(numStr);
//2,将字符串数组变成int数组。
int[] num_arr = toIntArray(str_arr);
//3,对int数组排序。
mySortArray(num_arr);
//4,将排序后的int数组变成字符串。
String temp = arrayToString(num_arr);
return temp;
}
public static String arrayToString(int[] num_arr) {
StringBuilder sb = new StringBuilder();
for(int x = 0; x
}
for (int i=0;i
for (int y=0;y
if (arr1[y] > arr1[y + 1])
{
int temp=0;
temp=arr1[y];
arr1[y]=arr1[y+1];
arr1[y+1]=temp;
}
}
}
集合框架!!!!!!!!!!!!!!!!!!!!!!
集合类的由来:
对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定。
就使用集合容器进行存储。
集合特点:
1,用于存储对象的容器。
2,集合的长度是可变的。
3,集合中不可以存储基本数据类型值。
集合容器因为内部的数据结构不同,有多种具体容器。
不断的向上抽取,就形成了集合框架。
框架的顶层Collection接口:
Collection的常见方法:
1,添加。
boolean add(Object obj):
boolean addAll(Collection coll):
2,删除。
boolean remove(object obj):
boolean removeAll(Collection coll);
void clear();
3,判断:
boolean contains(object obj):
boolean containsAll(Colllection coll);
boolean isEmpty():判断集合中是否有元素。
4,获取:
int size():
Iterator iterator():取出元素的方式:迭代器。
该对象必须依赖于具体容器,因为每一个容器的数据结构都不同。
所以该迭代器对象是在容器中进行内部实现的。
对于使用容器者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器的对象即可,
也就是iterator方法。
Iterator接口就是对所有的Collection容器进行元素取出的公共接口。
其实就是抓娃娃游戏机中的夹子!
5,其他:
boolean retainAll(Collection coll);取交集。
Object[] toArray():将集合转成数组。
Collection
|–List:有序(存入和取出的顺序一致),元素都有索引(角标),元素可以重复。
|–Set:元素不能重复,无序。
package cn.itcast.p3.collection.demo;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo {
/**
* @param args
*/
public static void main(String[] args) {
Collection coll = new ArrayList();
// show(coll);
Collection c1 = new ArrayList();
Collection c2 = new ArrayList();
show(c1,c2);
}
public static void show(Collection c1,Collection c2){
//给c1添加元素。
c1.add("abc1");
c1.add("abc2");
c1.add("abc3");
c1.add("abc4");
//给c2添加元素。
c2.add("abc1");
c2.add("abc2");
c2.add("abc3");
c2.add("abc4");
c2.add("abc5");
System.out.println("c1:"+c1);
System.out.println("c2:"+c2);
//演示addAll
// c1.addAll(c2);//将c2中的元素添加到c1中。
//演示removeAll
// boolean b = c1.removeAll(c2);//将两个集合中的相同元素从调用removeAll的集合中删除。
// System.out.println(“removeAll:”+b);
//演示containsAll
// boolean b = c1.containsAll(c2);
// System.out.println(“containsAll:”+b);
//演示retainAll
boolean b = c1.retainAll(c2);//取交集,保留和指定的集合相同的元素,而删除不同的元素。
//和removeAll功能相反 。
System.out.println("retainAll:"+b);
System.out.println("c1:"+c1);
}
public static void show(Collection coll){
//1,添加元素。add.
coll.add("abc1");
coll.add("abc2");
coll.add("abc3");
System.out.println(coll);
//2,删除元素。remove
// coll.remove(“abc2”);//会改变集合的长度
//清空集合.
// coll.clear();
System.out.println(coll.contains("abc3"));
System.out.println(coll);
}
}
package cn.itcast.p3.collection.demo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class IteratorDemo {
/**
* @param args
*/
public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add("abc1");
coll.add("abc2");
coll.add("abc3");
coll.add("abc4");
// System.out.println(coll);
//使用了Collection中的iterator()方法。 调用集合中的迭代器方法,是为了获取集合中的迭代器对象。
// Iterator it = coll.iterator();
// while(it.hasNext()){
// System.out.println(it.next());
// }
for(Iterator it = coll.iterator(); it.hasNext(); ){
System.out.println(it.next());
}
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());//java.util.NoSuchElementException
}
}
List:特有的常见方法:有一个共性特点就是都可以操作角标。
1,添加
void add(index,element);
void add(index,collection);
2,删除;
Object remove(index):
3,修改:
Object set(index,element);
4,获取:
Object get(index);
int indexOf(object);
int lastIndexOf(object);
List subList(from,to);
list集合是可以完成对元素的增删改查。
List:
|–Vector:内部是数组数据结构,是同步的。增删,查询都很慢!
|–ArrayList:内部是数组数据结构,是不同步的。替代了Vector。查询的速度快。
|–LinkedList:内部是链表数据结构,是不同步的。增删元素的速度很快。
LinkedList:
addFirst();
addLast():
jdk1.6
offerFirst();
offetLast();
getFirst();.//获取但不移除,如果链表为空,抛出NoSuchElementException.
getLast();
jdk1.6
peekFirst();//获取但不移除,如果链表为空,返回null.
peekLast():
removeFirst();//获取并移除,如果链表为空,抛出NoSuchElementException.
removeLast();
jdk1.6
pollFirst();//获取并移除,如果链表为空,返回null.
pollLast();
package cn.itcast.p4.list.demo;
import java.util.ArrayList;
import java.util.List;
public class ListDemo {
/**
* @param args
*/
public static void main(String[] args) {
List list = new ArrayList();
show(list);
}
public static void show(List list) {
//添加元素
list.add("abc1");
list.add("abc2");
list.add("abc3");
System.out.println(list);
//插入元素。
// list.add(1,“abc9”);
//删除元素。
// System.out.println(“remove:”+list.remove(2));
//修改元素。
// System.out.println(“set:”+list.set(1, “abc8”));
//获取元素。
// System.out.println(“get:”+list.get(0));
//获取子列表。
// System.out.println(“sublist:”+list.subList(1, 2));
System.out.println(list);
}
}
package cn.itcast.p4.list.demo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class ListDemo2 {
/**
* @param args
*/
public static void main(String[] args) {
List list = new ArrayList();
// show(list);
list.add("abc1");
list.add("abc2");
list.add("abc3");
System.out.println("list:"+list);
ListIterator it = list.listIterator();//获取列表迭代器对象
//它可以实现在迭代过程中完成对元素的增删改查。
//注意:只有list集合具备该迭代功能.
while(it.hasNext()){
Object obj = it.next();
if(obj.equals("abc2")){
it.set("abc9");
}
}
// System.out.println(“hasNext:”+it.hasNext());
// System.out.println(“hasPrevious:”+it.hasPrevious());
while(it.hasPrevious()){
System.out.println("previous:"+it.previous());
}
System.out.println("list:"+list);
/*Iterator it = list.iterator();
while(it.hasNext()){
Object obj = it.next();//java.util.ConcurrentModificationException
//在迭代器过程中,不要使用集合操作元素,容易出现异常。
//可以使用Iterator接口的子接口ListIterator来完成在迭代中对元素进行更多的操作。
if(obj.equals("abc2")){
list.add("abc9");
}
else
System.out.println("next:"+obj);
}
System.out.println(list);
*/
}
public static void show(List list) {
list.add("abc1");
list.add("abc2");
list.add("abc3");
list.add("abc4");
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println("next:"+it.next());
}
//list特有的取出元素的方式之一。
for(int x=0; x
}
package cn.itcast.p2.linkedlist.demo;
import java.util.Iterator;
import java.util.LinkedList;
public class LinkedListDemo {
/**
* @param args
*/
public static void main(String[] args) {
LinkedList link = new LinkedList();
link.addFirst("abc1");
link.addFirst("abc2");
link.addFirst("abc3");
link.addFirst("abc4");
// System.out.println(link);
// System.out.println(link.getFirst());//获取第一个但不删除。
// System.out.println(link.getFirst());
// System.out.println(link.removeFirst());//获取元素但是会删除。
// System.out.println(link.removeFirst());
while(!link.isEmpty()){
System.out.println(link.removeLast());
}
System.out.println(link);
// Iterator it = link.iterator();
// while(it.hasNext()){
// System.out.println(it.next());
// }
}
}
用LinkedList 模拟队列
先进先出
package cn.itcast.p2.linkedlist.test;
import java.util.LinkedList;
public class DuiLie {
private LinkedList link;
public DuiLie() {
link = new LinkedList();
}
/**
* 队列的添加元素的功能。
*/
public void myAdd(Object obj) {
link.addLast(obj);
}
public Object myGet() {
return link.removeFirst();
}
public boolean isNull() {
return link.isEmpty();
}
}
package cn.itcast.p2.linkedlist.test;
import java.util.ArrayList;
/*
public class LinkedTest {
/**
* @param args
*/
public static void main(String[] args) {
DuiLie dl = new DuiLie();
dl.myAdd("abc1");
dl.myAdd("abc2");
dl.myAdd("abc3");
dl.myAdd("abc4");
while(!dl.isNull()){
System.out.println(dl.myGet());
}
}
}
作业:
1,自己去查文档演示Vector中的elements()方法。
2,LinkedList中的,addFirst addLast getFirst,getLast removeFirst removeLast。
3,既然集合是存储对象的,请定义ArryaList集合,并存储Person对象。如new Person(“lisi”,20);
并取出。将姓名和年龄打印出来。
ArrayList
package cn.itcast.p3.arraylist.test;
import java.util.ArrayList;
import java.util.Iterator;
import cn.itcast.p.bean.Person;
public class ArrayListTest {
/**
* @param args
*/
public static void main(String[] args) {
Person p1 = new Person("lisi1",21);
ArrayList al = new ArrayList();
al.add(p1);
al.add(new Person("lisi2",22));
al.add(new Person("lisi3",23));
al.add(new Person("lisi4",24));
Iterator it = al.iterator();
while(it.hasNext()){
// System.out.println(((Person)it.next()).getName()+"::"+((Person)it.next()).getAge());
Person p = (Person) it.next();
System.out.println(p.getName()+"–"+p.getAge());
}
// al.add(5);//al.add(new Integer(5));
}
}
package cn.itcast.p3.arraylist.test;
import java.util.ArrayList;
import java.util.Iterator;
import cn.itcast.p.bean.Person;
/*
public class ArrayListTest2 {
/**
* @param args
*/
public static void main(String[] args) {
// demo();
// singleDemo();
ArrayList al = new ArrayList();
al.add(new Person("lisi1",21));
al.add(new Person("lisi2",22));
al.add(new Person("lisi3",23));
al.add(new Person("lisi4",24));
al.add(new Person("lisi2",22));
al.add(new Person("lisi3",23));
System.out.println(al);
al = getSingleElement(al);
System.out.println(al.remove(new Person("lisi2",22)));
System.out.println(al);
}
/**
*
*/
public static void singleDemo() {
ArrayList al = new ArrayList();
al.add("abc1");
al.add("abc2");
al.add("abc2");
al.add("abc1");
al.add("abc");
System.out.println(al);
al = getSingleElement(al);
System.out.println(al);
}
public static ArrayList getSingleElement(ArrayList al) {
//1,定义一个临时容器。
ArrayList temp = new ArrayList();
//2,迭代al集合。
Iterator it = al.iterator();
while(it.hasNext()){
Object obj = it.next();
//3,判断被迭代到的元素是否在临时容器存在。
if(!temp.contains(obj)){
temp.add(obj);
}
}
return temp;
}
/**
*
*/
public static void demo() {
// al.add(5);//al.add(new Integer(5));
}
}
Set:元素不可以重复,是无序。
Set接口中的方法和Collection一致。
|–HashSet: 内部数据结构是哈希表 ,是不同步的。
如何保证该集合的元素唯一性呢?
是通过对象的hashCode和equals方法来完成对象唯一性的。
如果对象的hashCode值不同,那么不用判断equals方法,就直接存储到哈希表中。
如果对象的hashCode值相同,那么要再次判断对象的equals方法是否为true。
如果为true,视为相同元素,不存。如果为false,那么视为不同元素,就进行存储。
记住:如果元素要存储到HashSet集合中,必须覆盖hashCode方法和equals方法。
一般情况下,如果定义的类会产生很多对象,比如人,学生,书,通常都需要覆盖equals,hashCode方法。
建立对象判断是否相同的依据。
package cn.itcast.p4.hashset.test;
import java.util.HashSet;
import java.util.Iterator;
import cn.itcast.p.bean.Person;
/*
往hashSet集合中存储Person对象。如果姓名和年龄相同,视为同一个人。视为相同元素。
*/
public class HashSetTest {
/**
@param args
*/
public static void main(String[] args) {
HashSet hs = new HashSet();
/*
*/
hs.add(new Person(“lisi4”,24));
hs.add(new Person(“lisi7”,27));
hs.add(new Person(“lisi1”,21));
hs.add(new Person(“lisi9”,29));
hs.add(new Person(“lisi7”,27));
Iterator it = hs.iterator();
while(it.hasNext()){
Person p = (Person)it.next();
System.out.println§;
// System.out.println(p.getName()+"…"+p.getAge());
}
}
}
package cn.itcast.p.bean;
public class Person /extends Object/ implements Comparable {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
复写!!!!!!!
@Override
public int hashCode() {
// System.out.println(this+"…hashCode");
return name.hashCode()+age*27;
// return 100;
}
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(!(obj instanceof Person))
throw new ClassCastException("类型错误");
// System.out.println(this+"…equals…"+obj);
Person p = (Person)obj;
return this.name.equals(p.name) && this.age == p.age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString(){
return name+":"+age;
}
@Override
public int compareTo(Object o) {
Person p = (Person)o;
int temp = this.age-p.age;
return temp==0?this.name.compareTo(p.name):temp;
// int temp = this.name.compareTo(p.name);
// return temp==0?this.age-p.age:temp;
/*
if(this.age>p.age)
return 1;
if(this.age
}
package cn.itcast.p4.hashset.demo;
import java.util.HashSet;
import java.util.Iterator;
public class HashSetDemo {
/**
* @param args
*/
public static void main(String[] args) {
HashSet hs = new HashSet();
hs.add("hehe");
// hs.add(“heihei”);
hs.add(“hahah”);
hs.add(“xixii”);
hs.add(“hehe”);
Iterator it = hs.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
输出无序,没有重复
LinkedHashSet 输出有序按插入顺序 遍历时 按元素的添加顺序访问
迭代访问时效率比HashSet好 插入性能稍微次
|--TreeSet:可以对Set集合中的元素进行排序。是不同步的。
判断元素唯一性的方式:就是根据比较方法的返回结果是否是0,是0,就是相同元素,不存。
TreeSet对元素进行排序的方式一:
让元素自身具备比较功能,元素就需要实现Comparable接口。覆盖compareTo方法。
如果不要按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序。怎么办?
可以使用TreeSet集合第二种排序方式二:
让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。
将该类对象作为参数传递给TreeSet集合的构造函数。
if(this.hashCode()== obj.hashCode() && this.equals(obj))
package cn.itcast.p5.comparator;
import java.util.Comparator;
public class ComparatorByLength implements Comparator {
@Override
public int compare(Object o1, Object o2) {
String s1 = (String)o1;
String s2 = (String)o2;
int temp = s1.length()-s2.length();
return temp==0? s1.compareTo(s2): temp;
}
}
package cn.itcast.p5.comparator;
import java.util.Comparator;
import cn.itcast.p.bean.Person;
/**
创建了一个根据Person类的name进行排序的比较器。(年龄)
*/
public class ComparatorByName implements Comparator {
@Override
public int compare(Object o1, Object o2) {
Person p1 = (Person)o1;
Person p2 = (Person)o2;
int temp = p1.getName().compareTo(p2.getName());
return temp==0?p1.getAge()-p2.getAge(): temp;
// return 1;//有序。
}
}
package cn.itcast.p5.treeset.demo;
import java.util.Iterator;
import java.util.TreeSet;
import cn.itcast.p.bean.Person;
import cn.itcast.p5.comparator.ComparatorByName;
public class TreeSetDemo {
/**
* @param args
*/
public static void main(String[] args) {
TreeSet ts = new TreeSet(new ComparatorByName());
//比较器的使用
/*
* 以Person对象年龄进行从小到大的排序。
*
*/
ts.add(new Person("zhangsan",28));
ts.add(new Person("lisi",21));
ts.add(new Person("zhouqi",29));
ts.add(new Person("zhaoliu",25));
ts.add(new Person("wangu",24));
Iterator it = ts.iterator();
while(it.hasNext()){
Person p = (Person)it.next();
System.out.println(p.getName()+":"+p.getAge());
}
}
/**
*
*/
public static void demo1() {
TreeSet ts = new TreeSet();
ts.add("abc");
ts.add("zaa");
ts.add("aa");
ts.add("nba");
ts.add("cba");
Iterator it = ts.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
哈希表确定元素是否相同
1,判断的是两个元素的哈希值是否相同。
如果相同,在判断两个对象的内容是否相同。
2,判断哈希值相同,其实判断的是对象的hashCode的方法。判断内容相同,用的是equals方法。
注意:如果哈希值不同,是不需要判断equals。
泛型:
jdk1.5出现的安全机制。
好处:
1,将运行时期的问题ClassCastException转到了编译时期。
2,避免了强制转换的麻烦。
<>:什么时候用?当操作的引用数据类型不确定的时候。就使用<>。将要操作的引用数据类型传入即可.
其实<>就是一个用于接收具体引用数据类型的参数范围。
在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型 。
泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。
运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除。
为什么擦除呢?因为为了兼容运行的类加载器。
泛型的补偿:在运行时,通过获取元素的类型进行转换动作。不用使用者在强制转换了。
泛型的通配符:? 未知类型。
泛型的限定:
? extends E: 接收E类型或者E的子类型对象。上限
一般存储对象的时候用。比如 添加元素 addAll.
? super E: 接收E类型或者E的父类型对象。 下限。
一般取出对象的时候用。比如比较器。*/
//在jdk1.5后,使用泛型来接收类中要操作的引用数据类型。
//泛型类。什么时候用?当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。
/*
*/
class MyCollection{
public void add(E e){
}
public void addAll(MyCollection extends E> e){
}
}
/*
Tree(Comparator super Worker> comp);
*/
public class Tool{
private QQ q;
public QQ getObject() {
return q;
}
public void setObject(QQ object) {
this.q = object;
}
/**
* 将泛型定义在方法上。
* @param str
*/
public void show(W str){
System.out.println("show : "+str.toString());
}
public void print(QQ str){
System.out.println("print : "+str);
}
/**
* 当方法静态时,不能访问类上定义的泛型。如果静态方法使用泛型,
(实例化对象时强转错误!)
* 只能将泛型定义在方法上。
* @param obj
*/
public static void method(Y obj){
System.out.println(“method:”+obj);
}
}
===========================================================
集合的一些技巧:
需要唯一吗?
需要:Set
需要制定顺序:
需要: TreeSet
不需要:HashSet
但是想要一个和存储一致的顺序(有序):LinkedHashSet
不需要:List
需要频繁增删吗?
需要:LinkedList
不需要:ArrayList
如何记录每一个容器的结构和所属体系呢?
看名字!
List
|–ArrayList
|–LinkedList
Set
|–HashSet
|–TreeSet
后缀名就是该集合所属的体系。
前缀名就是该集合的数据结构。
看到array:就要想到数组,就要想到查询快,有角标.
看到link:就要想到链表,就要想到增删快,就要想要 add get remove+frist last的方法
看到hash:就要想到哈希表,就要想到唯一性,就要想到元素需要覆盖hashcode方法和equals方法。
看到tree:就要想到二叉树,就要想要排序,就要想到两个接口Comparable,Comparator 。
而且通常这些常用的集合容器都是不同步的。
============================================
Map:一次添加一对元素。Collection 一次添加一个元素。
Map也称为双列集合,Collection集合称为单列集合。
其实map集合中存储的就是键值对。
map集合中必须保证键的唯一性。
常用方法:
1,添加。
value put(key,value):返回前一个和key关联的值,如果没有返回null.
2,删除。
void clear():清空map集合。
value remove(key):根据指定的key翻出这个键值对。
3,判断。
boolean containsKey(key):
boolean containsValue(value):
boolean isEmpty();
4,获取。
value get(key):通过键获取值,如果没有该键返回null。
当然可以通过返回null,来判断是否包含指定键。
int size(): 获取键值对的个数。
Map常用的子类:
|–Hashtable :内部结构是哈希表,是同步的。不允许null作为键,null作为值。
|–Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合。
|–HashMap : 内部结构是哈希表,不是同步的。允许null作为键,null作 为值。
|–TreeMap : 内部结构是二叉树,不是同步的。可以对Map集合中的键进行排序。
HashMap把Hashtable的contains方法去掉了。改成containsvalue和containsKey。
package cn.itcast.p6.map.demo;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapDemo {
public static void main(String[] args) {
Map map = new HashMap();
method_2(map);
}
public static void method_2(Map map){
map.put(8,"zhaoliu");
map.put(2,"zhaoliu");
map.put(7,"xiaoqiang");
map.put(6,"wangcai");
Collection values = map.values();
Iterator it2 = values.iterator();
while(it2.hasNext()){
System.out.println(it2.next());
}
迭代方法2
/*
* 通过Map转成set就可以迭代。
* 找到了另一个方法。entrySet。返回此地图中包含的映射的Set视图
该方法将键和值的映射关系作为对象存储到了Set集合中,而这个映射关系的类型就是Map.Entry类型(结婚证)
*
*
*/
Set
Iterator> it = entrySet.iterator();
while(it.hasNext()){
Map.Entry me = it.next();
Integer key = me.getKey();
String value = me.getValue();
System.out.println(key+"::::"+value);
}
迭代方法3
//取出map中的所有元素。 返回此地图中包含的键的Set视图。
//原理,通过keySet方法获取map中所有的键所在的Set集合,在通过Set的迭代器获取到每一个键,
//在对每一个键通过map集合的get方法获取其对应的值即可。
/*
Set keySet = map.keySet();
Iterator it = keySet.iterator();
while(it.hasNext()){
Integer key = it.next();
String value = map.get(key);
System.out.println(key+":"+value);
}
*/
}
public static void method(Map
// 添加元素。
System.out.println(map.put(8, "wangcai"));//null
System.out.println(map.put(8, "xiaoqiang"));//wangcai 存相同键,值会覆盖。
map.put(2,"zhangsan");
map.put(7,"zhaoliu");
//删除。
// System.out.println(“remove:”+map.remove(2));
//判断。
// System.out.println(“containskey:”+map.containsKey(7));
//获取。
System.out.println("get:"+map.get(6));
System.out.println(map);
Outer.Inner.show();
}
}
interface MyMap{
public static interface MyEntry{//内部接口
void get();
}
}
class MyDemo implements MyMap.MyEntry{
public void get(){}
}
class Outer{
static class Inner{
static void show(){}
}
}
package cn.itcast.p7.hashmap.demo;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import cn.itcast.p2.bean.Student;
public class HashMapDemo {
/**
* @param args
*/
public static void main(String[] args) {
/*
* 将学生对象和学生的归属地通过键与值存储到map集合中。
*
*/
HashMap hm = new HashMap();
hm.put(new Student("lisi",38),"北京");
hm.put(new Student("zhaoliu",24),"上海");
hm.put(new Student("xiaoqiang",31),"沈阳");
hm.put(new Student("wangcai",28),"大连");
hm.put(new Student("zhaoliu",24),"铁岭");
// Set keySet = hm.keySet();
// Iterator it = keySet.iterator();
Iterator it = hm.keySet().iterator();
while(it.hasNext()){
Student key = it.next();
String value = hm.get(key);
System.out.println(key.getName()+":"+key.getAge()+"---"+value);
}
}
}
package cn.itcast.p8.treemap.demo;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import cn.itcast.p2.bean.Student;
import cn.itcast.p3.comparator.ComparatorByName;
public class TreeMapDemo {
/**
* @param args
*/
public static void main(String[] args) {
TreeMap tm = new TreeMap(new ComparatorByName());
tm.put(new Student("lisi",38),"北京");
tm.put(new Student("zhaoliu",24),"上海");
tm.put(new Student("xiaoqiang",31),"沈阳");
tm.put(new Student("wangcai",28),"大连");
tm.put(new Student("zhaoliu",24),"铁岭");
Iterator> it = tm.entrySet().iterator();
while(it.hasNext()){
Map.Entry me = it.next();
Student key = me.getKey();
String value = me.getValue();
System.out.println(key.getName()+":"+key.getAge()+"---"+value);
}
}
}
package cn.itcast.p1.map.demo;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapDemo {
/**
* @param args
*/
public static void main(String[] args) {
File f= null;
HashMap hm = new LinkedHashMap();//怎么输入怎么输出
hm.put(7, "zhouqi");
hm.put(3, "zhangsan");
hm.put(1, "qianyi");
hm.put(5, "wangwu");
Iterator> it = hm.entrySet().iterator();
while(it.hasNext()){
Map.Entry me = it.next();
Integer key = me.getKey();
String value = me.getValue();
System.out.println(key+":"+value);
}
}
}
package cn.itcast.p1.map.test;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
/*
*/
public class MapTest {
/**
* @param args
*/
public static void main(String[] args) {
String str = "fdg+avAdc bs5dDa9c-dfs";
String s = getCharCount(str);
System.out.println(s);
}
public static String getCharCount(String str) {
//将字符串变成字符数组
char[] chs = str.toCharArray();
//定义map集合表。
Map map = new TreeMap();
for (int i = 0; i < chs.length; i++) {
if(!(chs[i]>='a' && chs[i]<='z' || chs[i]>='A' && chs[i]<='Z'))
// if(!(Character.toLowerCase(chs[i])>=‘a’ && Character.toLowerCase(chs[i])<=‘z’))
continue;
//将数组中的字母作为键去查map表。
Integer value = map.get(chs[i]);
int count = 1;
//判断值是否为null.
if(value!=null){
count = value+1;
}
// count++;
map.put(chs[i], count);
/*
if(value==null){
map.put(chs[i], 1);
}else{
map.put(chs[i], value+1);
}
*/
}
return mapToString(map);
}
private static String mapToString(Map map) {
StringBuilder sb = new StringBuilder();
Iterator it = map.keySet().iterator();
while(it.hasNext()){
Character key = it.next();
Integer value = map.get(key);
sb.append(key+"("+value+")");
}
return sb.toString();
}
}
package cn.itcast.p1.map.test;
import java.util.HashMap;
import java.util.Map;
public class MapTest2 {
/**
* @param args
*/
public static void main(String[] args) {
/*
* Map在有映射关系时,可以优先考虑。
*
* 在查表法中的应用较为多见。
*/
String week = getWeek(1);
System.out.println(week);
System.out.println(getWeekByMap(week));
}
public static String getWeekByMap(String week){
Map map = new HashMap();
map.put("星期一","Mon");
map.put("星期二","Tus");
map.put("星期三","Wes");
map.put("星期日","Sun");
map.put("星期天","Sun");
return map.get(week);
}
public static String getWeek(int week){
if(week<1 || week>7)
throw new RuntimeException("没有对应的星期,请您重新输入");
String[] weeks = {"","星期一","星期二"};
return weeks[week];
}
}
List list = new ArrayList();//非同步的。
list = MyCollections.synList(list);//返回一个同步的list.
给非同步的集合加锁。
class MyCollections{
public static List synList(List list){
return new MyList(list);
}
private class MyList implements List{
private List list;
private static final Object lock = new Object();
MyList(List list){
this.list = list;
}
public boolean add(Object obj){
synchronized(lock)
{
return list.add(obj);
}
}
public boolean remove(Object obj){
synchronized(lock)
{
return list.remove(obj);
}
}
}
}
//LinkedHashMap
怎么输入怎么输出
作业:
1,自己去查文档演示Vector中的elements()方法。
2,LinkedList中的,addFirst addLast getFirst,getLast removeFirst removeLast。
3,既然集合是存储对象的,请定义ArryaList集合,并存储Person对象。如new Person(“lisi”,20);
并取出。将姓名和年龄打印出来。
类型强转要加上健壮性判断否则ClassCastException
instanceOf
二叉树怎么提高效率的--------二分查找
比较器里的equals方法?判断比较器是否相同,不咋用
Comparable 接口Person 类里实现复写compareTo方法
Comparator 比较器 class ComparatorByName implements Comparator
public int compare(Object o1,Object o2)
你还是看上面泛型下的笔记吧
泛型必须写在返回值类型前面,修饰符的后面
public static void method(W w){}
Collections.synchronizedList() 返回加锁的List
========================================================================
集合框架工具类
Collections
package cn.itcast.p2.toolclass.collections.demo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import cn.itcast.p2.comparator.ComparatorByLength;
public class CollectionsDemo {
/**
* @param args
*/
public static void main(String[] args) {
/*
* Collections:是集合框架的工具类。
* 里面的方法都是静态的。
*
*
*/
demo_4();
}
public static void demo_4() {
List list = new ArrayList();
list.add("abcde");
list.add("cba");
list.add("zhangsan");
list.add("zhaoliu");
list.add("xiaoqiang");
System.out.println(list);
// Collections.replaceAll(list, “cba”, “nba”); // set(indexOf(“cba”),“nba”);
Collections.shuffle(list); //打乱顺序
// Collections.fill(list, “cc”);//替代
System.out.println(list);
}
public static void demo_3() {
/*
TreeSet ts = new TreeSet(new Comparator(){
@Override
public int compare(String o1, String o2) {
int temp = o2.compareTo(o1);
return temp;
}
});
*/
TreeSet ts = new TreeSet(Collections.reverseOrder(new ComparatorByLength()));
ts.add("abc");
ts.add("hahaha");
ts.add("zzz");
ts.add("aa");
ts.add("cba");
System.out.println(ts);
}
public static void demo_2(){
List list = new ArrayList();
list.add("abcde");
list.add("cba");
list.add("aa");
list.add("zzz");
list.add("cba");
list.add("nbaa");
// Collections.sort(list);
System.out.println(list);
// int index = Collections.binarySearch(list, “cba”);
// System.out.println(“index=”+index);
//获取最大值。
String max = Collections.max(list,new ComparatorByLength());
System.out.println("max="+max);
}
public static void demo_1(){
List list = new ArrayList();
list.add("abcde");
list.add("cba");
list.add("aa");
list.add("zzz");
list.add("cba");
list.add("nbaa");
System.out.println(list);
//对list集合进行指定顺序的排序。
// Collections.sort(list);
// mySort(list);
// mySort(list,new ComparatorByLength());
Collections.sort(list,new ComparatorByLength());
System.out.println(list);
}
public static void mySort(List list,Comparator super T> comp){
for (int i = 0; i < list.size()-1; i++) {
for (int j = i+1; j < list.size(); j++) {
if(comp.compare(list.get(i), list.get(j))>0){
// T temp = list.get(i);
// list.set(i, list.get(j));
// list.set(j, temp);
Collections.swap(list, i, j);
}
}
}
}
public static > void mySort(List list){
for (int i = 0; i < list.size()-1; i++) {
for (int j = i+1; j < list.size(); j++) {
if(list.get(i).compareTo(list.get(j))>0){
// T temp = list.get(i);
// list.set(i, list.get(j));
// list.set(j, temp);
Collections.swap(list, i, j);//交换
}
}
}
}
}
Arrays
package cn.itcast.p3.toolclass.arrays.demo;
import java.util.Arrays;
import java.util.List;
//数组转成集合。
public class ArraysDemo {
/**
* @param args
*/
public static void main(String[] args) {
/*
* Arrays:集合框架的工具类。里面的方法都是静态的。
*
*/
// int[] arr = {3,1,5,6,3,6};
// System.out.println(Arrays.toString(arr));
demo_2();
}
public static void demo_2() {
/*
* 如果数组中的元素是对象,那么转成集合时,直接将数组中的元素作为集合中的元素进行集合存储。
*
* 如果数组中的元素是基本类型数值,那么会将该数组作为集合中的元素进行存储。
*
*/
int[] arr = {31,11,51,61};
List list = Arrays.asList(arr);
System.out.println(list); //只有一个元素
}
/**
*
*/
public static void demo_1() {
/*
* 重点:List asList(数组)将数组转成集合。
*
* 好处:可以使用集合的方法操作数组中的元素。
* 注意:数组的长度是固定的,所以对于集合的增删方法是不可以使用的
* 否则会发生UnsupportedOperationException
*
*
*/
String[] arr = {"abc","haha","xixi"};
boolean b = myContains(arr, "xixi");
System.out.println("contains:"+b);
List list = Arrays.asList(arr);
boolean b1 = list.contains("xixi");
System.out.println("list contaisn:="+b1);
// list.add(“hiahia”);//UnsupportedOperationException
System.out.println(list);
}
public static boolean myContains(String[] arr,String key){
for (int i = 0; i < arr.length; i++) {
if(arr[i].equals(key))
return true;
}
return false;
}
//toString的经典实现。
public static String myToString(int[] a){
int iMax = a.length - 1;
if (iMax == -1)
return "[]";
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {//中间省略条件判断,提高了效率。
b.append(a[i]);
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}
}
package cn.itcast.p3.toolclass.arrays.demo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ToArray {
public static void main(String[] args) {
/*
* 集合转成数组呢?
*
* 使用的就是Collection接口中的toArray方法。
*
* 集合转成数组:可以对集合中的元素操作的方法进行限定。不允许对其进行增删。
*
*
*/
List list = new ArrayList();
list.add("abc1");
list.add("abc2");
list.add("abc3");
/*
* toArray方法需要传入一个指定类型的数组。
* 长度该如何定义呢?
* 如果长度小于集合的size,那么该方法会创建一个同类型并和集合相同size的数组。
* 如果长度大于集合的size,那么该方法就会使用指定的数组,存储集合中的元素,其他位置默认为null。
*
* 所以建议,最后长度就指定为,集合的size。
*/
String[] arr = list.toArray(new String[list.size()]);
System.out.println(Arrays.toString(arr));
}
}
高级for循环
package cn.itcast.p4.news.demo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ForEachDemo {
/**
* @param args
*/
public static void main(String[] args) {
/*
* foreach语句:
* 格式:
* for(类型 变量 :Collection集合|数组)
* {
*
* }
*
* 传统for和高级for的区别?
* 传统for可以完成对语句执行很多次,因为可以定义控制循环的增量和条件。
*
* 高级for是一种简化形式。
* 它必须有被遍历的目标。该目标要是数组,要么是Collection单列集合。
*
* 对数数组的遍历如果仅仅是获取数组中的元素,可以使用高级for。
* 如果要对数组的角标进行操作建议使用传统for。
*
*/
List list =new ArrayList();
list.add("abc1");
list.add("abc2");
list.add("abc3");
for(String s : list){ //简化书写。
System.out.println(s);
}
int[] arr = {3,1,5,7,4};
for(int i : arr){
System.out.println(i);
}
//可以使用高级for遍历map集合吗?不能直接用,但是可以将map转成单列的set,就可以用了。
Map map = new HashMap();
map.put(3,"zhagsan");
map.put(1,"wangyi");
map.put(7,"wagnwu");
map.put(4,"zhagsansan");
for(Integer key : map.keySet()){
String value = map.get(key);
System.out.println(key+"::"+value);
}
for(Map.Entry me : map.entrySet()){
Integer key = me.getKey();
String value = me.getValue();
System.out.println(key+":"+value);
}
// Iterator it = list.iterator();
// while(it.hasNext()){
// System.out.println(it.next());
// }
}
}
===================================
函数的可变参数
package cn.itcast.p4.news.demo;
public class ParamterDemo {
/**
* @param args
*/
public static void main(String[] args) {
// int sum = add(4,5);
// System.out.println(“sum=”+sum);
// int sum1 = add(4,5,6);
// System.out.println(“sum1=”+sum1);
// int[] arr = {5,1,4,7,3};
// int sum = add(arr);
// System.out.println(“sum=”+sum);
// int[] arr1 = {5,1,4,7,3,9,8,7,6};
// int sum1 = add(arr1);
// System.out.println(“sum1=”+sum1);
int sum = newAdd(5,1,4,7,3);
System.out.println("sum="+sum);
int sum1 = newAdd(5,1,2,7,3,9,8,7,6);
System.out.println("sum1="+sum1);
}
/*
* 函数的可变参数。
* 其实就是一个数组,但是接收的是数组的元素。
* 自动将这些元素封装成数组。简化了调用者的书写。
*
* 注意:可变参数类型,必须定义在参数列表的结尾。
*
*/
public static int newAdd(int a,int... arr){
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum+=arr[i];
}
return sum;
// System.out.println(arr);
// return 0;
}
public static int add(int[] arr){
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum+=arr[i];
}
return sum;
}
public static int add(int a,int b){
return a+b;
}
public static int add(int a,int b,int c){
return a+b+c;
}
}
静态导入
package cn.itcast.p4.news.demo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static java.util.Collections.*;//静态导入,其实到入的是类中的静态成员。
//import static java.util.Collections.max;//静态导入,其实到入的是类中的静态成员。
import static java.lang.System.*;
public class StaticImportDemo {
/**
* @param args
*/
public static void main(String[] args) {
List list = new ArrayList();
list.add("abc3");
list.add("abc7");
list.add("abc1");
out.println(list);
sort(list);
System.out.println(list);
String max = max(list);
System.out.println("max="+max);
}
}
Properties—>Map的子类
System类
package cn.itcast.p1.otherapi;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.Set;
public class SystemDemo {
private static final String LINE_SEPARATOR = System.getProperty("line.separator");//获取换行符
/**
* @param args
*/
public static void main(String[] args) {
/*
* System:类中的方法和属性都是静态的。
*
*
* 常见方法:
* long currentTimeMillis();获取当前时间的毫秒值。
*
*/
// long l1 = 1335664696656l;//System.currentTimeMillis();
// System.out.println(l1/1000/60/60/24);//1335664696656
// code…
// long l2 = System.currentTimeMillis();
// System.out.println(l2-l1);//运行时间
System.out.println("hello-"+LINE_SEPARATOR+" world");
// demo_1();
//给系统设置一些属性信息。这些信息是全局,其他程序都可以使用。
// System.setProperty(“myclasspath”, “c:\myclass”);
}
public static void demo_1(){
//获取系统的属性信息,并存储到了Properties集合中。
/*
* properties集合中存储都是String类型的键和值。//
* 。最好使用它自己的存储和取出的方法来完成元素的操作
*/
Properties prop = System.getProperties();
Set nameSet = prop.stringPropertyNames();
for(String name : nameSet){
String value = prop.getProperty(name);
System.out.println(name+"::"+value);
}
}
}
Runtime r=Runtime.getRuntime();//Runtime没有构造方法,采用单例设计模式
package cn.itcast.p1.otherapi;
import java.io.IOException;
public class RuntimeDemo {
/**
* @param args
* @throws IOException
* @throws InterruptedException
*/
public static void main(String[] args) throws IOException, InterruptedException {
/*
* Runtime:没有构造方法摘要,说明该类不可以创建对象。
* 又发现还有非静态的方法。说明该类应该提供静态的返回该类对象的方法。
* 而且只有一个,说明Runtime类使用了单例设计模式。
*
*/
Runtime r = Runtime.getRuntime();
// execute: 执行。 xxx.exe
Process p = r.exec("notepad.exe");
Thread.sleep(5000);
p.destroy();
}
}
Math 类
package cn.itcast.p1.otherapi;
import java.util.Random;
public class MathDemo {
/**
* @param args
*/
public static void main(String[] args) {
/*
* Math:提供了操作数学运算的方法。都是静态的。
*
* 常用的方法:
* ceil():返回大于参数的最小整数。
* floor():返回小于参数的最大整数。
* round():返回四舍五入的整数。
* pow(a,b):a的b次方。
*
*/
double d1 = Math.ceil(12.56);
double d2 = Math.floor(12.56);
double d3 = Math.round(12.46);
// sop(“d1=”+d1);
// sop(“d2=”+d2);
// sop(“d3=”+d3);
// double d = Math.pow(10, 2);
// sop(“d=”+d);
Random r = new Random();
for (int i = 0; i < 10; i++) {
// double d = Math.ceil(Math.random()*
±10);
// double d = (int)(Math.random()*6+1);
// double d = (int)(r.nextDouble()*6+1);
int d = r.nextInt(6)+1;
System.out.println(d);
}
}
public static void sop(String string) {
System.out.println(string);
}
}
windows /r/n换行
流对象的处理方式
在try外面创建引用变量
在try里面进行对象的初始化
FileWrter fw =null;
try{
fw =new FileWriter(“demo.txt”);}
关闭前得判断空指针异常
学习Date类之前了解一下 工厂模式https://www.jianshu.com/p/e55fbddc071c
Date 类
long time =ourrentTimeMillis();
LocalDate是一个不可变的日期时间对象,表示日期
这个类是不可变的和线程安全的
LocalDate today = LocalDate.now();//获取今天日期
LocalDate todayKolkata = LocalDate.now(ZoneId.of(“Asia/Kolkata”));//获取。。。时区时间
of();
从一年,一个月和一天获得一个LocalDate的实例。
这将返回一个LocalDate与指定的年,月和日。 该日期必须在年和月中有效,否则将抛出异常。
LocalDate firstDay_2014 = LocalDate.of(2014, Month.JANUARY, 1);//2014-01-01
LocalDate.now(ZoneId.of(“Asia/Kolkala”));
设置时区
LocalDate todayKolkata = LocalDate.now(ZoneId.of(“Asia/Kolkata”));
System.out.println(“Current Date in IST=”+todayKolkata);
Current Date in IST=2014-04-29
LocalDate.ofEpochDay(365);
从1970-01-01开始 后的第365天
— 1971-01-01
java.time.LocalTime:LocalTime是一个不可变的类,它的实例代表一个符合人类可读格式的时间,默认格式是hh:mm:ss.zzz。像LocalDate一样,该类也提供了时区支持,同时也可以传入小时、分钟和秒等输入参数创建实例
LocalTime specificTime = LocalTime.of(12,20,25,40);
System.out.println(“Specific Time of Day=”+specificTime);
//12:20:25.000000040
LocalTime time = LocalTime.now();//15:51:45.240
LocalTime timeKolkata = LocalTime.now(ZoneId.of(“Asia/Kolkata”));
System.out.println(“Current Time in IST=”+timeKolkata);
//Current Time in IST=04:21:45.276
LocalDateTime
java.time.LocalDateTime:LocalDateTime是一个不可变的日期-时间对象,它表示一组日期-时间,默认格式是yyyy-MM-dd-HH-mm-ss.zzz。它提供了一个工厂方法,接收LocalDate和LocalTime输入参数,创建LocalDateTime实例
LocalDateTime specificDate = LocalDateTime.of(2014, Month.JANUARY, 1, 10, 10, 30);
System.out.println(“Specific Date=”+specificDate);
Specific Date=2014-01-01T10:10:30
LocalDateTime dateFromBase = LocalDateTime.ofEpochSecond(10000, 0, ZoneOffset.UTC);
System.out.println("10000th second time from 01/01/1970= "+dateFromBase);
10000th second time from 01/01/1970= 1970-01-01T02:46:40
http://www.importnew.com/14140.html
IO
输入流和输出流相对于内存设备而言.
将外设中的数据读取到内存中:输入
将内存的数写入到外设中:输出。
字符流的由来:
其实就是:字节流读取文字字节数据后,不直接操作而是先查指定的编码表。获取对应的文字。
在对这个文字进行操作。简单说:字节流+编码表
字节流的两个顶层父类:
1,InputStream 2,OutputStream.
字符流的两个顶层父类:
1,Reader 2,Writer
这些体系的子类都以父类名作为后缀。
而且子类名的前缀就是该对象的功能。
就从熟悉的文字开始字符流,
//需求:将一些文字存储到硬盘一个文件中。
记住;如果要操作文字数据,建议优先考虑字符流。
而且要将数据从内存写到硬盘上,要使用字符流中的输出流。Writer
硬盘的数据基本体现是文件。 希望找到一个可以操作文件的Writer.
找到了FileWriter
//需求:读取一个文本文件。将读取到的字符打印到控制台.
同上,找到了FileReader
作业:将c盘的一个文本文件复制到d盘。
package cn.itcast.p2.io.filewriter;
import java.io.FileWriter;
import java.io.IOException;
//需求:将一些文字存储到硬盘一个文件中。
public class FileWriterDemo {
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//创建一个可以往文件中写入字符数据的字符输出流对象。
/*
* 既然是往一个文件中写入文字数据,那么在创建对象时,就必须明确该文件(用于存储数据的目的地)。
*
* 如果文件不存在,则会自动创建。
* 如果文件存在,则会被覆盖。
*
* 如果构造函数中加入true,可以实现对文件进行续写!
*/
FileWriter fw = new FileWriter("demo.txt",true);
/*
* 调用Writer对象中的write(string)方法,写入数据。
*
* 其实数据写入到临时存储缓冲区中。
*
*/
fw.write("abcde"+LINE_SEPARATOR+"hahaha");
// fw.write(“xixi”);****
/*
* 进行刷新,将数据直接写到目的地中。
*/
// fw.flush();
/*
* 关闭流,关闭资源。在关闭前会先调用flush刷新缓冲中的数据到目的地。
*/
fw.close();
// fw.write(“haha”);// java.io.IOException: Stream closed
}
}
IOException
package cn.itcast.p2.io.filewriter;
import java.io.FileWriter;
import java.io.IOException;
public class IOExceptionDemo {
private static final String LINE_SEPARATOR = System
.getProperty("line.separator");
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) {
FileWriter fw = null;//这里就得这么写!!!!!
try {
fw = new FileWriter("k:\\demo.txt");
fw.write("abcde" + LINE_SEPARATOR + "hahaha");
} catch (IOException e) {
System.out.println(e.toString());
} finally {
if (fw != null)
try {
fw.close();
} catch (IOException e) {
// code....
throw new RuntimeException("关闭失败");
}
}
}
}
Char[] buf=new char[3];
System.out.println(new String (buf));
//String(char []) 字符数组转字符串
package cn.itcast.p3.io.filereader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
//需求:读取一个文本文件。将读取到的字符打印到控制台.
public class FileReaderDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//1,创建读取字符数据的流对象。
/*
* 在创建读取流对象时,必须要明确被读取的文件。一定要确定该文件是存在的。
*
* 用一个读取流关联一个已存在文件。
*/
FileReader fr = new FileReader("demo.txt");
int ch = 0;
while((ch=fr.read())!=-1){
System.out.println((char)ch);
}
/*
//用Reader中的read方法读取字符。
int ch = fr.read();
System.out.println((char)ch);
int ch1 = fr.read();
System.out.println(ch1);
int ch2 = fr.read();
System.out.println(ch2);
*/
fr.close();
}
}
package cn.itcast.p3.io.filereader;
import java.io.FileReader;
import java.io.IOException;
//需求:读取一个文本文件。将读取到的字符打印到控制台.
public class FileReaderDemo2 {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("demo.txt");
/*
* 使用read(char[])读取文本文件数据。
*
* 先创建字符数组。
*/
char[] buf = new char[1024];
int len = 0;
while((len=fr.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
/*
int num = fr.read(buf);//将读取到的字符存储到数组中。
System.out.println(num+":"+new String(buf,0,num));
int num1 = fr.read(buf);//将读取到的字符存储到数组中。
System.out.println(num1+":"+new String(buf,0,num1));
int num2 = fr.read(buf);//将读取到的字符存储到数组中。
System.out.println(num2+":"+new String(buf));
*/
fr.close();
}
}
package cn.itcast.p1.io.charstream.test;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
*/
public class CopyTextTest {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//1,读取一个已有的文本文件,使用字符读取流和文件相关联。
FileReader fr = new FileReader("IO流_2.txt");
//2,创建一个目的,用于存储读到数据。
FileWriter fw = new FileWriter("copytext_1.txt");
//3,频繁的读写操作。
int ch = 0;
while((ch=fr.read())!=-1){
fw.write(ch);
}
//4,关闭流资源。
fw.close();
fr.close();
}
}
package cn.itcast.p1.io.charstream.test;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyTextTest_2 {
private static final int BUFFER_SIZE = 1024;
/**
* @param args
*/
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("IO流_2.txt");
fw = new FileWriter("copytest_2.txt");
//创建一个临时容器,用于缓存读取到的字符。
char[] buf = new char[BUFFER_SIZE];//这就是缓冲区。
//定义一个变量记录读取到的字符数,(其实就是往数组里装的字符个数 )
int len = 0;
while((len=fr.read(buf))!=-1){
fw.write(buf, 0, len);
}
} catch (Exception e) {
// System.out.println(“读写失败”);
throw new RuntimeException(“读写失败”);
}finally{
if(fw!=null)
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
if(fr!=null)
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package cn.itcast.p2.io.charstream.buffer;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterDemo {
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("buf.txt");
//为了提高写入的效率。使用了字符流的缓冲区。
//创建了一个字符写入流的缓冲区对象,并和指定要被缓冲的流对象相关联
BufferedWriter bufw = new BufferedWriter(fw);
//使用缓冲区的写入方法将数据先写入到缓冲区中。
// bufw.write(“abcdefq”+LINE_SEPARATOR+“hahahha”);
// bufw.write(“xixiixii”);
// bufw.newLine();//换行
// bufw.write(“heheheheh”);
for(int x=1; x<=4; x++){
bufw.write("abcdef"+x);
bufw.newLine();
bufw.flush();
}
//使用缓冲区的刷新方法将数据刷目的地中。
// bufw.flush();
//关闭缓冲区。其实关闭的就是被缓冲的流对象。
bufw.close();
// fw.write(“hehe”);
// fw.close();
}
}
package cn.itcast.p2.io.charstream.buffer;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("buf.txt");
BufferedReader bufr = new BufferedReader(fr);
String line = null;
while((line=bufr.readLine())!=null){
System.out.println(line);
}
/*
String line1 = bufr.readLine();
System.out.println(line1);
String line2 = bufr.readLine();
System.out.println(line2);
String line3 = bufr.readLine();
System.out.println(line3);
String line4 = bufr.readLine();
System.out.println(line4);
String line5 = bufr.readLine();
System.out.println(line5);
*/
bufr.close();
}
/**
* @throws FileNotFoundException
* @throws IOException
*/
public static void demo() throws FileNotFoundException, IOException {
FileReader fr = new FileReader("buf.txt");
char[] buf = new char[1024];
int len = 0;
while((len=fr.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
fr.close();
}
}
package cn.itcast.p3.io.charstream.buffer.test;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyTextByBufTest {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("buf.txt");
BufferedReader bufr = new BufferedReader(fr);
FileWriter fw = new FileWriter("buf_copy.txt");
BufferedWriter bufw = new BufferedWriter(fw);
String line = null;
while((line=bufr.readLine())!=null){
bufw.write(line);
bufw.newLine();
bufw.flush();//要刷新 养习惯
}
/*
int ch = 0;
while((ch=bufr.read())!=-1){
bufw.write(ch);
}
*/
bufw.close();
bufr.close();
}
}
package cn.itcast.p4.io.charstream.mybuffer;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
/**
*/
public class MyBufferedReader extends Reader {
private Reader r;
//定义一个数组作为缓冲区。
private char[] buf = new char[1024];
//定义一个指针用于操作这个数组中的元素。当操作到最后一个元素后,指针应该归零。
private int pos = 0;
//定义一个计数器用于记录缓冲区中的数据个数。 当该数据减到0,就从源中继续获取数据到缓冲区中。
private int count = 0;
MyBufferedReader(Reader r){
this.r = r;
}
/**
* 该方法从缓冲区中一次取一个字符。
* @return
* @throws IOException
*/
public int myRead() throws IOException{
if(count==0){
count = r.read(buf);
pos = 0;
}
if(count<0)
return -1;
char ch = buf[pos++];
count--;
return ch;
/*
//1,从源中获取一批数据到缓冲区中。需要先做判断,只有计数器为0时,才需要从源中获取数据。
if(count==0){
count = r.read(buf);
if(count<0)
return -1;
//每次获取数据到缓冲区后,角标归零.
pos = 0;
char ch = buf[pos];
pos++;
count--;
return ch;
}else if(count>0){
char ch = buf[pos];
pos++;
count--;
return ch;
}*/
}
public String myReadLine() throws IOException{//ReadLine
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch = myRead())!=-1){
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
//将从缓冲区中读到的字符,存储到缓存行数据的缓冲区中。
sb.append((char)ch);
}
if(sb.length()!=0)
return sb.toString();//防止最后一行你不打回车
return null;
}
public void myClose() throws IOException {
r.close();
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
return 0;
}
@Override
public void close() throws IOException {
}
}
字符流缓冲区:
BufferedWriter
:newLine();
使用缓冲区复制一个文本文件。
装饰设计模式:
对一组对象的功能进行增强时,就可以使用该模式进行问题的解决。
装饰和继承都能实现一样的特点:进行功能的扩展增强。
有什么区别呢?
首先有一个继承体系。
Writer
|–TextWriter:用于操作文本
|–MediaWriter:用于操作媒体。
想要对操作的动作进行效率的提高。
按照面向对象,可以通过继承对具体的进行功能的扩展。
效率提高需要加入缓冲技术。
Writer
|–TextWriter:用于操作文本
|–BufferTextWriter:加入了缓冲技术的操作文本的对象。
|–MediaWriter:用于操作媒体。
|–BufferMediaWriter:
到这里就哦了。但是这样做好像并不理想。
如果这个体系进行功能扩展,有多了流对象。
那么这个流要提高效率,是不是也要产生子类呢?是。这时就会发现只为提高功能,进行的继承,
导致继承体系越来越臃肿。不够灵活。
重新思考这个问题?
既然加入的都是同一种技术–缓冲。
前一种是让缓冲和具体的对象相结合。
可不可以将缓冲进行单独的封装,哪个对象需要缓冲就将哪个对象和缓冲关联。
class Buffer{
Buffer(TextWriter w)
{}
Buffer(MediaWirter w)
{
}
}
class BufferWriter extends Writer{
BufferWriter(Writer w)
{
}
}
Writer
|–TextWriter:用于操作文本
|–MediaWriter:用于操作媒体。
|–BufferWriter:用于提高效率。
装饰比继承灵活。
特点:装饰类和被装饰类都必须所属同一个接口或者父类。
字节流:
InputStream
OutputStream
字节流:
FileInputStream
FileOutputStream
BufferedInputStream
BufferedOutputStream
字符流:
Writer Reader
FileReader
FileWriter
BufferedReader
BufferedWriter
package cn.itcast.p5.wrapper;
public class PersonDemo {
/**
* @param args
*/
public static void main(String[] args) {
Person p = new Person();
// p.chifan();
NewPerson p1 = new NewPerson(p);
p1.chifan();
NewPerson2 p2 = new NewPerson2();
p2.chifan();
}
}
class Person{
void chifan(){
System.out.println(“吃饭”);
}
}
//这个类的出现是为了增强Person而出现的。
class NewPerson{
private Person p ;
NewPerson(Person p){
this.p = p;
}
public void chifan(){
System.out.println("开胃酒");
p.chifan();
System.out.println("甜点");
}
}
class NewPerson2 extends Person{
public void chifan(){
System.out.println(“开胃酒”);
super.chifan();
System.out.println(“甜点”);
}
}
写个行号
package cn.itcast.p6.io.charstream.linenumber;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
public class LineNumberReaderDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("IO流_2.txt");
LineNumberReader lnr = new LineNumberReader(fr);
String line = null;
lnr.setLineNumber(100);
while((line=lnr.readLine())!=null){
System.out.println(lnr.getLineNumber()+":"+line);
}
lnr.close();
}
}
字节流
package cn.itcast.p7.io.bytestream.demo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteStreamDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
demo_read();
}
public static void demo_read() throws IOException {
//1,创建一个读取流对象。和指定文件关联。
FileInputStream fis = new FileInputStream("bytedemo.txt");
// System.out.println(fis.available());
// byte[] buf = new byte[fis.available()];
// fis.read(buf);
// System.out.println(new String(buf));
//建议使用这种读取数据的方式
// byte[] buf = new byte[1024];
// int len = 0;
//
// while((len=fis.read(buf))!=-1){
// System.out.println(new String(buf,0,len));
// }
// int ch = 0;
// while((ch=fis.read())!=-1){
// System.out.println((char)ch);
// }
//一次读取一个字节。
// int ch = fis.read();
// System.out.println(ch);
fis.close();
}
public static void demo_write() throws IOException {
//1,创建字节输出流对象。用于操作文件.
FileOutputStream fos = new FileOutputStream("bytedemo.txt");
//2,写数据。直接写入到了目的地中。
fos.write("abcdefg".getBytes());
// fos.flush();
fos.close();//关闭资源动作要完成。
}
}
package cn.itcast.p7.io.bytestream.test;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyMp3Test {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
copy_4();
}
// 千万不要用,效率没有!
public static void copy_4() throws IOException {
FileInputStream fis = new FileInputStream(“c:\0.mp3”);
FileOutputStream fos = new FileOutputStream(“c:\4.mp3”);
int ch = 0;
while((ch =fis.read())!=-1){
fos.write(ch);
}
fos.close();
fis.close();
}
//不建议。
public static void copy_3() throws IOException {
FileInputStream fis = new FileInputStream("c:\\0.mp3");
FileOutputStream fos = new FileOutputStream("c:\\3.mp3");
byte[] buf = new byte[fis.available()];
fis.read(buf);
fos.write(buf);
fos.close();
fis.close();
}
public static void copy_2() throws IOException {
FileInputStream fis = new FileInputStream("c:\\0.mp3");
BufferedInputStream bufis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("c:\\2.mp3");
BufferedOutputStream bufos = new BufferedOutputStream(fos);
int ch = 0;
while((ch=bufis.read())!=-1){
bufos.write(ch);
}
bufos.close();
bufis.close();
}
public static void copy_1() throws IOException {
FileInputStream fis = new FileInputStream("c:\\0.mp3");
FileOutputStream fos = new FileOutputStream("c:\\1.mp3");
byte[] buf = new byte[1024];
int len = 0;
while((len=fis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
fis.close();
}
}
动态绑定与动态绑定
在Java中存在两种绑定方式,一种为静态绑定,又称作早期绑定;另一种就是动态绑定,也叫后期绑定。
区别
(1)、静态绑定发生在编译时期,动态绑定发生在运行时。
(2)、使用private或static或final修饰的变量或者方法,使用静态绑定。而虚方法(可以被子类重写的方法)则会根据运行时
的对象进行动态绑定。
(3)、静态绑定使用类信息来完成,而动态绑定则需要使用对象信息来完成。
(4)、重载(Overload)的方法是用静态绑定完成,而重写(Override)的方法则使用动态绑定完成。
后期绑定:动态绑定是指编译器在编译阶段不知道要调用哪个方法,直到运行时根据具体对象的类型进行绑定。
Collections.shuffle();洗牌
默认的输入输出设备不需要关流,就一个流关了就没了。System.in
集合清空 clear
StringBuffer 清空 delete(0, .lenth())
UTF-8编码表 一个字节能装就一个,两个能装就两个
三个。。。。。。每个字节有个编码头
.getpath(); //构造里写啥我就是啥
https://blog.csdn.net/chenleixing/article/details/44408875
时间类学习路径!!!!!!!
package cn.itcast.io.p1.transstream.demo;
import java.io.IOException;
import java.io.InputStream;
/*
*/
public class ReadKey {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// readKey();
// System.out.println((int)’\r’);
// System.out.println((int)’\n’);
readKey2();
}
public static void readKey2() throws IOException {
/*
* 获取用户键盘录入的数据,
* 并将数据变成大写显示在控制台上,
* 如果用户输入的是over,结束键盘录入。
*
* 思路:
* 1,因为键盘录入只读取一个字节,要判断是否是over,需要将读取到的字节拼成字符串。
* 2,那就需要一个容器。StringBuilder.
* 3,在用户回车之前将录入的数据变成字符串判断即可。
*
*/
//1,创建容器。
StringBuilder sb = new StringBuilder();
//2,获取键盘读取流。
InputStream in = System.in;
//3,定义变量记录读取到的字节,并循环获取。
int ch = 0;
while((ch=in.read())!=-1){
// 在存储之前需要判断是否是换行标记 ,因为换行标记不存储。
if(ch==’\r’)
continue;
if(ch==’\n’){
String temp = sb.toString();
if(“over”.equals(temp))
break;
System.out.println(temp.toUpperCase());
sb.delete(0, sb.length());
}
else
//将读取到的字节存储到StringBuilder中。
sb.append((char)ch);
// System.out.println(ch);
}
}
public static void readKey() throws IOException {
InputStream in = System.in;
int ch = in.read();//阻塞式方法。
System.out.println(ch);
int ch1 = in.read();//阻塞式方法。
System.out.println(ch1);
int ch2 = in.read();//阻塞式方法。
System.out.println(ch2);
// in.close();
// InputStream in2 = System.in;
// int ch3 = in2.read();
}
}
package cn.itcast.io.p1.transstream.demo;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
public class TransStreamDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//字节流。
InputStream in = System.in;
// int ch = in.read();
// System.out.println(ch);
// int ch1 = in.read();
// System.out.println(ch1);
//将字节转成字符的桥梁。装换流。
InputStreamReader isr = new InputStreamReader(in);
// int ch = isr.read();
// System.out.println((char)ch);
//字符流。
BufferedReader bufr = new BufferedReader(isr);
OutputStream out = System.out;
OutputStreamWriter osw = new OutputStreamWriter(out);
BufferedWriter bufw = new BufferedWriter(osw);
String line = null;
while((line=bufr.readLine())!=null){
if("over".equals(line))
break;
// System.out.println(line.toUpperCase());
// osw.write(line.toUpperCase()+"\r\n");
// osw.flush();
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
}
}
package cn.itcast.io.p1.transstream.demo;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class TransStreamDemo2 {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
/*
* 1,需求:将键盘录入的数据写入到一个文件中。
*
* 2,需求:将一个文本文件内容显示在控制台上。
*
* 3,需求:将一个文件文件中的内容复制到的另一个文件中。
*/
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("b.txt")));
String line = null;
while((line=bufr.readLine())!=null){
if("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
}
}
package cn.itcast.io.p1.transstream.demo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
public class TransStreamDemo3 {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
readText_2();
}
public static void readText_2() throws IOException, FileNotFoundException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("gbk_1.txt","utf-8");//指定编码格式
char[] buf = new char[10];
int len = isr.read(buf);
String str = new String(buf,0,len);
System.out.println(str);
isr.close();
}
public static void readText_1() throws IOException {
FileReader fr = new FileReader("gbk_1.txt");
char[] buf = new char[10];
int len = fr.read(buf);
String str = new String(buf,0,len);
System.out.println(str);
fr.close();
}
public static void writeText_3() throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("u8_1.txt"),"UTF-8");
osw.write("你好");
osw.close();
}
public static void writeText_2() throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk_3.txt"),"GBK");
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“gbk_3.txt”),“GBK”);
// FileWriter fw = new FileWriter(“gbk_1.txt”);//默认编码格式
/*
* 这两句代码的功能是等同的。
* FileWriter:其实就是转换流指定了本机默认码表的体现。而且这个转换流的子类对象,可以方便操作文本文件。
* 简单说:操作文件的字节流+本机默认的编码表。
* 这是按照默认码表来操作文件的便捷类。
*
* 如果操作文本文件需要明确具体的编码。FileWriter就不行了。必须用转换流。
*
*/
osw.write("你好");
osw.close();
}
public static void writeText_1() throws IOException {
FileWriter fw = new FileWriter("gbk_1.txt");
fw.write("你好");
fw.close();
}
}
File类
package cn.itcast.io.p2.file.demo;
import java.io.File;
public class FileDemo {
/**
* @param args
*/
public static void main(String[] args) {
// constructorDemo();
}
public static void constructorDemo() {
//可以将一个已存在的,或者不存在的文件或者目录封装成file对象。
File f1 = new File("c:\\a.txt");
File f2 = new File("c:\\","a.txt");
File f = new File("c:\\");
File f3 = new File(f,"a.txt");
File f4 = new File("c:"+File.separator+"abc"+File.separator+"a.txt");
System.out.println(f4);
}
}
package cn.itcast.io.p2.file.demo;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
public class FileMethodDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
/*
* File对象的常见方法。
*
* 1,获取。
* 1.1 获取文件名称。
* 1.2 获取文件路径。
* 1.3 获取文件大小。
* 1.4 获取文件修改时间。
*
* 2,创建与删除。
*
* 3,判断。
*
* 4, 重命名
*
*/
// getDemo();
// createAndDeleteDemo();
// isDemo();
// renameToDemo();
// listRootsDemo();//系统根目录
}
public static void listRootsDemo() {
File file = new File("d:\\");
System.out.println("getFreeSpace:"+file.getFreeSpace());//剩余空间
System.out.println("getTotalSpace:"+file.getTotalSpace());//
System.out.println("getUsableSpace:"+file.getUsableSpace());
File[] files = File.listRoots(); //它们表示可用文件系统根的根目录 盘符
// for(File file : files){
// System.out.println(file);
// }
}
public static void renameToDemo() {
File f1 = new File("c:\\9.mp3");
File f2 = new File("d:\\aa.mp3");
boolean b = f1.renameTo(f2);
System.out.println("b="+b);
}
public static void isDemo() throws IOException{
File f = new File("aaa");
// f.mkdir();
f.createNewFile();
// boolean b = f.exists();
// System.out.println(“b=”+b);
// 最好先判断是否存在。
System.out.println(f.isFile());
System.out.println(f.isDirectory());//测试此抽象路径名表示的文件是否为目录
}
public static void createAndDeleteDemo() throws IOException {
File dir = new File("abc\\q\\e\\c\\z\\r\\w\\y\\f\\e\\g\\s");
// boolean b = dir.mkdir();//make directory
// System.out.println(“b=”+b);
// dir.mkdirs();//创建多级目录
System.out.println(dir.delete());
// System.out.println(dir.delete());
// 文件的创建和删除。
// File file = new File(“file.txt”);
/*
* 和输出流不一样,如果文件不存在,则创建,如果文件存在,则不创建。
*
*/
// boolean b = file.createNewFile();
// System.out.println(“b=”+b);
// boolean b = file.delete();
// System.out.println(“b=”+b);
}
public static void getDemo(){
// File file = new File(“E:\java0331\day22e\a.txt”);
File file = new File(“a.txt”);
String name = file.getName();
String absPath = file.getAbsolutePath();//绝对路径。完整版
String path = file.getPath();
long len = file.length();
long time = file.lastModified();
Date date = new Date(time);
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
String str_time = dateFormat.format(date);
System.out.println("parent:"+file.getParent());
System.out.println("name:"+name);
System.out.println("absPath:"+absPath);
System.out.println("path:"+path);
System.out.println("len:"+len);
System.out.println("time:"+time);
System.out.println("str_time:"+str_time);
}
}
package cn.itcast.io.p2.file.demo;
import java.io.File;
import cn.itcast.io.p2.filter.FilterByHidden;
import cn.itcast.io.p2.filter.SuffixFilter;
public class FileListDemo {
/**
* @param args
*/
public static void main(String[] args) {
listDemo_2();
}
public static void listDemo_3() {
File dir = new File("c:\\");
File[] files = dir.listFiles(new FilterByHidden());
for(File file : files){
System.out.println(file);
}
}
public static void listDemo_2() {
File dir = new File("c:\\");
String[] names = dir.list(new SuffixFilter(".txt"));
for(String name : names){
System.out.println(name);
}
}
public static void listDemo() {
File file = new File("c:\\");
/*
* 获取当前目录下的文件以及文件夹的名称,包含隐藏文件。
* 调用list方法的File对象中封装的必须是目录。
* 否则会发生NullPointerException
* 如果访问的系统级目录也会发生空指针异常。
*
* 如果目录存在但是没有内容,会返回一个数组,但是长度为0.
*
*/
String[] names = file.list();
System.out.println(names.length);
for(String name : names){
System.out.println(name);
}
}
}
package cn.itcast.io.p2.filter;
import java.io.File;
import java.io.FileFilter;
public class FilterByHidden implements FileFilter {
@Override
public boolean accept(File pathname) {
return !pathname.isHidden();
}
}
package cn.itcast.io.p2.filter;
import java.io.File;
import java.io.FilenameFilter;
public class FilterByJava implements FilenameFilter {
@Override
public boolean accept(File dir, String name) {
// System.out.println(dir+"—"+name);
return name.endsWith(".txt");
}
}
package cn.itcast.io.p2.filter;
import java.io.File;
import java.io.FilenameFilter;
public class SuffixFilter implements FilenameFilter {
private String suffix ;
public SuffixFilter(String suffix) {
super();
this.suffix = suffix;
}
@Override
public boolean accept(File dir, String name) {
return name.endsWith(suffix);
}
}
递归
package cn.itcast.io.p1.digui;
public class DiGuiDemo {
/**
* @param args
*/
public static void main(String[] args) {
/*
* 递归:
* 函数自身直接或者间接的调用到了自身。
*
* 一个功能在被重复使用,并每次使用时,参与运算的结果和上一次调用有关。
* 这时可以用递归来解决问题。
*
*
* 注意:
* 1,递归一定明确条件。否则容易栈溢出。
* 2,注意一下递归的次数。
*
*/
// show();
// toBin(6);
int sum = getSum(9000);
System.out.println(sum);
}
public static int getSum(int num){
int x = 9;
if(num==1)
return 1;
return num+getSum(num-1);
}
public static void toBin(int num){
if(num>0){
toBin(num/2);
System.out.println(num%2);
}
}
/*
public static void show(){
method();
}
public static void method(){
show();
}
*/
}
package cn.itcast.io.p1.file.test;
import java.io.File;
/*
*/
public class FileTest {
/**
* @param args
*/
public static void main(String[] args) {
File dir = new File("e:\\demodir");
listAll(dir,0);
}
public static void listAll(File dir,int level) {
System.out.println(getSpace(level)+dir.getName());
//获取指定目录下当前的所有文件夹或者文件对象
level++;
File[] files = dir.listFiles();//返回File类型
for(int x=0; x
}
package cn.itcast.io.p1.file.test;
import java.io.File;
/*
*/
public class RemoveDirTest {
/**
* @param args
*/
public static void main(String[] args) {
File dir = new File("e:\\demodir");
// dir.delete();
removeDir(dir);
}
public static void removeDir(File dir) {
File[] files = dir.listFiles();
for(File file : files){
if(file.isDirectory()){
removeDir(file);
}else{
System.out.println(file+":"+file.delete());
}
}
System.out.println(dir+":"+dir.delete());
}
}
Properties
package cn.itcast.io.p2.properties;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
/*
* Map
* |--Hashtable
* |--Properties:
*
* Properties集合:
* 特点:
* 1,该集合中的键和值都是字符串类型。
* 2,集合中的数据可以保存到流中,或者从流获取。
*
* 通常该集合用于操作以键值对形式存在的配置文件。
*
*
*/
// methodDemo_4();
// myLoad();
test();
}
//对已有的配置文件中的信息进行修改。
/*
* 读取这个文件。
* 并将这个文件中的键值数据存储到集合中。
* 在通过集合对数据进行修改。
* 在通过流将修改后的数据存储到文件中。
*/
public static void test() throws IOException{
//读取这个文件。
File file = new File("info.txt");
if(!file.exists()){
file.createNewFile();
}
FileReader fr = new FileReader(file);
//创建集合存储配置信息。
Properties prop = new Properties();
//将流中信息存储到集合中。
prop.load(fr);
prop.setProperty("wangwu", "16");
FileWriter fw = new FileWriter(file);
prop.store(fw,"");//存到配置文件
// prop.list(System.out);
fw.close();
fr.close();
}
//模拟一下load方法。
public static void myLoad() throws IOException{
Properties prop = new Properties();
BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
String line = null;
while((line=bufr.readLine())!=null){
if(line.startsWith("#"))
continue;
String[] arr = line.split("=");
// System.out.println(arr[0]+"::"+arr[1]);
prop.setProperty(arr[0], arr[1]);
}
prop.list(System.out);
bufr.close();
}
public static void methodDemo_4() throws IOException {
Properties prop = new Properties();
//集合中的数据来自于一个文件。
//注意;必须要保证该文件中的数据是键值对。
//需要使用到读取流。
FileInputStream fis = new FileInputStream("info.txt");
//使用load方法。
prop.load(fis);
prop.list(System.out);
}
public static void methodDemo_3() throws IOException {
Properties prop = new Properties();
//存储元素。
prop.setProperty("zhangsan","30");
prop.setProperty("lisi","31");
prop.setProperty("wangwu","36");
prop.setProperty("zhaoliu","20");
//想要将这些集合中的字符串键值信息持久化存储到文件中。
//需要关联输出流。
FileOutputStream fos = new FileOutputStream("info.txt");
//将集合中数据存储到文件中,使用store方法。
prop.store(fos, "info");
fos.close();
}
/**
* 演示Properties集合和流对象相结合的功能。
*/
public static void methodDemo_2(){
Properties prop = new Properties();
//存储元素。
// prop.setProperty(“zhangsan”,“30”);
// prop.setProperty(“lisi”,“31”);
// prop.setProperty(“wangwu”,“36”);
// prop.setProperty(“zhaoliu”,“20”);
prop = System.getProperties();
prop.list(System.out);
}
/*
* Properties集合的存和取。
*/
public static void propertiesDemo(){
//创建一个Properties集合。
Properties prop = new Properties();
//存储元素。
prop.setProperty("zhangsan","30");
prop.setProperty("lisi","31");
prop.setProperty("wangwu","36");
prop.setProperty("zhaoliu","20");
//修改元素。
prop.setProperty("wangwu","26");
//取出所有元素。
Set names = prop.stringPropertyNames();
for(String name : names){
String value = prop.getProperty(name);
System.out.println(name+":"+value);
}
}
}
package cn.itcast.io.p2.properties;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
/*
*/
public class PropertiesTest {
/**
* @param args
* @throws IOException
* @throws Exception
*/
public static void main(String[] args) throws IOException {
getAppCount();
}
public static void getAppCount() throws IOException{
//将配置文件封装成File对象。
File confile = new File("count.properties");
if(!confile.exists()){
confile.createNewFile();
}
FileInputStream fis = new FileInputStream(confile);
Properties prop = new Properties();
prop.load(fis);
//从集合中通过键获取次数。
String value = prop.getProperty("time");
//定义计数器。记录获取到的次数。
int count =0;
if(value!=null){
count = Integer.parseInt(value);
if(count>=5){
// System.out.println(“使用次数已到,请注册,给钱!”);
// return;
throw new RuntimeException(“使用次数已到,请注册,给钱!”);
}
}
count++;
//将改变后的次数重新存储到集合中。
prop.setProperty("time", count+"");
FileOutputStream fos = new FileOutputStream(confile);
prop.store(fos, "");
fos.close();
fis.close();
}
}
package cn.itcast.io.p3.test;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/*
*
*/
public class Test {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
File dir = new File("e:\\java0331");
FilenameFilter filter = new FilenameFilter(){
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".java");
}
};
List list = new ArrayList();
getFiles(dir,filter,list);
File destFile = new File(dir,"javalist.txt");
write2File(list,destFile);
}
/**
* 对指定目录中的内容进行深度遍历,并按照指定过滤器,进行过滤,
* 将过滤后的内容存储到指定容器List中。
* @param dir
* @param filter
* @param list
*/
public static void getFiles(File dir,FilenameFilter filter,List list){
File[] files = dir.listFiles();
for(File file : files){
if(file.isDirectory()){
//递归啦!
getFiles(file,filter,list);
}else{
//对遍历到的文件进行过滤器的过滤。将符合条件File对象,存储到List集合中。
if(filter.accept(dir, file.getName())){ //boolean类型
list.add(file);
}
}
}
}
public static void write2File(List list,File destFile)throws IOException{
BufferedWriter bufw = null;
try {
bufw = new BufferedWriter(new FileWriter(destFile));
for(File file : list){
bufw.write(file.getAbsolutePath());
bufw.newLine();
bufw.flush();
}
} /*catch(IOException e){
throw new RuntimeException("写入失败");
}*/finally{
if(bufw!=null)
try {
bufw.close();
} catch (IOException e) {
throw new RuntimeException("关闭失败");
}
}
}
}
package cn.itcast.io.p4.print.demo;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
public class PrintStreamDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
/*
* PrintStream:
* 1,提供了打印方法可以对多种数据类型值进行打印。并保持数据的表示形式。
* 2,它不抛IOException.
*
* 构造函数,接收三种类型的值:
* 1,字符串路径。
* 2,File对象。
* 3,字节输出流。
*/
PrintStream out = new PrintStream("print.txt");
// int by = read();
// write(by);
// out.write(610);//只写最低8位,前24位没了
// out.print(97);//将97先变成字符保持原样将数据打印到目的地。
out.close();
}
}
package cn.itcast.io.p4.print.demo;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class PrintWriterDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
/*
* PrintWriter:字符打印流。
* 构造函数参数:
* 1,字符串路径。
* 2,File对象。
* 3,字节输出流。
* 4,字符输出流。
*
*/
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(new FileWriter("out.txt"),true);//构造是File,bollean 可以继续添加数据
String line = null;
while((line=bufr.readLine())!=null){
if("over".equals(line))
break;
out.println(line.toUpperCase());
// out.flush();
}
out.close();
bufr.close();
}
}
//迭代器和枚举功能相同
List a1=new ArrayList();
Enumeration en=Collections.enumeration(a1);
package cn.itcast.io.p4.sequence.demo;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
public class SequenceInputStreamDemo {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
/*
* 需求:将1.txt 2.txt 3.txt文件中的数据合并到一个文件中。
*/
// Vector v = new Vector();
// v.add(new FileInputStream(“1.txt”));
// v.add(new FileInputStream(“2.txt”));
// v.add(new FileInputStream(“3.txt”));
// Enumeration en = v.elements();
ArrayList al = new ArrayList();
for(int x=1; x<=3; x++){
al.add(new FileInputStream(x+".txt"));
}
Enumeration en = Collections.enumeration(al);
/*
final Iterator it = al.iterator();
Enumeration en = new Enumeration(){
@Override
public boolean hasMoreElements() {
return it.hasNext();
}
@Override
public FileInputStream nextElement() {
return it.next();
}
};*/
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("1234.txt");
byte[] buf = new byte[1024];
int len = 0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
}
IO流文档
IO流:
输入流:
输出流:
字节流:
字符流:为了处理文字数据方便而出现的对象。
其实这些对象的内部使用的还是字节流(因为文字最终也是字节数据)
只不过,通过字节流读取了相对应的字节数,没有对这些字节直接操作。
而是去查了指定的(本机默认的)编码表,获取到了对应的文字。
简单说:字符流就是 : 字节流+编码表。
-----------------------
缓冲区:提高效率的,提高谁的效率?提高流的操作数据的效率。
所以创建缓冲区之前必须先有流。
缓冲区的基本思想:其实就是定义容器将数据进行临时存储。
对于缓冲区对象,其实就是将这个容器进行了封装,并提供了更多高效的操作方法。
缓冲区可以提高流的操作效率。
其实是使用了一种设计思想完成。设计模式:装饰设计模式。
Writer
|–TextWriter
|–MediaWriter
现在要对该体系中的对象进行功能的增强。增强的最常见手段就是缓冲区。
先将数据写到缓冲区中,再将缓冲区中的数据一次性写到目的地。
按照之前学习过的基本的思想,那就是对对象中的写方法进行覆盖。
产生已有的对象子类,复写write方法。不往目的地写,而是往缓冲区写。
所以这个体系会变成这样。
Writer
|–TextWriter write:往目的地
|–BufferTextWriter write:往缓冲区写
|–MediaWriter
|–BufferMediaWriter
想要写一些其他数据。就会子类。DataWriter,为了提高其效率,还要创建该类的子类。BufferDataWriter
Writer
|–TextWriter write:往目的地
|–BufferTextWriter write:往缓冲区写
|–MediaWriter
|–BufferMediaWriter
|–DataWriter
|–BufferDataWriter
发现这个体系相当的麻烦。每产生一个子类都要有一个高效的子类。
而且这写高效的子类使用的功能原理都一样,都是缓冲区原理。无论数据是什么。
都是通过缓冲区临时存储提高效率的。
那么,对于这个体系就可以进行优化,因为没有必要让每一个对象都具备相同功能的子类。
哪个对象想要进行效率的提高,只要让缓冲区对其操作即可。也就说,单独将缓冲区进行封装变成对象。
//它的出现为了提高对象的效率。所以必须在创建它的时候先有需要被提高效率的对象
class BufferWriter
{
[];
BufferedWriter(Writer w)
{
}
/*
BufferWriter(TextWriter w)
{
}
BufferedWriter(MediaWriter w)
{
}
*/
}
BufferWriter的出现增强了Writer中的write方法。
但是增强过后,BufferWriter对外提供的还是write方法。只不过是高效的。
所以写的实质没有变,那么BufferWriter也是Writer中的一员。
所以体系就会变成这样。
Writer
|–TextWriter
|–MediaWriter
|–BufferWriter
|–DataWriter
BufferWriter出现了避免了继承体系关系的臃肿,比继承更为灵活。
如果是为了增强功能,这样方式解决起来更为方便。
所以就把这种优化,总结出来,起个名字:装饰设计模式。
装饰类和被装饰类肯定所属于同一个体系。
既然明确了BufferedReader由来。
我们也可以独立完成缓冲区的建立
原理;
1,使用流的read方法从源中读取一批数据存储到缓冲区的数组中。
2,通过计数器记录住存储的元素个数。
3,通过数组的角标来获取数组中的元素(从缓冲区中取数据).
4,指针会不断的自增,当增到数组长度,会归0.计数器会自减,当减到0时,就在从源拿一批数据进缓冲区。
字符流:
FileReader
FileWriter
BufferedReader
BufferedWriter
字节流:
InputStream OutputStream。
操作文件的字节流对象。
FileOutputStream
FileInputStream
BufferedOutputStream
BufferedInputStream
字符流和字节流之间的转换动作。
转换流:
InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”));
InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”),“gbk”);
FileReader fr = new FileReader(“a.txt”);
FileWriter fw = new FileWriter(“b.txt”);
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“b.txt”));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“b.txt”),“gbk”);
转换流:字节流+编码表。
转换流的子类:FileReader,FileWriter:字节流+本地默认码表(GBK)。
如果操作文本文件使用的本地默认编码表完成编码。可以使用FileReader,或者FileWriter。因为这样写简便。
如果对操作的文本文件需要使用指定编码表进行编解码操作,这时必须使用转换流来完成。
IO流的操作规律总结:
1,明确体系:
数据源:InputStream ,Reader
数据汇:OutputStream,Writer
2,明确数据:因为数据分两种:字节,字符。
数据源:是否是纯文本数据呢?
是:Reader
否:InputStream
数据汇:
是:Writer
否:OutputStream
到这里就可以明确具体要使用哪一个体系了。
剩下的就是要明确使用这个体系中的哪个对象。
3,明确设备:
数据源:
键盘:System.in
硬盘:FileXXX
内存:数组。
网络:socket socket.getInputStream();
数据汇:
控制台:System.out
硬盘:FileXXX
内存:数组
网络:socket socket.getOutputStream();
4,明确额外功能:
1,需要转换?是,使用转换流。InputStreamReader OutputStreamWriter
2,需要高效?是,使用缓冲区。Buffered
3,需要其他?
1,复制一个文本文件。
1,明确体系:
源:InputStream ,Reader
目的:OutputStream ,Writer
2,明确数据:
源:是纯文本吗?是 Reader
目的;是纯文本吗?是 Writer
3,明确设备:
源:硬盘上的一个文件。 FileReader
目的:硬盘上的一个文件。FileWriter
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");
4,需要额外功能吗?
需要,高效,使用buffer
BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));
2,读取键盘录入,将数据存储到一个文件中。
1,明确体系:
源:InputStream ,Reader
目的:OutputStream ,Writer
2,明确数据:
源:是纯文本吗?是 Reader
目的;是纯文本吗?是 Writer
3,明确设备:
源:键盘,System.in
目的:硬盘,FileWriter
InputStream in = System.in;
FileWriter fw = new FileWriter(“a.txt”);
4,需要额外功能吗?
需要,因为源明确的体系时Reader。可是源的设备是System.in。
所以为了方便于操作文本数据,将源转成字符流。需要转换流。InputStreamReader
InputStreamReader isr = new InputStreamReader(System.in);
FileWriter fw = new FileWriter(“a.txt”);
需要高效不?需要。Buffer
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new FileWriter(“a.txt”));
3,读取一个文本文件,将数据展现在控制台上。
1,明确体系:
源:InputStream ,Reader
目的:OutputStream ,Writer
2,明确数据:
源:是纯文本吗?是 Reader
目的;是纯文本吗?是 Writer
3,明确设备:
源:硬盘文件,FileReader。
目的:控制台:System.out。
FileReader fr = new FileReader(“a.txt”);
OutputStream out = System.out;
4,需要额外功能?
因为源是文本数据,确定是Writer体系。所以为了方便操作字符数据,
需要使用字符流,但是目的又是一个字节输出流。
需要一个转换流,OutputStreamWriter
FileReader fr = new FileReader(“a.txt”);
OutputStreamWriter osw = new OutputStreamWriter(System.out);
需要高效吗?需要。
BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
4,读取键盘录入,将数据展现在控制台上。
1,明确体系:
源:InputStream ,Reader
目的:OutputStream ,Writer
2,明确数据:
源:是纯文本吗?是 Reader
目的;是纯文本吗?是 Writer
3,明确设备:
源:键盘:System.in
目的:控制台:System.out
InputStream in = System.in;
OutputStream out = System.out;
4,需要额外功能吗?
因为处理的数据是文本数据,同时确定是字符流体系。
为方便操作字符数据的可以将源和目的都转成字符流。使用转换流。
为了提高效率,使用Buffer
BufferedReader bufr =new BufferedReader(new InputStreamReader(Systme.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
5,读取一个文本文件,将文件按照指定的编码表UTF-8进行存储,保存到另一个文件中。
1,明确体系:
源:InputStream ,Reader
目的:OutputStream ,Writer
2,明确数据:
源:是纯文本吗?是 Reader
目的;是纯文本吗?是 Writer
3,明确设备:
源:硬盘:FileReader.
目的:硬盘:FileWriter
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");
4,额外功能:
注意:目的中虽然是一个文件,但是需要指定编码表。
而直接操作文本文件的FileWriter本身内置的是本地默认码表。无法明确具体指定码表。
这时就需要转换功能。OutputStreamWriter,而这个转换流需要接受一个字节输出流,而且
对应的目的是一个文件。这时就使用字节输出流中的操作文件的流对象。FileOutputStream.
FileReader fr = new FileReader("a.txt");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"),"UTF-8");
需要高效吗?
BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bufw =
new BufferedWriter(new OutputStreamWriter(new FileOutputStream("b.txt"),"UTF-8"));
目前为止,10个流对象重点掌握。
字符流:
FileReader
FileWriter
BufferedReader
BufferedWriter
InputStreamReader
OutputStreamWrier
字节流:
FileInputStream
FileOutputStream
BufferedInputStream
BufferedOutputStream
File类:
用于将文件和文件夹封装成对象。
1,创建。
boolean createNewFile():如果该文件不存在,会创建,如果已存在,则不创建。不会像输出流一样会覆盖。
boolean mkdir();
boolean mkdirs();
2,删除。
boolean delete();
void deleteOnExit();
3,获取:
String getAbsolutePath();
String getPath();
String getParent();
String getName();
long length();
long lastModified();
4,判断:
boolean exists();
boolean isFile();
boolean isDirectory();
5,
IO中的其他功能流对象:
1,打印流:
PrintStream:字节打印流。
特点:
1,构造函数接收File对象,字符串路径,字节输出流。意味着打印目的可以有很多。
2,该对象具备特有的方法 打印方法 print println,可以打印任何类型的数据。
3,特有的print方法可以保持任意类型数据表现形式的原样性,将数据输出到目的地。
对于OutputStream父类中的write,是将数据的最低字节写出去。
PrintWriter:字符打印流。
特点:
1,当操作的数据是字符时,可以选择PrintWriter,比PrintStream要方便。
2,它的构造函数可以接收 File对象,字符串路径,字节输出流,字符输出流。
3,构造函数中,如果参数是输出流,那么可以通过指定另一个参数true完成自动刷新,该true对println方法有效。
什么时候用?
当需要保证数据表现的原样性时,就可以使用打印流的打印方法来完成,这样更为方便。
保证原样性的原理:其实就是将数据变成字符串,在进行写入操作。
SequenceInputStream:
特点:
1,将多个字节读取流和并成一个读取流,将多个源合并成一个源,操作起来方便。
2,需要的枚举接口可以通过Collections.enumeration(collection);
ObjectInputStream 和 ObjectOutputStream
对象的序列化和反序列化。
writeObject readObject
Serializable标记接口
关键字:transient
RandomAccessFile:
特点:
1,即可读取,又可以写入。
2,内部维护了一个大型的byte数组,通过对数组的操作完成读取和写入。
3,通过getFilePointer方法获取指针的位置,还可以通过seek方法设置指针的位置。
4,该对象的内容应该封装了字节输入流和字节输出流。
5,该对象只能操作文件。
通过seek方法操作指针,可以从这个数组中的任意位置上进行读和写
可以完成对数据的修改。
但是要注意:数据必须有规律。
管道流:需要和多线程技术相结合的流对象。
PipedOutputStream
PipedInputStream
用操作基本数据类型值的对象。
DataInputStream
DataOutputStream
IO流体系:
字符流:
Reader
|–BufferedReader:
|–LineNumberReader
|–CharArrayReader
|–StringReader
|–InputStreamReaer
|–FileReader
Writer
|–BufferedWriter
|–CharArrayWriter
|–StringWriter
|–OutputStreamWriter
|–FileWriter
|–PrintWriter
字节流:
InputStream
|–FileInputStream:
|–FilterInputStream
|–BufferedInputStream
|–DataInputStream
|–ByteArrayInputStream
|–ObjectInputStream
|–SequenceInputStream
|–PipedInputStream
OutputStream
|–FileOutputStream
|–FilterOutputStream
|–BufferedOutputStream
|–DataOutputStream
|–ByteArrayOutputStream
|–ObjectOutputStream
|–PipedOutputStream
|–PrintStream
RandomAccessFile:
file.mkdir() //创建目录