类和对象 类相当于C语言的结构体,但结构体内不能有函数,而类可以。类是一个模型,而对象是类实现的具体事物。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Triangle { int a,b,c; int zhouchang () return a + b + c; double area () { double p = 1.0 * (a + b + c) / 2 ; return Math.sqrt(p * (p-a) * (p-b) * (p-c)); } } class TestTriangle { public static void main (String[] args) { Triangle t = new Triangle (); t.a = 3 ; t.b = 4 ; t.c = 5 ; System.out.printf("%d %f\n" ,t.zhouchang(),t.area()); } }
内存分配 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class A { int i; int j; } class TestDemo { public static void main (String[] args) { A aa = new A (); aa.i = 10 ; aa.j = 20 ; System.out.printf("%d,%d\n" ,aa.i,aa.j); } }
访问控制符 将类和对象的例子修改一下,在Triangle中添加一个方法访问a,b,c,使得main函数通过这个方法间接访问a,b,c,这个方法相当于一个按钮,一个接口,一个黑匣子,不能让程序员或用户知道里面的具体实现,保证安全。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Triangle { private int a,b,c; void set (int i, int j, int k) { a = i; b = j; c = k; } int zhouchang () return a + b + c; double area () { double p = 1.0 * (a + b + c) / 2 ; return Math.sqrt(p * (p-a) * (p-b) * (p-c)); } } class TestTriangle_2 { public static void main (String[] args) { Triangle t = new Triangle (); t.set(3 , 4 , 5 ); System.out.printf("%d %f\n" ,t.zhouchang(),t.area()); } }
类的访问控制符
访问控制符
意义
public
可以通过外部访问方式访问类内部的public成员
private
不可以通过外部访问方式访问类内部的private成员
protected
default(默认)
权限高低:protected < public < private
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class A { private int i; public int j; protected int m; private void f () { i = 1 ; j = 2 ; m = 3 ; k(); g(); } protected void k () { i = 1 ; j = 2 ; m = 3 ; f(); g(); } public void g () { i = 1 ; j = 2 ; m = 3 ; f(); k(); } } class TestAccess { public static void main (String[] args) { A aa = new A (); aa.j = 20 ; aa.m = 22 ; } }
不同访问控制符
public
protected
default
private
同包同类
√
√
√
√
同包不同类
√
√
√
同包不同类继承
√
√
√
不同包继承
√
√
不同包无任何关系的类
√
包相当于文件夹,类相当于文件。
构造函数 构造函数要跟类名一样,构造函数没有返回值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class A { private int i; private int j; public A (int a, int b) { i = a; j = b; System.out.printf("有参构造函数被调用了!\n" ); } public A () { System.out.printf("无参构造函数被调用了!\n" ); } public void show () { System.out.printf("i = %d, j = %d\n" ,i ,j); } } class TestConst { public static void main (String[] args) { A aa = new A (1 , 2 ); aa.show(); A ab = new A (); ab.show(); int k; System.out.printf("%d\n" , k); } }
函数的重载 同名的函数通过不同的形参做类似的事情。
函数重载要求:
函数的形参个数
函数的形参顺序
函数的形参数据类型
这三个至少有一个是不一样的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Testadd { static int add (int a, int b) { return a + b; } static int add (int a, int b, int c) { return a + b + c; } static double add (double a, double b) { return a + b; } public static void main (String args[]) { System.out.printf("%d\n" ,add(1 ,2 )); System.out.printf("%d\n" ,add(1 ,2 ,3 )); System.out.printf("%f\n" ,add(1.2 ,2.4 )); } }
关键字 this指针 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class A { public int i; public A (int j) { i = j; } public void show () { System.out.printf("i = %d\n" ,i); } } public class TestThis { public static void main (String[] args) { A aa1 = new A (10 ); A aa2 = new A (20 ); aa1.show(); aa2.show(); } }
aa1和aa2在内存中分别由各自的数据成员i,但是aa1和aa2公用show()方法,show方法如何知道输出的i应该是哪个对象中的i?实际上每个非static方法中都隐含着一个this指针,指向当前正在调用该方法的对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class A { public int i = 99 ; public A (int i) { System.out.printf("%d\n" , i); } } public class TestThis_2 { public static void main (String[] args) { A aa = new A (2 ); System.out.printf("%d\n" , aa.i); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class A { public int i = 99 ; public A (int i) { this .i = i; System.out.printf("%d\n" , i); } } public class TestThis_2 { public static void main (String[] args) { A aa = new A (2 ); System.out.printf("%d\n" , aa.i); } }
static 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class A { public static int i = 10 ; public void show () { System.out.printf("%d\n" ,i); } } class M { public static void main (String[] args) { A aa1 = new A (); A aa2 = new A (); aa1.i = 20 ; aa2.show(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class A { public static int i = 10 ; public static void f () { System.out.printf("2022年1月20日\n" ); } } class M { public static void main (String[] args) { System.out.printf("%d\n" ,A.i); A.f(); A aa = new A (); aa.f(); System.out.printf("%d\n" ,aa.i); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class A { public static int i = 10 ; private static void f () { System.out.printf("2022年1月20日\n" ); } } class M { public static void main (String[] args) { System.out.printf("%d\n" ,A.i); A.f(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class A { public static int i = 10 ; public static void f () { System.out.printf("2022年1月20日\n" ); } public void g () { f(); System.out.printf("GGGG\n" ); } }
用static求出由某个类造出几个对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class A { private int i; private static int cnt = 0 ; public A () { ++cnt; } public A (int i) { this .i = i; ++cnt; } public static int getCnt () { return cnt; } } public class TestStatic { public static void main (String[] args) { System.out.printf("%d\n" ,A.getCnt()); A aa1 = new A (); System.out.printf("%d\n" ,A.getCnt()); A aa2 = new A (2 ); System.out.printf("%d\n" ,A.getCnt()); } }
某类只能造一个对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class A { public int i = 20 ; private static A aa = new A (); private A () { } public static A getA () { return aa; } } public class TestStatic_2 { public static void main (String[] args) { A aa1 = A.getA(); A aa2 = A.getA(); aa1.i = 99 ; System.out.printf("%d\n" ,aa2.i); } }
一个类的属性可以是个类对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class A { public void f () { System.out.printf("哈哈\n" ); } } class C { public int i; public A aa = new A (); public void g () { aa.f(); } } class M { public static void main (String[] args) { C cc = new C (); cc.g(); } }
继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class human { public String name; public int age; } class student { public String name; public int age; public double score; } class graduate { public String name; public int age; public double score; public String tutor; }
这样写很累赘,因为人包括学生,学生包括研究生,所以利用继承是一个很好的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class human { public String name = "张三" ; public int age = 22 ; } class student extends human { public double score = 99.9 ; } class graduate extends student { public String tutor = "李四" ; } public class TestExtends { public static void main (String[] args) { graduate gd = new graduate (); System.out.printf("%s %f\n" ,gd.name, gd.score); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 class A { public int i; protected int j; private int k; public void g () {} private void s () {} protected void b () {} } class B extends A { public void f () { i = 10 ; j = 20 ; g(); b(); } private void m () { i = 10 ; j = 20 ; g(); b(); } } class M { public static void main (String[] args) { B bb = new B (); bb.i = 20 ; bb.j = 30 ; bb.b(); bb.g(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class A { public static int i = 20 ; protected int j; private int k; } class B extends A { private void g () { } } class M { public static void main (String[] args) { B.i = 99 ; System.out.printf("%d\n" ,B.i); } }
子类访问父类成员的三种方式:
在子类内部访问父类成员
通过子类对象名访问父类成员
通过子类的类名访问父类成员
Java只支持单继承,不允许多继承。单继承就是一个类只能有一个父类。
子类可以继承父类所有成员变量和成员方法,但子类永远也无法继承父类的构造函数。在子类的构造方法中可使用语句super(参数列表)调用父类的构造方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class A { public int i; public int j; public A () { } public A (int i, int j) { this .i = i; this .j = j; } } class B extends A { public int k; public B () { } public B (int i, int j, int k) { this .i = i; this .j = j; this .k = k; } } public class TestSuper { public static void main (String[] args) { B bb = new B (1 ,2 ,3 ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class A { public int i; public int j; public A () { } public A (int i, int j) { this .i = i; this .j = j; } } class B extends A { public int k; public B () { } public B (int i, int j, int k) { super (i, j); this .k = k; } } public class TestSuper { public static void main (String[] args) { B bb = new B (1 ,2 ,3 ); System.out.printf("%d,%d\n" ,bb.i,bb.j); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class A { public int i; } class B { public int j; public B (int i, int j) { this .j = j; } public void f (int i) { } } public class TestSuper_2 { public static void main (String[] args) { } }
重写父类的方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class A { public void f () { System.out.printf("AAAA\n" ); } } class B extends A { public void f () { super .f(); System.out.printf("BBBB\n" ); } } public class TestOver { public static void main (String[] args) { B bb = new B (); bb.f(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class A { public void f () { System.out.printf("AAAA\n" ); } public void f (int i) { System.out.printf("hhhh\n" ); } } class B extends A { public void f () { super .f(); f(10 ); System.out.printf("BBBB\n" ); } } public class TestOver { public static void main (String[] args) { B bb = new B (); bb.f(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class A { public void f () { System.out.printf("AAAA\n" ); } } class B extends A { private void f () { System.out.printf("BBBB\n" ); } } public class TestOver { public static void main (String[] args) { B bb = new B (); bb.f(); } }
方法重写指在子类中重新定义父类中已有的方法。重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 class human { private String name; private int age; public human () { } public human (String name, int age) { this .name = name; this .age = age; } public void setName (String name) { this .name = name; } public void setAge (int age) { this .age = age; } public String getInfor () { String strInf = name + ": " +age; return strInf; } } class student extends human { public String school; public student () {} public student (String name, int age, String school) { super (name, age); this .school = school; } public void setschool (String school) { this .school = school; } public String getInfor () { String strInf = super .getInfor() + ": " + school; return strInf; } } public class TestStudent { public static void main (String[] args) { student st1 = new student ("张三" , 22 , "星星大学" ); System.out.printf("%s\n" , st1.getInfor()); } }
多态 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class A { protected void f () { System.out.printf("AAAA\n" ); } } class B extends A { public void f () { System.out.printf("BBBB\n" ); } } public class TestPoly_2 { public static void main (String[] args) { A aa = new A (); B bb = new B (); aa.f(); aa = bb; aa.f(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class A { public void f () { System.out.printf("AAAA\n" ); } } class B extends A { public void f () { System.out.printf("BBBB\n" ); } } class C extends B { public void f () { System.out.printf("CCCC\n" ); } } class D extends C { public void f () { System.out.printf("DDDD\n" ); } } public class TestPoly_3 { public static void g (A aa) { aa.f(); } public static void main (String[] args) { A aa = new A (); B bb = new B (); C cc = new C (); D dd = new D (); g(aa); g(bb); g(cc); g(dd); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class A { public void f () { System.out.printf("AAAA\n" ); } } class B extends A { public void f () { System.out.printf("BBBB\n" ); } public void g () { System.out.printf("GGGG\n" ); } } public class TestPoly_4 { public static void main (String[] args) { A aa = new A (); B bb = new B (); aa = bb; bb = (B)aa; bb.g(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class A { public void f () { System.out.printf("AAAA\n" ); } } class B extends A { public void f () { System.out.printf("BBBB\n" ); } public void g () { System.out.printf("GGGG\n" ); } } public class TestPoly_4 { public static void main (String[] args) { A aa = new A (); B bb = new B (); aa = bb; } }
子类对象可以直接赋给父类引用,但父类对象在任何情况下都不可以直接赋给子类使用。通过父类引用只能访问子类对象从父类继承过来的成员,不能访问子类对象所特有的成员。
抽象类 抽象类通常用来作为一个类族的最顶层的父类,用最底层的类表示现实中的具体事物,用最顶层的类表示该类族所有事物的共性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 abstract class A { abstract public void f () ; } abstract class B { public void g () {} } public class TestAbstract { public static void main (String[] args) {} }
1 2 3 4 5 6 7 8 9 10 11 12 13 class A { } abstract class B extends A { } public class TestAbsPoly { public static void main (String[] args) {} }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 abstract class A { abstract public void f () ; } class B extends A { public void f () { System.out.printf("BBBB\n" ); } } abstract class C extends A { } public class TestAbsPoly { public static void main (String[] args) { B bb = new B (); bb.f(); A aa; aa = bb; aa.f(); } }
Final Final可以修饰
整个类
类中的若干个属性
类中的若干个方法:表示该方法可以被子类继承,但不可以被子类重写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class A { } class B extends A { } public class TestFinal { public static void main (String[] args) { } }
1 2 3 4 5 6 7 8 9 10 11 12 class A { final public int i = 10 ; } public class TestFinal { public static void main (String[] args) { } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class A { final public int i; public A () { i = 22 ; } public void f () { } } public class TestFinal { public static void main (String[] args) { } }
接口 接口就是抽象方法和常量值的集合。从本质上讲,接口是一种特殊的抽象类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 interface It { public void f () ; } abstract class B { public void f () { } } public class A { public static void main (String[] args) { } }
接口的注意事项
接口中定义的属性必须是public static final
的,而接口中定义的方法则必须是public abstract
的,因此这些修饰符可以部分或全部省略。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 interface It { public static final int i = 20 ; public abstract void f () ; } public class A { public static void main (String[] args) { } }
接口中定义的属性的值在实现类中不能被更改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 interface It { int i = 10 ; } class A implements It { public A (int j) { } } public class B { public static void main (String[] args) {} }
一个类只能实现(implements
)某个接口,不能继承(extends
)某个接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 interface It { public static final int i = 20 ; public abstract void f () ; } abstract class A implements It { } class C implements It { public void f () { System.out.printf("i = %d\n" , i); } } public class B { public static void main (String[] args) { C cc = new C (); cc.f(); } }
接口可以继承接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 interface It1 { } interface It2 { } interface It3 extends It1 , It2{ } public class C { public static void main (String[] args) { } }
接口允许多继承。(看4)
如果一个类只实现了一个接口的部分方法,则该类必须得声明为抽象类。(看3)
一个类可以在继承一个父类的同时实现一个或多个接口,但extends
关键字必须得在implements
之前。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class A {} interface It1 {} interface It2 {} interface It3 extends It1 , It2{} interface It4 { int i = 20 ; } class T extends A implements It4 , It3{} public class TestIter { public static void main (String[] args) {} }
不可以new
接口对象,但可以定义一个接口引用类型的变量并将其指向实现接口的对象,达到多态的目的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 interface It { void f () ; } class A implements It { public void f () { System.out.printf("AAAA\n" ); } public void g () {} } class D { publc static void main (String[] args) { It it; it = new A (); it.f(); } }
接口的作用
通过接口可以实现不相关类的相同行为
接口提供了不同对象进行协作的平台
接口可以实现多继承,从一个程度上弥补了类只能单继承的缺陷
接口是我们了解一个类功能的重要途径
包 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package zhangsan.lisi;class A { public void f () { System.out.printf("AAAA\n" ); } } class M { public static void main (String[] args) { A aa = new A (); aa.f(); new A ().f(); } }
同包不同类的相互访问 1 2 3 4 5 6 7 8 9 class A { public void f () { System.out.printf("AAAA\n" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 class B { public static void main (String[] args) { A aa = new A (); aa.f(); } }
因为类A和类B默认是在同一个无名的包中,所以彼此可以相互访问。只要是非私有成员都可以被同包的另一个类访问。
不同包类的相互访问 1 2 3 4 5 6 7 8 9 package zhangsan.lisi;public class A { public void f () { System.out.printf("AAAA\n" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package v5le0n9;import zhangsan.lisi.A;public class B { public static void main (String[] args) { A aa = new A (); aa.f(); } }
不同包的类继承 1 2 3 4 5 6 7 8 9 10 11 12 13 package zhangsan.lisi;public class A { public void g () { System.out.printf("GGGG\n" ); } protected void b () { System.out.printf("BBBB\n" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package v5le0n9;import zhangsan.lisi.*;class B extends A { public void f () { g(); b(); } } class M { public static void main (String[] args) { B bb = new B (); bb.f(); bb.g(); } }
普通jar包的生成 假设需要将v5le0b9
和zhangsan
打包,就新建一个文件夹将v5le0n9
和zhangsan
放进去,确保文件夹只有需要打包的内容。
在命令窗口进入新文件夹目录,输入jar -cvf T.jar *
,生成叫作T.jar的包。
如何使用jar包中的类 1 2 3 4 5 6 7 8 9 import zhangsan.lisi.A;public class Test { public static void main (String[] args) { A aa = new A (); aa.g(); } }
如果jar包和新编辑的java文件不在同一个目录下,则在命令窗口编译前,先设置classpath,再编译运行。
1 set classpath=xxxx\xxx\T.jar;
异常 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package v5le0n9;class A { int divide (int a, int b) { int m; m = a / b; return m; } } public class TestExcep { public static void main (String[] args) { A aa = new A (); aa.divide(6 , 2 ); System.out.printf("看得见我吗?" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package v5le0n9;class A { int divide (int a, int b) { int m; m = a / b; return m; } } public class TestExcep_2 { public static void main (String[] args) { A aa = new A (); try { aa.divide(6 , 0 ); } catch (ArithmeticException e) { System.out.printf("除数不能为零\n" ); } System.out.printf("看得见" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class TestExcep_3 { public static void main (String[] args) { int m; try { m = 2 ; System.out.printf("m = %d\n" , m); } catch (Exception e) { } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package v5le0n9;class A { int divide (int a, int b) { int m = 0 ; try { m = a / b; } catch (ArithmeticException e) { System.out.printf("除数不能为零\n" ); } return m; } } public class TestExcep_4 { public static void main (String[] args) { new A ().divide(6 , 0 ); } }
Error和Exception的区别:Error表示语法错误,而Exception表示程序运行时出现的错误。
为什么需要异常 根据上面那个例子,用if…else…语句也可实现,所以为什么需要异常?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.util.*;public class TestExcep_5 { public static void main (String[] args) { int i; Scanner sc = new Scanner (System.in); i = sc.nextInt(); System.out.printf("i = %d\n" , i); } }
假如输入的不是整型,会报异常。此时,用if…else…语句显得很困难。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.*;public class TestExcep_6 { public static void main (String[] args) { int i; Scanner sc = new Scanner (System.in); try { i = sc.nextInt(); System.out.printf("i = %d\n" , i); } catch (InputMismatchException e) { System.out.printf("输入数据不合法\n" ); } } }
异常的处理机制
当Java程序运行时出现问题时,系统会自动检测到该错误,并立即生成一个与该错误对应的异常对象。
然后把该异常对象提交给Java虚拟机。
Java虚拟机会自动寻找相应的处理代码来处理这个异常,如果没有找到,则由Java虚拟机做一些简单的处理后,程序被强行终止。
程序员可以自己编写代码来捕捉可能出现的异常,并编写代码来处理相应的异常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package v5le0n9;class A { int divide (int a, int b) { return a / b; } public void f () { g(); } public void g () { divide(6 , 0 ); } } public class TestExcep_7 { public static void main (String[] args) { new A ().f(); } }
在调试时,可以用_printStackTrace
观察哪里出错。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package v5le0n9;class A { int divide (int a, int b) { return a / b; } public void f () { g(); } public void g () { divide(6 , 0 ); } } public class TestExcep_8 { public static void main (String[] args) { try { new A ().f(); } catch (Exception e) { e.printStackTrace(); } } }
常见异常 空指针异常 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package v5le0n9;class Person { public int age; } public class TestNullPointerException { public static void main (String[] args) { Person p = null ; System.out.println(p.age); } }
下标越界异常 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package v5le0n9;public class TestIndexOutOf { public static void main (String[] args) { String friends[] = {"Lisa" , "Bily" , "Kessy" }; for (int i=0 ; i<5 ; i++) { System.out.println(friends[i]); } System.out.println("\nThis is the end.\n" ); } }
算数异常 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package v5le0n9;class A { int divide (int a, int b) { int m; m = a / b; return m; } } public class TestExcep { public static void main (String[] args) { A aa = new A (); aa.divide(6 , 2 ); System.out.printf("看得见我吗?" ); } }
异常的分类
Error是系统错误,程序员无法处理这些异常
Exception是程序员可以捕获并处理的异常
RuntimeException的子类异常是可以处理也可以不处理的异常
凡是继承自Exception但又不是RuntimeException子类的异常我们都必须捕捉并进行处理
有些异常在编译时就报错。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.io.*;class A { public void f () { throw new IOException (); } public void g () { throw new ArithmeticException (); } } public class Exception { public static void main (String[] args) { A aa = new A (); } }
处理异常的两种方式 try…catch… 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.io.*;class A { public void f () { try { throw new IOException (); } catch (IOException e) { } } }
throws 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.io.*;class A { public void f () throws IOException { } } public class Exception_2 { public static void main (String[] args) { A aa = new A (); try { aa.f(); } catch (IOExeption e) { } } }
异常处理步骤 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 try { } catch (ExceptionName1 e){ } catch (ExceptionName2 e){ } finally { }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class A { int divide (int a, int b) { int m; m = a / b; return m; } } public class TestExcep_9 { try { new A ().divide(6 , 0 ); } catch (ArithmeticException e) { System.out.printf("huuu\n" ); } catch (ArrayIndexOutOfBoundsException e) { System.out.printf("yooooo\n" ); } finally { System.out.printf("hhhh\n" ); } }
Finally的作用 无论try所指定的程序块中是否抛出异常,也无论catch语句的异常类型是否与所抛出的异常类型一致finally中的代码都会执行。finally语句为异常处理提供一个统一的出口,使得在控制流程转到程序的其它部分之前,能够对程序的装药作统一的管理。通常在finally语句中可以进行资源的清除工作,如关闭打开的文件、删除临时文件等。
自定义异常 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package v5le0n9;class DivisorIsZeroException extends Exception { public DivisorIsZeroException (String name) { super (name); } } class A { public int divide (int a, int b) throws DivisorIsZeroException { int m = 0 ; if (0 == b) throw new DivisorIsZeroException ("除数不能为零" ); else m = a / b; return m; } } public class TestExcep_10 { public static void main (String[] args) { A aa = new A (); try { aa.divide(6 , 0 ); } catch (Exception e) { e.printStackTrace(); } } }
异常的范围 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class A extends Exception {} class B extends Exception {} class C extends Exception {} class M { void f () throws A,B {} } class N extends M { void f () throws A,B { } } class Test { public void k (M mm) { try { mm.f(); } catch (A aa) {} catch (B bb) {} } } class TestExtendExce { public static void main (String[] args) { M m = new M (); N n = new N (); } }
注意事项
toString 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class A { public String toString () { return "hhhh\n" ; } } public class TestObject { public static void main (String[] args) { A aa = new A (); System.out.printf("%s\n" , aa.toString()); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package v5le0n9;class Point_ { public int x, y; public Point_ (int x, int y) { this .x = x; this .y = y; } } public class TestPoint { public static void main (String[] args) { Point_ p = new Point_ (1 , 2 ); System.out.printf("%s\n" , p); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package v5le0n9;class Point_ { public int x, y; public Point_ (int x, int y) { this .x = x; this .y = y; } public String toString () { return "[" + x + "," + y + "]" ; } } public class TestPoint { public static void main (String[] args) { Point_ p = new Point_ (1 , 2 ); System.out.printf("%s\n" , p); System.out.println(p); } }
equals 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class A { public int i; public A (int i) { this .i = i; } } public class TestStringEquals { public static void main (String[] args) { A aa1 = new A (2 ); A aa2 = new A (2 ); System.out.println(aa1); System.out.println(aa2); aa1.equals(aa2); System.out.println(aa1.equals(aa2)); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class A { public int i; public A (int i) { this .i = i; } public boolean equals (Object obj) { A aa = (A)obj; if (this .i == aa.i) return true ; else return false ; } } public class TestStringEquals_2 { public static void main (String[] args) { A aa1 = new A (2 ); A aa2 = new A (2 ); System.out.println(aa1.equals(aa2)); } }
String类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class TestString_1 { public static void main (String[] args) { String str1 = new String ("China" ); String str2 = new String ("China" ); System.out.println(str1.equals(str2)); if (str1 == str2) System.out.println("str1 == str2" ); else System.out.println("str1 != str2" ); String str3 = "Chinese" ; String str4 = "Chinese" ; if (str3 == str4) System.out.println("str3 == str4" ); else System.out.println("str3 != str4" ); } }
String类常用方法
String类方法
用途
public char charAt(int index)
返回字符串中第index个字符
public int length()
返回字符串的长度
public int indexOf(String str)
返回字符串中出现str的第一个位置
public int indexOf(String str, int fromIndex)
返回字符串中从fromIndex开始出现str的第一个位置
public boolean equalsIgnoreCase(String another)
比较字符串与another是否一样(忽略大小写)
public String replace(char oldChar, char newChar)
在字符串中用newChar字符替换oldChar字符
public boolean startsWith(String prefix)
判断字符串是否以prefix字符串开头
public booleab endsWith(String suffix)
判断字符串是否以suffix字符串结尾
public String toUpperCase()
返回一个字符串为该字符串的大写形式
public String toLowerCase()
返回一个字符串为该字符串的小写形式
public String substring(int beginIndex)
返回该字符串从beginIndex开始到结尾的子字符串
public String substring(int beginIndex, int endIndex)
返回该字符串从beginIndex开始到endIndex结尾的字符串
public static String valueOf(…)
将基本类型数据转换为字符串
public String[] split(String regex)
将一个字符串按照指定的分隔符分分隔,返回分隔后的字符串数组
常用方法举例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class TestString_2 { public static void main (String[] args) { int i = 123 ; String str = String.valueOf(i); System.out.printf("str = %s\n" , str); str = "456" ; try { i = Integer.parseInt(str); System.out.printf("i = %d\n" , i); } catch (NumberFormatException e) { System.out.println("数字格式化异常!" ); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class Test { public static void main (String[] args) { String s1 = "v5le0n9" , s2 = "V5LE0N9" ; System.out.println(s1.charAt(1 )); System.out.println(s2.length()); System.out.println(s1.indexOf("0n9" )); System.out.println(s1.indexOf("0N9" )); System.out.println(s1.equals(s2)); System.out.println(s1.equalsIgnoreCase(s2)); System.out.println(s1.toUpperCase()); System.out.println(s2.toLowerCase()); System.out.println(s2.substring(3 )); System.out.println(s2.substring(3 ,5 )); String s = "世界如此美好!" ; String sr = s.replace("世界" , "生活" ); System.out.println(sr); System.out.println(s.startsWith("世界" )); System.out.println(s.endsWith("美好" )); String st = " hello world " ; System.out.println(st.trim()); int j = 1234567 ; String sNumber = String.valueOf(j); System.out.println("j是" +sNumber.length()+"位数" ); String str = "Mary,F,1976" ; String[] sPlit = str.split("," ); for (int i=0 ; i<sPlit.length; i++) { System.out.println(sPlit[i]); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 public class TestString_3 { public static void main (String[] args) { String str = "abAM,!123" ; int cntU = 0 ; int cntL = 0 ; int cntOther = 0 ; int i; for (i=0 ; i<str.length(); i++) { char ch = str.charAt(i); if (ch>='a' && ch<='z' ) cntL++; else if (ch>='A' && ch<='Z' ) cntU++; else cntOther++; } for (i=0 ; i<str.length(); i++) { char ch = str.charAt(i); if (Character.isUpperCase(ch)) cntU++; else if (Character.isLowerCase(ch)) cntL++; else cntOther++; } String s1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ; String s2 = "abcdefghijklmnopqrstuvwxyz" ; for (i=0 ; i<str,length(); i++) { char ch = str.charAt(i); if (-1 != s1.indexOf(ch)) cntU++; else if (-1 != s2.indexOf(ch)) cntL++; else cntOther++; } System.out.printf("大写字母个数为%d\n" ,cntU); System.out.printf("小写字母个数为%d\n" ,cntL); System.out.printf("其它字符个数为%d\n" ,cntOther); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class TestString_4 { public static void main (String[] args) { String str1 = "abcabcbacbac" ; String str2 = "abc" ; int index = -1 ; int cnt = 0 ; index = str1.indexOf(str2); while (-1 != index) { cnt++; index = str1.indexOf(str2, index+str2.length()); } System.out.printf("%d\n" ,cnt); } }
printf和println的区别 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class Dian { public int x, y; public Dian (int x,int y) { this .x = x; this .y = y; } public String toString () { return "[" + x + "," + y + "]" ; } } public class TestPrint { public static void main (String[] args) { Dian d = new Dian (3 , 2 ); System.out.printf("%s\n" , d); System.out.println(d); int i, j, k; i = 1 ; j = 2 ; k = 3 ; System.out.printf("%d的值 + %d的值 是 %d\n" , i, j, k); System.out.println(i + "的值" + j + "的值 是 " + k); int m = 47 ; System.out.println(m); System.out.printf("%d\n" , m); System.out.printf("十进制数字%d用十六进制表示是:%#X\n" , m, m); System.out.println("十进制数字" + m + "用十六进制表示是:0X" + Integer.toHexString(m).toUpperCase()); System.out.printf("%b\n" , "abc" .equals("zhangsan" )); System.out.printf("%d\n" , "abc" .length()); } }
StringBuffer String类对象一旦创建就不可更改,因为String类用final修饰了。如果经常对字符串内容进行修改,则使用StringBuffer。
StringBuffer类的构造函数
构造函数
含义
public StringBuffer()
创建一个空的没有任何字符的StringBuffer对象
public StringBuffer(int capacity)
创建一个不带字符,但具有指定初始容量的字符串缓冲区
public StringBuffer(String str)
创建一个StringBuffer对象,包含与str对象相同的字符序列
StringBuffer常用方法
常用方法
含义
public StringBuffer append(…)
为该StringBuffer对象添加字符序列,返回添加后的该StringBuffer对象引用
public StringBuffer insert(…)
为该StringBuffer对象在指定位置插入字符序列,返回修改后的该StringBuffer对象引用
public StringBuffer delete(int start, int end)
删除从start开始到end-1为止的一段字符序列,返回修改后的该StringBuffer对象引用
public StringBuffer reverse()
将字符序列逆序,返回修改后的该StringBuffer对象引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class TestStringBuffer { public static void main (String[] args) { StringBuffer sb = new StringBuffer (); sb.append("abc" ); sb.append("123" ); System.out.println("sb = " + sb); sb.insert(3 ,"--" ); System.out.println("sb = " + sb); sb.delete(2 , 6 ); System.out.println("sb = " + sb); sb.reverse(); System.out.println("sb = " + sb); String str = sb.toString(); System.out.println("str = " + str); } }
1 2 3 4 5 6 7 8 9 public class TestStringBuffer_2 { public static void main (String[] args) { StringBuffer sb = new StringBuffer ("zhangsan" ); System.out.println(sb); } }
数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public class TestArray { public static void mian (String[] args) { int [] arr1; arr1 = new int [3 ]; arr1[0 ] = 0 ; arr1[1 ] = 1 ; arr1[2 ] = 2 ; showArr(arr1); int [] arr2 = new int []{0 ,1 ,2 }; showArr(arr2); int [] arr6 = {0 ,1 ,2 }; showArr(arr6); arr6 = new int []{5 ,4 ,3 ,2 ,1 }; showArr(arr6); } public static void showArr (int [] arr) { for (int i=0 ; i<arr.length; i++) System.out.println(arr[i]); } }
创建并使用基本类型数组 1 2 3 4 5 6 7 8 9 10 11 12 13 public class TestArray_2 { public static void main (String[] args) { int [] s; s= new int [10 ]; for (int i=0 ; i<10 ; i++) { s[i] = 2 * i + 1 ; System.out.println(s[i]); } } }
创建并使用引用类型数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class MyDate { private int day; private int month; private int year; public MyDate (int d, int m, int y) { day = d; month = m; year = y; } public void display () { System.out.println(day + "-" + month + "-" + year); } } public class TestArray_3 { public static void main (String[] args) { MyDate[] m; m = new MyDate [10 ]; for (int i=0 ; i<10 ; i++) { m[i] = new MyDate (i+1 , i+1 , 1990 +i); m[i].display(); } } }
数组的拷贝 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class TestArrayCopy { public static void main (String[] args) { int [] a = {1 ,2 ,3 ,4 ,5 }; int [] b = {-1 ,-2 ,-3 ,-4 ,-5 }; System.arraycopy(a,0 ,b,1 ,2 ); System.out.println("a = " ); for (int i=0 ; i<a.length; i++) System.out.println(a[i]); System.out.println("b = " ); for (i=0 ; i<b.length; i++) System.out.println(b[i]); } }
数组的排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.*;public class TestArraySort { public static void main (String[] args) { int [] data = {1 ,3 ,5 ,7 ,2 ,4 ,6 ,8 ,10 ,9 }; System.out.println("排序前数组data中的内容是:" ); showArray(data); Arrays.sort(data); System.out.println("排序后数组data中的内容是:" ); showArray(data); } public static void showArray (int [] data) { for (int e : data) System.out.printf("%d\t" , e); System.out.println("" ); } }
线程 线程是一个程序里的不同执行路径。
创建线程的两种方式 创建线程的第一种方式:
创建一个继承Thread的类(假定类名为A),并重写Thread的run方法
构造一个A类对象(假定对象名为aa)
调用aa的start方法(start方法是从Thread继承过来的)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class A extends Thread { public void run () { while (true ) System.out.println("AAAA" ); } } public class TestThread { public static void main (String[] args) { A aa = new A (); aa.start(); while (true ) { System.out.println("BBBB" ); } } }
创建线程的第二种方式:
定义一个实现了Runnable接口的类(假定为A)
创建A类对象aa
利用aa构造一个Thread对象t
调用t中的start方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class A implements Runnable { public void run () { while (true ) System.out.println("AAAA" ); } } public class TestThread_2 { public static void main (String[] args) { A aa = new A (); Thread t = new Thread (aa); t.start(); while (true ) { System.out.println("BBBB" ); } } }
线程的常用方法
常用方法
含义
public final void setName(String name)
设置当前线程的名字
public static Thread currentThread()
返回对当前正在执行的线程对象的引用
public final String getName()
返回当前线程的名字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class A extends Thread { public void run () { System.out.printf("%s在执行\n" , Thread.currentThread().getName()); } } public class TestThread_3 { public static void main (String[] args) { A aa1 = new A (); aa1.setName("v5le0n9" ); aa1.start(); A aa2 = new A (); aa2.setName("l30n9ry0n" ); aa2.start(); A aa3 = new A (); aa3.setName("凉凉" ); aa3.start(); System.out.printf("%s在执行\n" , Thread.currentThread().getName()); } }
线程的控制
方法
功能
isAlive()
判断线程是否还“活”着,即线程是否还未终止
getPriority()
获得线程的优先级数值
setPriority()
设置线程的优先级数值
Thread.sleep()
将当前线程睡眠指定毫秒数
join()
调用某线程的该方法,将当前线程与该线程“合并”,即等待该线程结束,再恢复当前线程的运行
yield()
让出CPU,当前线程进入就绪队列等待调度
wait()
当前线程进入对象的wait pool
notify()/notifyAll()
唤醒对象的wait pool中的一个/所有等待线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class TestPriority { public static void main (String[] args) { Thread t1 = new Thread (new T1 ()); Thread t2 = new Thread (new T2 ()); t1.setPriority(Thread.NORM_PRIORITY + 3 ); t1.start(); t2.start(); } } class T1 implements Runnable { public void run () { for (int i=0 ; i<100 ; i++) System.out.println("T1: " + i); } } class T2 implements Runnable { public void run () { for (int i=0 ; i<100 ; i++) System.out.println("----T2: " + i); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class TestSleep { public static void main (String[] args) { A aa = new A (); Thread tt = new Thread (aa); tt.start(); } } class A implements Runnable { public void run () { for (int i=0 ; i<10 ; i++) { System.out.println(Thread.currentThread().getName() + " " + i); try { Thread.sleep(1000 ); } catch (Exception e) {} } } }
无论是继承Thread类的run方法还是实现Runnable接口的run方法,都不能抛出任何异常。因为重写方法抛出异常的范围不能大于被重写方法抛出的异常范围。
1 2 3 4 5 6 7 8 9 10 class A implements Runnable { public void run () {} } class B extends Thread { public void run () {} }
线程的让步 让出CPU,给其它线程执行的机会。让运行中的线程主动放弃当前获得的CPU处理机会,但不是使该线程阻塞,而是使之转入就绪状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class TestYield { public static void main (String[] args) { MyThread mt = new MyThread (); Thread t1 = new Thread (mt); Thread t2 = new Thread (mt); t1.setName("线程A" ); t2.setName("线程B" ); t1.start(); t2.start(); } } class MyThread implements Runnable { public void run () { for (int i=1 ; i<=100 ; i++) { System.out.println(Thread.currentThread().getName() + ": " + i); if (0 == i%10 ) { Thread.yield(); } } } }
线程的串行化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class TestJoin { public static void main (String[] args) { MyRunner r = new MyRunner (); Thread t = new Thread (r); t.start(); try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); } for (int i=0 ; i<50 ; i++) System.out.println("主线程:" + i); } } class MyRunner implements Runnable { public void run () { for (int i=0 ; i<50 ; i++) System.out.println("子线程:" + i); } }
生命周期控制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class TestShutThread { public static void main (String[] args) { A aa = new A (); Thread tt = new Thread (aa); tt.start(); try { Thread.sleep(1000 ); } catch (Exception e) { e.printStackTrace(); } aa.shutDown(); } } class A implements Runnable { private boolean flag = true ; public void run () { while (flag) System.out.println("AAAA" ); } public void shutDown () { this .flag = false ; } }
线程同步问题产生的原因 假设一个买票程序
1 2 3 4 5 if (票数 > 0 ){ 买一张票; 票数减一; }
当票数只剩一张时,A买了一张票,此时线程切换到B,B显示剩一张票,他也买了一张票。这样就会导致一张票卖给了两个人。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class A implements Runnable { private static int tickets = 100 ; public void run () { while (true ) { if (tickets > 0 ) { System.out.printf("%s线程正在卖出第%d张票\n" , Thread.currentThread().getName(), tickets); tickets--; } else break ; } } } public class TestTickets { public static void main (String[] args) { A aa1 = new A (); Thread t1 = new Thread (aa1); t1.start(); A aa2 = new A (); Thread t2 = new Thread (aa2); t2.start(); } }
数据库有“事务”的概念,也就是将所有操作放到事务里,这些操作要不就全部执行成功,要不就全部执行失败。推广到上面代码,即将第8行到第14行放到“事务”里。
买票程序 synchronized关键字 synchronized可以用来修饰一个方法,也可以修饰一个方法内部的某个代码块。
1 2 3 4 5 synchronized (类对象名aa){ 同步代码块 }
功能:判断aa是否已经被其他线程霸占,如果发现已经被其他线程霸占,则当前线程陷入等待中,如果发现aa没有被其他线程霸占,则当前线程霸占aa对象,并执行同步代码块,在当前线程执行代码块时,其他线程将无法再执行同步代码块,当前线程执行完同步代码块后,会自动释放对aa对象的霸占,此时其他线程会相互竞争对aa的霸占,最后CPU会选择其中的某一个线程执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class A implements Runnable { private int tickets = 100 ; public void run () { while (true ) { synchronized (this ) { if (tickets > 0 ) { System.out.printf("%s线程正在卖出第%d张票\n" , Thread.currentThread().getName(), tickets); tickets--; } else break ; } } } } public class TestTickets_2 { public static void main (String[] args) { A aa = new A (); Thread t1 = new Thread (aa); t1.start(); Thread t2 = new Thread (aa); t2.start(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class A extends Thread { private static int tickets = 100 ; private static String str = new String ("v5le0n9" ); public void run () { while (true ) { synchronized (str) { if (tickets > 0 ) { System.out.printf("%s线程正在卖出第%d张票\n" , Thread.currentThread().getName(), tickets); tickets--; } else break ; } } } } public class TestTickets_3 { public static void main (String[] args) { A aa1 = new A (); aa1.start(); A aa2 = new A (); aa2.start(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class A extends Thread { private static int tickets = 100 ; private static String str = new String ("v5le0n9" ); public void run () { while (true ) { synchronized (str) { if (tickets > 0 ) { System.out.printf("%s线程正在卖出第%d张票\n" , Thread.currentThread().getName(), tickets); tickets--; } else break ; } } } } public class TestTickets_4 { public static void main (String[] args) { A aa1 = new A (); aa1.start(); A aa2 = new A (); aa2.start(); } }
生产消费 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Stack { int index = 0 ; char [] data = new char [6 ]; public void push (char c) { data[index] = c; index++; } public char pop () { index--; return data[index]; } }
压栈出栈如果不同步会出错。当push执行的时候不能执行pop,反之同理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 class SynStack { private char [] data = new char [6 ]; private int cnt = 0 ; public synchronized void push (char ch) { while (cnt == data.length) { try { this .wait(); } catch (Exception e) {} } this .notify(); data[cnt] = ch; ++cnt; System.out.printf("生产线程正在生产第%d个产品,该产品是:%c\n" , cnt, ch); } public synchronized char pop () { char ch; while (cnt == 0 ) { try { this .wait(); } catch (Exception e) {} } this .notify(); ch = data[cnt-1 ]; System.out.printf("---消费线程正在消费第%d个产品,该产品是:%c\n" , cnt, ch); --cnt; return ch; } } class Producer implements Runnable { private SynStack ss = null ; public Producer (SynStack ss) { this .ss = ss; } public void run () { char ch; for (int i=0 ; i<20 ; i++) { ch = (char )('a' + i); ss.push(ch); } } } class Consumer implements Runnable { private SynStack ss = null ; public Consumer (SynStack ss) { this .ss = ss; } public void run () { for (int i=0 ; i<20 ; i++) { try { Thread.sleep(200 ); } catch (Exception e) {} ss.pop(); } } } public class TestPC { public static void main (String[] args) { SynStack ss = new SynStack (); Producer p = new Producer (ss); Consumer c = new Consumer (ss); Thread t1 = new Thread (p); t1.start(); Thread t2 = new Thread (c); t2.start(); } }
awt展望 1 2 3 4 5 6 7 8 9 10 11 import java.awt.*;public class TestCom { public static void main (String[] args) { Frame f = new Frame (); f.setSize(400 , 400 ); f.setBackground(Color.GREEN); f.setVisible(true ); } }
GUI(图形化用户界面) 组件 组件是图形用户界面的基本组成元素,凡是能够以图形化方式显示在屏幕上并能够与用户进行交互的对象均为组件,如菜单、按钮、标签、文本框、滚动条等。
组件分类
java.awt.Component
java.awt.MenuComponent
抽象类java.awt.Component是除菜单相关组件之外所有Java AWT组件类的根父类,该类规定了GUI组件的基本特性,如尺寸、位置和颜色效果等,并实现了作为一个GUI部件所应具备的基本功能。
容器 组件通常不能独立地显示出来,必须将组件放在一定的容器中才可以显示出来。
有一类特殊的组件是专门用来包含其他组件的,这类组件叫容器,java.awt.Container是所有容器的父类,java.awt.Container继承自java.awt.Component
容器类对象本身也是一个组件,具有组件的所有性质,但组件不一定是容器。
Frame常用方法
常用方法
功能
public void setBounds(int x, int y, int width, int height)
设置窗体的位置和大小,x和y表示窗体左上角距离屏幕水平和垂直距离,width和height是窗体自身的宽度和高度
public void setSize(int width, int heigth)
设置窗体的大小,width和height是窗体自身的宽度和高度
public void setVisible(boolean flag)
设置窗体是否可见,true表示可见。false表示不可见
public void setBackground(Color c)
设置窗体的背景色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.awt.*;public class TestFrame { public static void main (String[] args) { Frame f = new Frame ("v5le0n9" ); f.setSize(200 , 200 ); f.setLocation(300 , 300 ); f.setBackground(Color.RED); f.setVisible(true ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.awt.Frame;public class TestFrame_2 { public static void main (String[] args) { Frame f = new Frame ("v5le0n9" ); f.setize(200 ,200 ); f.setVisible(true ); try { Thread.sleep(2000 ); } catch (InterruptedException e) { System.out.println(e.getMessage()); } f.setLocation(200 , 200 ); try { Thread.sleep(2000 ); } catch (InterruptedException e) { System.out.println(e.getMessage()); } f.setVisible(false ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.awt.*;public class TestFrame_3 { public static void main (String[] args) { MyFrame f1 = MyFrame(100 ,100 ,200 ,200 ,Color.BLUE); MyFrame f2 = MyFrame(300 ,100 ,200 ,200 ,Color.YELLOW); MyFrame f3 = MyFrame(100 ,300 ,200 ,200 ,Color.GREEN); MyFrame f4 = MyFrame(300 ,300 ,200 ,200 ,Color.MAGENTA); } } class MyFrame extends Frame { public static int id = 0 ; MyFrame(int x, int y, int w, int h, Color color) { super ("MyFrame " + (id++)); setBackground(color); setLayout(null ); setBounds(x, y, w, h); setVisible(true ); } }
Panel panel是容纳其他组件的组件,即容器。panel不能单独存在,必须被添加到其他容器中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.awt.*;public class TestPanel { public static void main (String[] args) { Frame f = new Frame ("Java Frame with Panel" ); Panel p = new Panel (); f.setLayout(null ); f.setBounds(300 ,300 ,500 ,500 ); f.setBackground(new Color (100 ,100 ,102 )); p.setBounds(300 /2 ,300 /2 ,500 /2 ,500 /2 ); p.setBackground(new Color (204 ,204 ,255 )); f.add(p); f.setVisible(true ); } }
布局管理器 容器对其中所包含组件的排列方式,包括组件的位置和大小设定,被称为容器的布局(Layout)。
为了使图形用户界面具有良好的平台无关性,Java语言提供了布局管理器来管理容器的布局,而不建议直接设置组件在容器中的位置和尺寸。
每个容器都有一个默认的布局管理器,当容器需要对某个组件进行定位或判断大小尺寸时,就会自动调用其对应的布局管理器。
在AWT中,常见的布局管理器有:
BorderLayout
FlowLayout
GridLayout
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import java.awt.*;public class TestFlowLayout { public static void main (String[] args) { Frame f = new Frame ("Flow Layout" ); Button button1 = new Button ("OK" ); Button button2 = new Button ("Open" ); Button button3 = new Button ("Close" ); f.setLayout(new FlowLayout (FlowLayout.CENTER)); f.add(button1); f.add(button2); f.add(button3); f.setSize(300 ,400 ); f.setVisible(true ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.awt.*;public class TestFlowLayout_2 { public static void main (String[] args) { Frame f = new Frame ("Java Frame" ); FlowLayout l = new FlowLayout (FlowLayout.CENTER, 30 , 30 ); f.setLayout(l); f.setLocation(300 ,400 ); f.setSize(300 ,100 ); f.setBackgrond(new Color (255 ,255 ,255 )); for (int i=0 ; i<7 ; i++) { f.add(new Button (".BUTTON" )); } f.setVisible(true ); } }
BorderLayout BorderLayout是Frame类的默认布局管理器,将整个容器布局划分成东(EAST)、西(WEST)、南(SOUTH)、北(NORTH)、中(CENTER)。如不指定组件的加入部位,则默认加入到CENTER区。每个区域只能加入一个组件,如果加入多个,则先前加入的会被覆盖。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import java.awt.*;public class TestBorderLayout { public static void main (String[] args) { Frame f; f = new Frame ("Border Layout" ); Button bn = new Button ("BN" ); Button bs = new Button ("BS" ); Button bw = new Button ("BW" ); Button be = new Button ("BE" ); Button bc = new Button ("BC" ); f.add(bn, BoderLayout.NORTH); f.add(bs, BoderLayout.SOUTH); f.add(bw, BoderLayout.WEST); f.add(be, BoderLayout.EAST); f.add(bc, BoderLayout.CENTER); f.setSize(200 ,200 ); f.setVisible(true ); } }
GridLayout GridLayout型布局管理器将空间划分成规则的矩形网格,每个单元格区域大小相等。组件被添加到每个单元格中,先从左到右添满一行后换行,再从上到下。
在GridLayout构造方法中指定分割的行数和列数,如GridLayout(3,4)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.awt.*;public class TestGridLayout { public static void main (String[] args) { Frame f = new Frame ("GridLayout Example" ); Button b1 = nee Button ("b1" ) ; Button b2 = nee Button ("b2" ) ; Button b3 = nee Button ("b3" ) ; Button b4 = nee Button ("b4" ) ; Button b5 = nee Button ("b5" ) ; f.setLayout(new GridLayout (2 ,10 )); f.add(b1); f.add(b2); f.add(b3); f.add(b4); f.add(b5); f.pack(); f.setVisible(true ); } }
十个按钮的设计 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 import java.awt.*;public class TestGUI { public static void main (String[] args) { Frame f = new Frame (); f.setSize(400 ,400 ); f.setLayout(new GridLayout (2 ,1 )); Panel p1 = new Panel (); p1.setLayout(new BorderLayout ()); Panel p1_1 = new Panel (); p1_1.setLayout(new GridLayout (2 ,1 )); Button bn1 = new Button ("Button1" ); Button bn2 = new Button ("Button2" ); Button bn3 = new Button ("Button3" ); Button bn4 = new Button ("Button4" ); p1.add(bn1, BorderLayout.WEST); p1_1.add(bn3); p1_1.add(bn4); p1.add(p1_1, BorderLayout.CENTER); p1.add(bn2, BorderLayout.EAST); Panel p2 = new Panel (); p2.setLayout(new BorderLayout ()); Panel p2_2 = new Panel (); p2_2.setLayout(new GridLayout (2 ,2 )); Button bn5 = new Button ("Button5" ); Button bn6 = new Button ("Button6" ); Button bn7 = new Button ("Button7" ); Button bn8 = new Button ("Button8" ); Button bn9 = new Button ("Button9" ); Button bn10 = new Button ("Button10" ); p2.add(bn5, BorderLayout.WEST); p2.add(bn6, BorderLayout.EAST); p2_2.add(bn7); p2_2.add(bn8); p2_2.add(bn9); p2_2.add(bn10); p2.add(p2_2); f.add(p1); f.add(p2); f.pack(); f.setVisible(true ); } }
事件处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import java.awt.*;import java.awt.event.*;public class TestButton { public static void main (String[] args) { Frame f = new Frame (); Button bn = mew Button ("OK" ) ; f.add(bn); A aa = new A (); bn.addActionListener(aa); f.pack(); f.addWindowListerner(new B ()); f.setVisible(true ); } } class B extends WindowAdapter { public void windowClosing (WindowEvent e) { System.exit(-1 ); } } class A implements ActionListener { public void actionPerformed (ActionEvent e) { System.out.println("hello world!" ); } }
默认情况下事件源不会自动产生任何事件,程序员需要做两件事:
告诉事件源可以自动产生哪类事件,即向事件源注册某种事件的事件监听器对象
设计好可以处理这种事件的事件监听器
一旦完成这两步操作,当用户对事件源进行操作时。事件源就会自动产生事件,事件源就会自动把产生的事件封装成一个事件对象,事件源就会自动把封装好的事件对象传递给事件监听器。
事件监听器收到事件源发送过来的事件时,事件监听器就会自动调用相应的事件处理方法来对该事件进行相应的处理。
事件种类 java.awt.event包中含有所有的事件,常用的事件有:
ActionEvent:激活组件时发生的事件
KeyEvent:操作键盘时发生
MouseEvent:操作鼠标时发生
WindowEvent:操作窗口时发生的事件,如最大化或最小化某一窗口
一个事件源会产生哪些事件,一般第三方软件会自动显示,不需要特地记忆。
三个文本框相加运算 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 import java.awt.*;import java.awt.event.*;public class TestTextField { public static TextField tf1, tf2, tf3; public static void main (String[] args) { tf1 = new TextField (30 ); tf2 = new TextField (30 ); tf3 = new TextField (30 ); Button bn = new Button ("=" ); Label lb = new Label ("+" ); Frame f = new Frame ("文本框相加示例" ); f.setLayout(new FlowLayout ()); f.add(tf1); f.add(lb); f.add(tf2); f.add(bn); f.add(tf3); bn.addActionListener(new MyMonitor ()); f.pack(); f.setVisible(true ); } } class MyMonitor implements ActionListener { @Override public void actionPerformed (ActionEvent e) { String str1 = TestTextField.tf1.getText(); String str2 = TestTextField.tf2.getText(); int num1 = Integer.parseInt(str1); int num2 = Integer.parseInt(str2); int num3 = num1 + num2; Integer it = new Integer (num3); String str3 = it.toString(); TestTextField.tf3.setText(str3); String str3 = num3 + "" ; TestTextField.tf3.setText(str3); String str3 = Integer.toString(num3); TestTextField.tf3.setText(str3); String str3 = String.ValueOf(num3); TestTextField.tf3.setText(str3); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class A { public void dsvdknslsvjfnhvfbcj () { System.out.println("AAAA" ); } } class B extends A { @Override public void dsvdknslsvjfnhvfbcj () { System.out.println("BBBB" ); } } public class TestOverride { public static void main (String[] args) { A aa = new B (); aa.dsvdknslsvjfnhvfbcj(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 import java.awt.*;import java.awt.event.*;public class TestTextField_2 { public static void main (String[] args) { new TF ().launch(); } } class TF { public TextField tf1, tf2, tf3; public void launch () { tf1 = new TextField (30 ); tf2 = new TextField (30 ); tf3 = new TextField (30 ); Button bn = new Button ("=" ); Label lb = new Label ("+" ); Frame f = new Frame ("文本框相加示例" ); f.setLayout(new FlowLayout ()); f.add(tf1); f.add(lb); f.add(tf2); f.add(bn); f.add(tf3); bn.addActionListener(new MyMonitor (this )); f.pack(); f.setVisible(true ); } } class MyMonitor implements ActionListener { private TF tf; public MyMonitor (TF tf) { this .tf = tf; } @Override public void actionPerformed (ActionEvent e) { String str1 = tf.tf1.getText(); String str2 = tf.tf2.getText(); int num1 = Integer.parseInt(str1); int num2 = Integer.parseInt(str2); int num3 = num1 + num2; String str3 = num3 + "" ; tf.tf3.setText(str3); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import java.awt.*;import java.awt.event.*;public class TestTextField_3 { public static void main (String[] args) { new TF ().launch(); } } class TF { private TextField tf1, tf2, tf3; public void launch () { tf1 = new TextField (30 ); tf2 = new TextField (30 ); tf3 = new TextField (30 ); Button bn = new Button ("=" ); Label lb = new Label ("+" ); Frame f = new Frame ("文本框相加示例" ); f.setLayout(new FlowLayout ()); f.add(tf1); f.add(lb); f.add(tf2); f.add(bn); f.add(tf3); bn.addActionListener(new MyMonitor ()); f.pack(); f.setVisible(true ); } class MyMonitor implements ActionListener { @Override public void actionPerformed (ActionEvent e) { String str1 = tf1.getText(); String str2 = tf2.getText(); int num1 = Integer.parseInt(str1); int num2 = Integer.parseInt(str2); int num3 = num1 + num2; String str3 = num3 + "" ; tf3.setText(str3); } } }
内部类 内部类定义:在A类的内部但是所有方法的外部定义了一个B类,则B类就是A类的内部类,A是B的外部类。
内部类的方法可以访问外部类所有成员,外部类的方法不可以直接访问内部类的成员。
内部类的优点:①可以让一个类方便地访问另一类中的所有成员;②增加程序的安全性,有效避免其他部相关类对该类的访问。
匿名类 匿名类是一种特殊的内部类。如果在一个方法内部定义了一个匿名类,则该匿名类可以访问:①外部类的所有成员;②包裹该匿名类的方法中的所有final类型的局部变量,非final类型的局部变量无法被匿名类访问。
创建匿名类的三种方式:继承父类、实现接口、实现抽象类。
创建匿名类之实现接口 假设A是接口名,格式:
生成一个实现了A接口的匿名类对象。
创建匿名类之实现抽象类 假设A是抽象类,格式:
生成一个匿名类,该匿名类必须得实现了A类的所有抽象方法,当然该匿名类也可以定义自己的属性和方法。
创建匿名类之继承父类 假设A是个类名,格式:
生成一个A类的子类对象,该匿名类对象继承了A的所有非private成员。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.awt.*;import java.awt.event.*;public class TestWindow { public static void main (String[] args) { Frame f = new Frame (); f.setSize(300 ,300 ); f.addWindowListener( new WindowAdapter () { @Override public void windowClosing (WindiwEvent e) { System.exit(-1 ); } } ); f.setVisible(true ); } }
可运行jar包生成步骤
新建一个记事本文件,假设为1.txt,文件内容:
Main-Class: 可运行类的名字(启动类的名字)
附注:记得敲回车
dos下命令:
``` jar cvfm haha.jar 1.txt *.class1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 注意:只有GUI程序生成的class文件才可以作为main class # 流 ```java import java.io.*; public class TestFileReader { public static void main(String[] args) throws Exception { FileReader fr = new FileReader("D:\\Java\\TestFileReader.java");//某个文件路径 int ch; int cnt = 0; ch = fr.read();//从文件读取字符编码,用整型变量存储 while(-1 != ch) { ++cnt; System.out.printf("%c",(char)ch); ch = fr.read(); } System.out.printf("该文件字符的个数是%d\n", cnt); fr.close(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.io.*;public class TestFileInputStream { public static void main (String[] args) throws Exception { FileInputStream fis = new FileInputStream ("D:\\Java\\TestFileReader.java" ); int ch; int cnt = 0 ; ch = fis.read(); while (-1 != ch) { ++cnt; System.out.printf("%c" ,(char )ch); ch = fis.read(); } System.out.printf("该文件字节的个数是%d\n" , cnt); fis.close(); } }
流就是程序和设备之间嫁接起来的一根用于数据传输的管道,这个管道上有很多按钮,不同的按钮可以实现不同的功能。这根带按钮的用于数据传输的管道就是流。
流的分类 java.io包中定义了多个流类型(类或抽象类)来实现输入/输出功能,可以从不同的角度对其进行分类:
按数据流的方向不同可以分为输入流和输出流
按处理数据单位不同可以分为多字节流和字符流
按照功能不同可以分为节点流和处理流
J2SDK所提供的所有流类型位于包java.io内部分别继承自以下四种抽象流类型:
字节流
字符流
输入流
InputStream
Reader
输出流
OutputStream
Writer
四大基本流 1 public int read () throws IOException
读取一个字节并以整数形式返回,如果读取到输入流的末尾则返回-1。
1 public int read (byte [] b) throws IOException
从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中。以整数形式返回实际读取的字节数。
如果b的长度为0,则不读取任何字节并返回0;如果因为流位于文件末尾而没有可用的字节,则返回值为-1。
1 2 3 4 byte [] buf = new byte [1000 ];FileInputStream fis = new FileInputStream ("D:\\Java\\errorlog.txt" );int len = fis.read(buf);
1 public int read (byte [] b, int off, int len) throws IOException
从输入流中最多读取len个字节的数据并存入byte数组中,b表示读取的数据要存入的数组的名字,off表示第一个读出的数据要存入的位置,即下标,len表示最多能读取的字节数。
1 void close () throws IOException
关闭此输入流并释放与该流关联的所有系统资源。
1 long skip (long n) throws IOException
跳过和丢弃此输入流中数据的n个字节。
OutPutStream 1 2 3 4 5 6 7 8 9 10 11 12 13 14 void write (int b) throws IOException void write (byte [] b) throws IOException void write (byte [] b, int off, int len) throws IOException void close () throws IOException void flush () throws IOException
Reader 1 2 3 4 5 6 7 8 9 10 11 12 13 14 int read () throws IOException int read (char [] cbuf) throws IOException int read (char [] cbuf, int offset, int length) throws IOException void close () throws IOException long skip (long n) throws IOException
Writer 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 void write (int c) throws IOException void write (char [] cbuf) throws IOException void write (char [] cbuf, int off, int len) throws IOException void write (String string) throws IOException void write (String string, int off, int len) throws IOExceptionvoid close () throws IOException void flush () throws IOException
字节流和字符流的区别 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.io.*;public class TestFileReaderWriterCopy { public static void main (String[] args) throws Exception { FileReader fr = new FileReader ("D:\\Java\\TestFileReaderWriterCopy.java" ); FileWriter fw = new FileWriter ("D:\\v5le0n9.txt" ); int ch; ch = fr.read(); while (-1 != ch) { fw.write(ch); ch = fr.read(); } fw.flush(); fr.close(); fw.close(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.io.*;public class TestFileInputStreamOutputStreamCopy { public static void main (String[] args) throws Exception { FileInputStream fis = new FileInputStream ("D:\\Java\\TestFileReaderWriterCopy.java" ); FileOutputStream fos = new FileOutputStream ("D:/v5le0n9.txt" ); int ch; ch = fis.read(); while (-1 != ch) { fos.write(ch); ch = fis.read(); } fos.flush(); fis.close(); fos.close(); } }
例:
缓冲流 缓冲流就是带有缓冲区的输入输出流。缓冲流可以显著地减少对IO的访问次数,保护硬盘。
缓冲流是处理流,必须依附于节点流。
J2SDK提供了四种缓冲流,其常用的构造方法为:
1 2 3 4 5 6 7 8 9 10 11 BufferedReader(Reader in) BufferedReader(Reader in, int sz) BufferedWriter(Writer out) BufferedWriter(Wreiter out, int sz) BufferedInputStream(InputStream in) BufferedInputStream(InputStream in, int size) BufferedOutputStream(OutputStream out) BufferedOutputStream(OutputStream out, int size)
缓冲输入流支持其父类的mark和reset方法。
BufferedReader提供了readLine方法用于读取一行字符串(以\r或\n分隔)。
BufferedWriter提供了newLine用于写入一个行分隔符。
对于输出的缓冲流,写出的数据会现在内存中缓存,使用flush方法将会是内存中的数据立刻写出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.io.*;public class TestBufferedInputStreamOutputStreamCopy { public static void main (String[] args) throws Exception { BufferedInputStream bis = new BufferedInputStream (new FileInputStream ("D:\\Java\\TestFileReaderWriterCopy.java" )); BufferedOutputStream bos = new BufferedOutpuntStream (new FileOutputStream ("D:/v5le0n9.txt" )); byte [] buf = new byte [1024 ]; int len; len = bis.read(buf); while (-1 != len) { bos.write(buf, 0 , len); len = bis.read(buf); } bos.flush(); bis.close(); bos.close(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import java.io.*;public class TestBufferedReaderWriterCopy { public static void main (String[] args) { BufferedReader br = null ; BufferedWriter bw = null ; try { br = new BufferedReader (new FileReader ("D:/Java/TestBufferedReaderWriterCopy.java" )); bw = new BufferedWriter (new FileWriter ("D:\\Java\\v5le0n9.heihei" )); String str = null ; while (null != (str=br.readLine())) { bw.write(str); bw.newLine(); } bw.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); Sytsem.exit(-1 ); } catch (IOException e) { e.printStackTrace(); Sytsem.exit(-1 ); } finally { try { bw.close(); br.close(); } catch (IOException e) { e.printStackTrace(); Sytsem.exit(-1 ); } } } }
数据流 DataInputStream能够以一种有与机器无关的方式,直接从底层字节输入流读取Java基本类型和String类型的数据,常用的方法包括:
1 2 3 4 5 6 7 8 9 10 public DataInputStream (InputStream in) public final boolean readBoolean () public final byte readByte () public final char readChar () public final double readDouble () public final float readFloat () public final int readInt () public final long readLong () public final short readShort () public final String readUTF ()
DataInputStream是包裹流(处理流),必须依附于InputStream
DataOutputStream DataOutputStream能够以一种与机器无关的方式,直接将Java基本类型和String类型数据写出到其他的字节输出流。常见方法:
1 2 3 4 5 6 7 8 9 10 public DataOutputStream (OutputStream out) public final boolean writeBoolean () public final byte writeByte () public final char writeChar () public final double writeDouble () public final float writeFloat () public final int writeInt () public final long writeLong () public final short writeShort () public final String writeUTF ()
DataOutputStream是包裹流(处理流),必须依附于OutputStream
数据流实例 编程实现将long类型数据写入byte数组,然后再从byte数组中把该数据读出来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.io.*;public class TestByteArrayOutputStream { public static void main (String[] args) throws Exception { long n = 9876543210L ; ByteArrayOutputStream baos = new ByteArrayOutputStream (); DataOutputStream dos = new DataOutputStream (baos); dos.writeLong(n); dos.flush(); byte [] buf = baos.toByteArray(); ByteArrayInputStream bais = new ByteArrayInputStream (buf); DataInputStream dis = new DataInputStream (bais); long l = dis.readLong(); System.out.println("l = " + l); dos.close(); } }
转换流 OutputStreamWriter流是把OutputStream流转化成Writer流的流,InputStreamReader流是把InputStream流转化成Reader流的流。
OutputStreamWriter和InputStreamWriter都是处理流。
转换流实例 如何将键盘输入的字符组成字符串直接赋给String对象。
1 2 3 4 5 6 7 8 9 10 11 import java.io.*;public class TestString { public static void main (String[] args) throws Exception { String str = null ; BufferedReader br = new BufferedReader (new InputStreamReader (System.in)); str = br.readLine(); System.out.println("str = " + str); } }
Print流 Print流只有输出,没有输入。
PrintWriter输出字符,PrintStream输出字节。
PrintStream PrintStream在OutputStream基础之上提供了增强的功能,即可以方便地输出各种类型数据(而不仅限于byte型)的格式化表示形式。
PrintStream重载了printf和println方法,用于各种不同类型数据的格式化输出,格式化输出是指将一个数据用其字符串格式输出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.io.*;public class TestPrintString { public static void main (String[] args) throws Exception { DataOutputStream dos = new DataOutputStream (new FileOutputStream ("D:/Java/1.txt" )); dos.writeLong(12345 ); dos.close(); System.out.printf("%#X\n" , 12345 ); PrintStream ps = new PrintStream (new FileOutputStream ("D:/Java/2.txt" )); ps.println(12345 ); ps.close(); } }
PrintWriter PrintWriter提供了PrintStream的所有打印方法,其方法也从不抛出IOException
与PrintStream的区别:①作为处理流使用时,PrintStream只能封装OutputStream类型的字节流,而PrintWriter既可以封装OutputStream还能够封装Writer;②PrintWriter中的println()方法具有更好的跨平台性。
标准输入输出的重定向 1 2 3 4 5 6 7 8 9 try { ... } catch (Exception e){ e.printStackTrace(); ... }
1 2 3 4 5 6 7 8 9 public class TestSys { public static void main (String[] args) throws Exception { PrintStream ps = new PrintStream ("D:/heihei.aaa" ); System.setOut(ps); System.out.println("哈哈" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class TestSetSystemOut { public static void main (String[] args) { PrintStream ps_out = null ; try { ps_out = new PrintStream (new FileOutputStream ("D:/Java/hello" )); System.setOut(ps_out); System.out.println(12 ); System.out.println(55.5 ); } catch (Exception e) { e.printStackTrace(); } finally { try { ps_out.close(); } catch (Exception e) { e.printStackTrace(); } } } }
实例 编程实现将键盘输入整型数据到A文件中,如果输入有误,则把出错信息输出到B文件中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import java.io.*;import java.util.*;public class TestSetOutErr { public static void main (String[] args) { PrintStream psOut = null ; PrintStream psError = null ; Scanner sc = null ; try { psOut = new PrintStream ("D:/Out.txt" ); psError = new PrintStream ("D/Error.txt" ); sc = new Scanner (System.in); int num; System.setOut(psOut); System.serErr(psError); while (true ) { num = sc.nextInt(); System.out.println(num); } } catch (Exception e) { System.err.println("出错的信息是:" ); e.printStackTrace(); } } }
对象的序列化(Object流) Serializable接口中没有任何方法,这种类型的接口被称为标记接口。如果一个类实现了Serializable接口,潜在含义就是告诉编译器这个类是允许被序列化的,如果程序中存在序列该对象的代码,编译器就会自动进行相应的处理以完成该对象的序列化,如果该对象没有实现Serializable接口,程序中却存在该对象被序列化的代码,编译器编译时就会报错。
在Java中transient修饰的成员变量在对象序列化时不会被序列化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 import java.io.*;public class TestObjectIO { public static void main (String[] args) { ObjectOutputStream oos = null ; ObjectInputStream ois = null ; Student ss = new Student ("zhangsan" , 1000 , 88.8f ); Student ss2 = null ; try { FileOutputStream fos = new FileOutputStream ("D:\\Java\\dudu" ); oos = new ObjectOutputStream (fos); oos.writeObject(ss); ois = new ObjectInputStream (new FileInputStream ("D:/Java/dudu" )); ss2 = (Student)ois.readObject(); System.out.println("ss2.sname = " + ss2.sname); System.out.println("ss2.sid = " + ss2.sid); System.out.println("ss2.sscore = " + ss2.sscore); } catch (FileNotFoundException e) { System.out.println("文件没有找到!" ); System.exit(-1 ); } catch (Exception e) { e.printStackTrace(); System.exit(-1 ); } finally { try { oos.close(); ois.close(); } catch (Exception e) { e.printStackTrace(); System.exit(-1 ); } } } } class Student implements Serializable { public String sname = null ; public int sid = 0 ; transient public float sscore = 0 ; public Student (String name, int id, float score) { this .sname = name; this .sid = id; this .sscore = score; } }
容器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.*;class A { public String toString () { return "Haha" ; } } public class Test { public static void main (String[] args) { ArrayList al = new ArrayList (); al.add(12345 ); al.add("张三" ); al.add(66.6 ); al.add(new A ()); System.out.println(al); System.out.println(al.get(2 )); Object[] obArr = al.toArray(); System.out.println(al[2 ]); } }
为什么需要容器 数组存在两个缺陷:
容器可以弥补数组的这两个缺陷。
容器与现实的对应关系 集合(容器)就是将若干用途、性质相同或相近的“数据”组合而成的一个整体。
数学上,集合类型可以归纳为三种
集(Set):Set集合不区分元素的顺序,不允许出现重复元素
列表(List):List集合区分元素顺序,且允许包含重复元素
映射(Map):映射中保存成对“键-值”(Key-Value)信息,映射中不能包含重复的键,每个键最多只能映射一个值
Java设计了三个接口来对应数学上的三种集合类型,这三个接口名字分别为Set、List、Map。
Collection接口中的方法介绍 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 int size () ;boolean isEmpty () ;boolean containesAll (Collection c) ;Iterator iterator () ; Object[] toArray(); boolean add (Object e) ;boolean remove (Object o) ;boolean addAll (Collection c) ;boolean removeAll (Collection c) ;void clear () ;boolean equals (Object o) ;int hashCode () ;
Collection接口的子接口——List接口 List接口是Collection的子接口,实现List接口的容器类中的元素是有顺序的,而且可以重复。
List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
J2SDK所提供的List容器类有ArrayList, LinkList等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Object get (int index) ; Object set (int index, Object element) ; void add (int index, Object element) ;Object remove (int index) ; int indexOf (Object o) ;int lastIndexOf (Object o) ;
ArrayList与LinkedList的比较 ArrayList和LinkedList都实现了List接口中的方法,但两者内部实现不同。ArrayList底层采用数组完成,而LinkedList则是以一般的双向链表完成,其内每个对象除了数据本身外,还有两个引用,分别指向前一个元素和后一个元素。
它们两个的性质与C语言的数组和链表的性质一样。
Collections类 Collection接口的实现类,如ArrayList、LinkedList本身并没有提供排序、倒置、查找等方法,这些方法是由Collesctions类来实现的,该类有很多public static方法,可以直接对Collection接口的实现类进行操作。
Collections类常用方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void sort (List) ;void shuffle (List) ;void reverse (List) ;void fill (List, Object) ;void copy (List dest, List src) ;int binarySearch (List, Object) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import java.util.*;public class TestCollections { public static void main (String[] args) { List lt = new LinkedList (); for (int i=0 ; i<7 ; i++) { lt.add("a" + i); } System.out.println(lt); Collections.shuffle(lt); System.out.println(lt); Collections.sort(lt); System.out.println(lt); Collections.reverse(lt); System.out.println("倒置之后:" + lt); System.out.println(Collections.binarySearch(lt, "a5" )); Collections.sort(lt); System.out.println("重新排序之后:" + lt); System.out.println(Collections.binarySearch(lt, "a5" )); Collections.fill(lt, "0" ); System.out.println(lt); } }
Comparable接口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.util.*;class Student { private int id; private String name; public Student (inti id, String name) { this .id = id; this .name = name; } @Override public String toString () { return id + " " + name; } } public class TestList { public static void main (String[] args) { List L = new ArrayList (); L.add(new Student (1000 , "张三" )); L.add(new Student (1001 , "李四" )); L.add(new Student (1002 , "王五" )); System.out.println(L); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import java.util.*;class Student implements Comparable { private int id; private String name; public Student (int id, String name) { this .id = id; this .name = name; } @Override public String toString () { return id + " " + name; } @Override public int compareTo (Object o) { Student st = (Student)o; if (this .id == st.id) return 0 ; else if (this .id > st.id) return 1 ; else return -1 ; } } public class TestList_2 { public static void main (String[] args) { List L = new ArrayList (); L.add(new Student (1000 , "张三" )); L.add(new Student (1001 , "李四" )); L.add(new Student (1002 , "王五" )); L.add(new Student (1002 , "王五" )); Collections.sort(L); System.out.println(L); } }
Collection接口的子接口——Set接口 因为Set和List都是继承自Collection接口,所以Set和List中有很多方法是一样的。
List接口中有add, set, indexOf方法,但Set接口中却只有add方法,没有set, indexOf方法。因为Set是无序且不能重复的,不存在某元素具体位置这个概念。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 import java.util.*;class Student { private int id; private String name; public Student (int id, String name) { this .id = id; this .name = name; } @Override public String toString () { return id + " " + name; } @Override public boolean equals (Object ob) { Student st = (Student)ob; return this .id == st.id && this .name == st.name; } @Override public int hashCode () { return id * this .name.hashCode(); } } public class TestSet { public static void main (String[] args) { Set S = new HashSet (); S.add(new Student (1000 , "张三" )); S.add(new Student (1001 , "李四" )); S.add(new Student (1002 , "王五" )); System.out.println(S); S.add(new Student (1002 , "王五" )); S.add(new Student (1001 , "王五" )); S.add(new Student (1004 , "王五" )); System.out.println(S); } }
equals和hashCode方法的使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class A { private int i; public A (int i) { this .i = i; } } public class TesthashCode { public static void main (String[] args) { A aa1 = new A (1 ); A aa2 = new A (1 ); System.out.println(aa1 == aa2); System.out.println(aa1.equals(aa2)); System.out.println(aa1.hashCode() == aa2.hashCode()); Integer it1 = new Integer (1 ); Integer it2 = new Integer (1 ); System.out.println(it1 == it2); System.out.println(it1.equals(it2)); System.out.println(it1.hashCode() == it2.hashCode()); } }
如果不重写equals和hashCode方法,equals比较aa1和aa2的对象的地址的十六进制是否相等,hashCode比较aa1和aa2的对象的地址的十进制是否相等。
如何重写equals和hashCode方法?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class A { private int i; public A (int i) { this .i = i; } @Override public boolean equals (Object ob) { A aa = (A)ob; return this .i == aa.i; } @Override public int hashCode () { return new Integer (i).hashCode(); } } public class TesthashCode_2 { public static void main (String[] args) { A aa1 = new A (1 ); A aa2 = new A (1 ); System.out.println(aa1 == aa2); System.out.println(aa1.equals(aa2)); System.out.println(aa1.hashCode() == aa2.hashCode()); Integer it1 = new Integer (1 ); Integer it2 = new Integer (1 ); System.out.println(it1 == it2); System.out.println(it1.equals(it2)); System.out.println(it1.hashCode() == it2.hashCode()); } }
Iterator接口 常用方法:
1 2 3 4 5 6 7 8 boolean hasNext () ;Object next () ; void remove () ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import java.util.*;public class TestIterator { public static void showCollection (Collection c) { Iterator it = c.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } public static void main (String[] args) { ArrayList al = new ArrayList (); al.add("one" ); al.add(22 ); al.add(new Point (1 ,1 )); System.out.println("al容器的内容是:" ); showCollection(al); HashSet hs = new HashSet (); hs.add("one" ); hs.add(22 ); hs.add(new Point (1 ,1 )); System.out.println("hs容器的内容是:" ); showCollection(hs); } } class Point { private int i, j; public Point (int i, int j) { this .i = i; this .j = j; } public String toString () { return "[" + i + "," + j + "]" ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.util.*;public class TestIterator_2 { public static void main (String[] args) { Collection c = new TreeSet (); c.add("123" ); c.add("456" ); c.add("234" ); c.add("111" ); c.add("678" ); Iterator i = c.iterator(); while (i.hasNext()) { System.out.println(i.next()); } } }
Map接口 java.util.Map接口描述了映射结构,Map结构允许以键集、值集合或键-值映射关系集的形式查看某个映射的内容。
主要方法:
1 2 3 4 5 6 7 8 9 10 11 Object put (Object key, Object value) ; Object get (Object key) ; void putAll (Map m) ;boolean isEmpty () ;void clear () ;int size () ;boolean containsKey (Object key) ;boolean containsValue (Object value) ;Object remove (Object key) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.*;public class TestHashMap { public static void main (String[] args) { Map m = new HashMap (); m.put("one" , "zhangsan" ); m.put(66.6 , 70 ); m.put(new A (), "12" ); System.out.println(m.get(66.6 )); System.out.println(m); m.put(66.6 , 80 ); System.out.println(m); } } class A {}
Map(映射)是一种把键对象和值对象进行映射的集合,它的每一个元素都包含一对键对象和值对象。
向Map集合中加入元素时,必须提供一对键对象和值对象,从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 import java.util.*;class Student { private int id; private String name; private int age; public Student () {} public Student (int id, String name, int age) { this .id = id; this .name = name; this .age = age; } public int hashCode () { return this .name.hashCode() * id * age; } public boolean equals (Object o) { Student s = (Student)o; return this .name.equals(s.name) && this .id == s.id && this .age == s.age; } public String toString () { return id + " " + name + " " + age; } } public class TestHashMap_2 { public static void main (String[] args) { HashMap hm = new HashMap (); hm.put(1001 , new Student (1001 , "zhangsan" , 20 )); hm.put(1003 , new Student (1003 , "lisi" , 30 )); hm.put(new Integer (1004 ), new Student (1004 , "wangwu" , 10 )); hm.put(1002 , new Student (1002 , "v5le0n9" , 20 )); System.out.println("hm容器中所有的元素是:" ); Set s = hm.keySet(); Iterator it = s.iterator(); while (it.hasNext()) { Integer key = (Integer)it.next(); System.out.println(hm.get(key)); } System.out.println("直接查找某一元素" ); System.out.println(hm.get(1003 )); System.out.println(hm.get(1005 )); } }
泛型 泛型是用来限制传入容器、接口中的数据类型。
参考TestHashMap_2
1 2 3 4 5 6 7 8 HashMap<Integer, Student> hm = new HashMap <Integer, Student>(); Set<Integer> s = hm.keySet(); Iterator<Integer> it = s.iterator(); Integer key = it.next();
网络编程 UDP编程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.net.*;import java.io.*;public class TestUDPServer { public static void main (String[] args) throws Exception { DatagramSocket ds = new DatagramSocket (5678 ); byte buf[] = new byte [1024 ]; DatagramPacket dp = new DatagramPacket (buf, buf.length); try { while (true ) { ds.receive(dp); ByteArrayInputStream bais = new ByteArrayInputStream (dp.getData()); DataInputStream dis = new DataInputStream (bais); System.out.println(dis.readLong()); } } catch (Exception e) { e.printStackTrace(); ds.close(); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.net.*;import java.io.*;public class TestUDPClient { public static void main (String[] args) throws Exception { DatagramSocket ds = new DatagramSocket (); long n = 10000L ; ByteArrayOutputStream baos = new ByteArrayOutputStream (); DataOutputStream dos = new DataOutputStream (baos); dos.writeLong(n); byte [] buf = baos.toByteArray(); DatagramPacket dp = new DatagramPacket (buf, buf.length, new InetSocketAddress ("127.0.0.1" , 5678 )); ds.send(dp); ds.close(); } }
TCP编程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.net.*;import java.io.*;public class TCPServer { public static void main (String[] args) throws Exception { ServerSocket ss = new ServerSocket (6666 ); while (true ) { Socket s = ss.accept(); System.out.println("一个连接已经建立!" ); DataInputStream dis = new DataInputStream (s.getInputStream()); System.out.println(dis.readUTF()); dis.close(); s.close(); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.net.*;import java.io.*;public class TCPClient { public static void main (String[] args) throws Exception { Socket s = new Socket ("127.0.0.1" , 6666 ); OutputStream os = s.getOutputStream(); DataOutputStream dos = new DataOutputStream (os); dos.writeUTF("v5le0n9" ); dos.flush(); dos.close(); s.close(); } }