1、Java的三种体系:
J2SE | 用于桌面开发,低端商务开发(Java to Standard Edition) ; |
J2ME | 用于移动电话、电子消费品、嵌入式开发(Java to Micro Edition) ; |
J2EE | 企业级解决方案的开发,基于WEB的开发等,(Java to Enterprise Edition) ; |
2、Java的特点:
序号 | 语言角度 | 学习角度 |
1 | 比C++简单,放弃了对指针的使用; | 入门迅速,容易学; |
2 | 目前最好的网络编程语言; | 编写更少、更好的代码; |
3 | 开放式先进的技术,可移植性强; | 更快的开发程序 |
4 | 完全的OO(面向对象,单根结构) 的跨平台语言; | 用纯Java编写的程序可以避免平台相关性; |
5 | 分布式开发,支持多线程,可靠安全健壮; | 一次编写,处处运行,可以更容易的发布软件; |
3、主要的开源网站:
①www.Java.net ②www.apache.org ③www.sourceforge.net
④www.theserverside.com ⑤www.javaworld.com ⑥www.chinalab.com
4、其他技术问题:
序号 | 特征 | ||
1 | 目前国内比较流行的技术组合:spring(www.springframework.com) + hibernate技术,还有webservice +XML技术; | ||
2 | J2EE的相关技术:EJB,SEVILET,JSP等; | ||
3 | 源文件(*.java) --------->类文件(*.class) --------->java虚拟机(JVM) 编译器 解释器 | ||
4 | 应用程序层 | Java应用程序 | |
Java平台层 | Java虚拟机 | ||
操作系统层 | UNIX | WINDOWS | RTOS |
硬件层 | SPARC | X86 | MIPSPPC |
二、面向对象的特征
序号 | 特征 | ||
1 | 面向对象的三个原则 | 封装性 | 封装的基本单元是类(class),类是一个抽象的逻辑结构,而类的对象是一个真实的物理实体;类的目的是封装复杂性,在类内部存在隐藏实现复杂性机制; 封装(encapsulation) 的两个好处: 模块化:可以独立于其他对象的源代码进行编写和维护,可以很容易的将对象在系统中传递; 隐藏信息:其他对象可以通过本对象的一个公共接口进行通信而不影响其他对象; |
继承性 | 继承是一个对象获得另一个对象的属性的过程,继承机制是一个对象成为一个更具通用类的一个特定实例成为可能,避免了代码的重复编写; | ||
多态性 | (重载overload,方法名相同、参数的个数不同、参数的类型不同、返回的类型不同和覆盖override) ;多态性就是“一种接口,多种方法”,可以为一组相关的动作设计一个通用的接口,其实类的函数的重载就是一种多态的体现; | ||
4 | 引入抽象编程的思想; | 类的封装就是一种抽象思想 |
三、Java关键字
1、类访问修饰符
序号 | 说明 |
1 | 类的修饰符只有public和default两个; |
2 | public修饰类时表示任何包的其它类都可以访问该类; |
3 | 访问修饰符为default时只有在同一个包里的类才能访问它,其他包里的都不行; |
4 | 类的构造函数(构造器) 不能用final、abstract、synchronized、native、static等关键字进行修饰; |
2、成员访问修饰符(public、protected、default、private)
序号 | 规则说明 | |||
1 | java的成员访问修饰符有4种:public、private、protected、default | |||
2 | public static == static public; | |||
3 | 类的成员访问修饰符的详细描述如下:(√表示允许访问,×表示不能访问) | |||
visibility | public | protected | default | private |
访问同一个类 | √ | √ | √ | √ |
访问同一个package中不同的类 | √ | √ | √ | × |
访问在不同package中的父类(superclass) | √ | √ | × | × |
访问不同的package中不同的类 | √ | × | × | × |
综合上表,访问修饰符的访问权限为:public>protected>default>private |
3、final关键字
序号 | 修饰范围 | 规则说明 |
1 | 类 | final类不能被继承,final类的性能会有所提升如: public final class A{…} public class B extends A{…} //错误,A被final类不能作为B的基类 |
2 | 方法 | final成员不能被重写(overriding); |
3 | 类的成员变量 | final变量不能被修改值,如: public final class A{ static final int a = 10; a = 11; //错误,不能被修改 static final int b; //此处是非法的,必须是如static final int b=9; } |
4 | 方法中的变量 | 可以在声明时不赋值,但是在使用之前必须赋值,一旦赋值就不能被修改; public static void method() { Final int a; System.out.println(a) ; //错误,必须改为:a = 10;System.out.println(a) ; } |
5 | final修饰的对象表示它所修饰的对象所分配的内存地址不可变; | |
final和abstract不能同时使用,如public final abstract class A{}是不允许的;因为final是使类A不能被继承而abstract是要类A在其子类中实现它的方法; |
4、abstract关键字
序号 | 修饰范围 | 规则说明 |
1 | 类 | 1、 被修饰的类为抽象类,不能被实例化(生成对象) 只能作为其他类的基类(父类) 2、 abstract不能修饰类的构造函数(构造器) ; 3、 类下面的方法可以不都被修饰为abstract,没有被修饰的方法则需要实现该方法; |
2 | 类的方法 | 修饰方法时,它的类也必须被修饰为abstract |
3 | 其它 | abstract不能与final同时使用; |
5、static关键字
如果一个类的成员被声明为static,则该成员实际上是一个全局变量,static关键字的使用规则如下:
序号 | 规则说明 |
1 | 在java中只有接口、最外层的类和static Inner Class可以定义static变量或方法; |
2 | Static变量和方法属于它的类,它的类的所有对象都可以访问到它;但是任何一个类的对象对static变量进行修改都直接影响到所有对象; |
3 | 它们只能访问static修饰的类的成员变量和方法 |
4 | 它们不能以任何方式引用this或super; |
6、override关键字
7、synchronized关键字
synchronized只能用在方法的声明的前面,而变量不能用该关键字;
四、变量(variables statement)
1、变量声明
序号 | 规则说明 | |
1 | 变量名称的命名规则: (1)java只允许英文字母以及”$”以及”_”两个非英文字母作为变量或类名的首字母; (2)变量以小写字母开头,以后的每个单词首字母大写;其它的普通变量除了第一个单词首字 母小写外其他的都大写; (3)类名的每个单词的首字母都大写; (4)java约定_只用在常量声明的单词之间分隔单词; | |
2 | 规则1 | int 99year = 99是非法的,而int _99year=99是允许的 |
规则2 | int myInt = 99; | |
规则3 | Class MyClass{} | |
规则4 | int MAX_VALUE = 99 | |
3 | 当变量声明为null时表示该变量没有初始化即没有分配内存空间; | |
4 | 八进制数的声明 | int five = 05;int nine = 011; |
十六进制的声明 | int a = 0x9;int fifteen= 0xF;int sixteen=0x10; | |
在java中除了接口、外部类和static Inner Class可以定义static变量或方法; |
2、变量作用范围
变量声明的位置直接决定了变量的作用范围,它共有4种作用范围:
序号 | 声明范围 | 规则说明 |
1 | 类的成员变量 | 它是一个类的成员(static修饰,所有类的变量即是所有对象公有的一个变量,它的更改将影响到所有的类的对象)或者一个对象的成员(非静态变量,属于类的对象的变量),它在类内,但是是在任何方法和构造函数之外; |
2 | 局部变量 | 主要是在类的方法或者一个代码块中,只在所在的方法或代码块中起作用; |
3 | 方法的参数 | 是方法或者构造器中的正式自变量,用于向方法或者构造器传递值,作用范围是它所在方法或则构造器内; |
4 | 异常处理器参数 | 与参数类似,它是异常处理器的自变量; |
五、接口(Interface)
序号 | 规则说明 |
1 | 接口可以继承接口,用关键字extends(扩充、继承) |
2 | 普通类可以实现多个接口,用关键字implements(实现),用“,”分隔 |
3 | 接口中的定义中不能加private和protected,其default值是public; |
4 | 接口中可以定义静态的变量,格式为:public static final type variableName; |
5 | 实现类必须实现接口中的所有方法; |
六、构造函数(构造器,constructor)
序号 | 规则说明 |
1 | 构造函数的作用:在生成类的对象时,为对象分配一个(封闭)的内存空间; |
2 | 构造函数必须与类名一致;构造函数可以重载; |
3 | 不管父类有无构造器,子类在实例化时都会调用父类的构造器,所以当父类中声明了带参数的构造器时,子类必须在构造器的第一行指定调用父类的哪个构造器; |
4 | 构造器不返回任何类型,可以是个空方法,也可以给类的变量赋值; |
5 | 在类的继承中,子类会默认调用父类中的构造器,可能出现的情况有: |
public class A{ public A(int i){ … } } | 可以将类B中加个构造器: public class B extends A{ public B(int i){super(i)} public static void main(String[] args){ B b = new B(1); } } 或者在A类中加个没有参数和方法体的构造函数: public class A{ public A(){} public A(int i){…} } |
public class B extends A{ public static void main(String[] args){ B b = new B(); } } | |
6 | 例子: public class A{ private int a; public A(){} //默认的构造函数可以不写 public A(int i){ a= i;} //一旦建立了自己的构造函数,则java默认构造函数则将不再使用了。 } |
七、程序控制语句
1、循环控制语句
Java中共有while、do while、for三种循环语句。
序号 | 类型 | 规则说明 | |
1 | while | int a =0,b=10; while(a<b){ … a++ //当a等于b时即跳出循环; } | |
2 | do while | 规则:先执行后判断,至少要执行一次,如: int a =0,b=10; do{ … a++ //当a等于b时即跳出循环; } while(a<b); | |
3 | for | 规则根据条件执行; for(int a=0;a<10;i++){ …//当a=10时自动跳出循环; } 上个for循环语句等价于: for(int a=0;a<10;){ … //当a=10时自动跳出循环; | a++; }甚至可以: int a=0; for(;a<10;){ … //当a=10时自动跳出循环; a++; } |
2、switch等跳转语句
Java中共有break、continue、return三种跳转语句,其中:
序号 | 跳转类型 | 规则说明 |
1 | break | ①switch语句中的跳转; ②用来跳出循环语句; for(int i=0;i<100;i++){ if(i== 50 && j==49) break; //直接跳出循环语句 else System.out.println(i); } ③可以作为一种的先进的goto语句来使用; |
2 | continue | for(int i=0;i<100;i++){ if(i== 50 && j==49) continue; //直接跳转到控制语句控制体中i++ else System.out.println(i); }在循环体语句中可以用continue语句使程序只执行满足循环体条件的表达式; |
3 | return | 直接结束并跳出方法,或者返回方法定义的数据类型; |
3、New运算符
理解new运算符是在运行期间为对象分配内存的是很重要的。请记住下面的话:
当一个对象引用赋值给另一个对象引用时,仅仅只是对引用的一个拷贝(即只是将2个对象都指向同一片内存。)
如下面的代码:
public class Box{ public int length; public int height; public Box(int l,int h){ this. length = l; this. height = h; } } public class B{ Box b1= new Box(10,20); Box b2= b1; | System.out.println (b1.length+”-“+b1.height); System.out.println (b2.length+”-“+b2.height); b1.length =20; b1.height =30; System.out.println(b1.length+”-“+b1.height); System.out.println (b2.length+”-“+b2.height); } 结果: 10-20 10-20 20-30 20-30 |
这是因为:在上面的代码中,先是为b1分配了内存空间,然后在b2=b1时,将b2的指针也指向了b1所指向的内存空间,所以无论b1怎么变,b2都跟b1完全一致; |
4、++操作符
序号 | 分类 | 规则说明 |
1 | 优先级 | 在同一个运算表达式中,A++的优先级高于++A |
2 | A++ | B=A++表示B=A;A=A+1; |
3 | ++A | B=++A表示B=A=A+1; |
八、内部类(Inner Class)
定义:inner class是 class的另一种类的成员;内部类可以实现(implement)接口或者继承(extends)其它的类; | ||
序号 | 分类 | 规则说明 |
1 | 静态内部类(又叫嵌套类) | 类似与类中的static成员方法,在调用该类时不需要声明,可以直接调用; |
2 | 成员内部类 | 类似与类中的非static成员方法,在调用该类时需要实例化它的外部类,然后通过该实例在实例化该内部类 |
3 | 本地内部类(local Inner Class) | 类似于类的方法中的局部变量; |
4 | 匿名类(Anonymous Inner Class) | 一种特殊的local Inner Class; |
5 | 总之,这4种内部类类似于普通类中的静态成员、非静态成员、方法中的局部变量 |
1、 静态内部类(static Inner Class)
序号 | 规则说明 |
1 | Static inner class可以访问它的外部类的所有的静态成员变量和方法;而它的外部类可以访问它的所有成员和方法(无论用什么修饰符); |
2 | Static inner class访问它的外部类的非static变量时只能通过它的外部类的对象实例去访问; |
3 | Static inner class中只能有静态成员变量和方法; |
4 | Static inner class的名字不能跟它的外部类相同; |
例子:public class MyOuter { public static int ins; public int myins; public static class MyInner { int i = ins; int x =myins; //不能这样访问外部类的非静态成员,必须通过它的实例来访问; int y = new MyOuter().myins; //这样访问myins是正确的; public void food() { …} } } 在编译之后不仅要生成一个MyOuter.class还将生成一个MyOuter $MyInner.class; |
2、成员内部类(Member Inner Class)
序号 | 规则说明 |
1 | 它类似与普通类中的非静态成员变量,但又具有类的特性,调用它需要对它实例化; |
2 | 它可以访问public, package, protected, and private修饰的任何方法和成员变量; |
3 | Member Inner Class不能有static变量和方法; |
4 | Member Inner Class对象只能通过它的外部类的实例对象来进行访问,如 href="#例子memInner" 例子; |
5 | Member Inner Class的名字不能跟它的外部类的名字相同; |
6 | inner class的声明: A. 在outerclass内部访问: MyInner in = new MyInner(); B. 在outer class的外部访问: Myouter.MyInner in = new Myouter().new MyInner(); 或者 Myouter out = new Myouter(); Myouter.MyInner in = out.new MyInner(); |
Member Inner Class例子: public class Outer{ Public class Inner{ } } public class Test{ | Outer ot = new Outer(); Inner inn= new Inner(); //这样是错误的,不能这样直接初始化 Outer .Inner inn= ot.new Inner(); //这样才是正确的 } |
3、本地内部类(Local Inner Class)
序号 | 规则说明 |
1 | Local Inner Class是定义在类的方法中或者方法的某个代码块中的一种类; |
2 | 类似于类的方法中的变量,不能被public, protected, private, or static修饰; |
3 | 名字不能跟外部类的名字相同;不能有static成员或方法;只能访问它所在方法中的final变量; |
4、匿名内部类Anonymous Inner Classes
序号 | 规则说明 | |
1 | Anonymous Inner Classes可以说是一个没有类名的Local Inner Class,由于没有名字所以不需要为它定义构造器; | |
2 | 匿名内部类只能访问final修饰的本地变量; | |
3 | 它总是要继承一个类或实现一个接口(2取其1),但不需使用extends或者implement关键字; | |
例子 | public class A{ public void print(){ System.out.println(“printing A”);} } public class B{ public void print(){ A a = new A(){ //覆盖A类中的print() public void print(){ System.out.println(“printing B”); }; //声明一个匿名类,并将它的对象赋值给它的父类A的对象a, | a.print(); } } public class Test{ public static void main(String[] args){ A a = new A(); B b = new B(); a.print(); b.print() } }结果是:printing A printing B |
九、String和StringBuffer类
序号 | 规则说明 |
1 | String类与StringBuffer类的区别: a、 String类是一个final类,一旦生成对象便不可改变它的值,如果改变这个对象则相当于生成了一个新的对象(将该对象指向了一个新的内存) b、 StringBuffer类则可以创建和操作动态字符串,系统可以自动地为对象扩展内存以容纳新增的文本; |
2 | StringBuffer中的length()和capacity()方法的区别: 1)length方法返回字符串或字符串缓冲区中包含的字符数; 2)capacity方法返回分配给字符串缓冲区的空间量(capacity() = length()+16); |
3 | String类中的equals方法与==是不一样的,equals方法表示两个比较的字符串中的字符是否一致,而==则表示操作符的两边的字符串变量所指的地址是否相同; |
4 | 1)String A=”a”+”b”+”c”; 2)StringBuffer B=new StringBuffer(“a”); B. append(“b”). append(“c”); 上面的两个语句最后都是返回的字符串”abc”,但是1)共创建了5个字符对象(a,b,ab,c,abc),而2)中只创建了3个,节省了内存空间,效率更高; |
例子:
import java.util.*;
class StringTest{
public String hello ="Hello";
public String hel ="Hel";
public String lo ="lo";
}
class MyTest{
public MyTest(){}
public static void main(String[] args){
StringTest st = new StringTest();
String str1 ="Hello";
String str2 ="Hel";
String str3 ="lo";
String str4 ="Hel"+"lo";
String str5 =str2+str3;
String str6 =st.hel+st.lo;
System.out.println(str1==str4);
System.out.println(str1==str5);
System.out.println(str1==st.hello);
System.out.println(str1==str6);
}
}
结果:
true(str1==str4)
false(str1==str5)
true(str1==st.hello)
false(str1==str6)
十、线程(Thread)
序号 | 规则说明 | |
1 | 定义:它是程序内的一个单一的顺序控制流程; | |
2 | 特点:多个线程可以同时运行,在一个程序内可以执行不同的任务;这正是它的神奇之处; | |
3 | 线程与进程 | 相同点: a、 都有一个专门的单一的顺序控制流程; b、 线程又被称为轻量级进程(lightweight process);因为它在一个完整程序的上下文中运行,并利用了程序分配给它的资源和此程序的环境; |
4 | 创建一个线程的方法: (1)继承一个Thread类,覆盖Thread类的run()方法: public class A extends Thread(public void run(){…..}); (2)继承一个接口Runnable来实现一个线程: public class A implements Runnable{public void run(){…..}}; 实例化一个线程: 对于(1):A a = new A(); a.start(); 对于(2):A a = new A(); Thread th = new Thread(a); th.start(); start()方法对于一个线程来说只能调用一次,如果再次start一个已经started的线程,则会抛出一个unchecked exception(IllegalThreadStateException) | |
5 | 线程的4种状态: | |
主函数入口点,作为一个线程(main thread,主线程)在后台运行 |
十一、异常处理(Exception)
序号 | 规则说明 | |
1 | 定义:异常是在程序执行期间中断指令的正常流程的事件; | |
2 | 异常有两种: | |
运行时异常 | 它是在java运行时系统内发生;如算术异常(被零除),指针异常(通过一个null引用访问对象成员)、索引异常(如试图用太大或太小的索引访问数组中的元素) 方法不必捕获或者指定运行时异常; | |
非运行时异常 | 它是在java运行时系统外的代码中发生的异常,比如输入输出期间的异常,它也叫被检查的异常(checked exception) | |
3 | 在异常处理中所涉及到的关键字:try、catch、throw、throws、finally | |
4 | 构造异常处理器的步骤: a、 将可能抛出异常的语句封闭在try块中; b、 然后在catch块中捕获并抛出异常(可以多个); c、 最后在finally块中释放在try块中资源(可有可无,视情况而定); | |
5 | 在程序中使用异常的优点: a、 将错误处理代码与常规代码分离; b、 将错误沿调用堆栈向上传递; c、 将错误类型进行分组和区分 | |
6 | 在一个捕捉异常的句子中,必须包含try{}的语句块,而catch和finally块两者必取其一或者都有,其中catch语句块可以有多个,catch块捕获的异常类型必须是子类异常在前,父类在后; | |
7 | 当try、catch和finally三块都有时,无论在try或者catch块中使用了return或者break也好,都将执行finally块中的语句; | |
8 | 在开发当中,我们一般使用finally语句块来清除错误或者异常发生时的无用的内存资源; | |
9 | error | 在java虚拟机中发生dll链接故障或者其他硬故障时,jvm抛出error。典型程序不应该也不可能捕获error。 |
Exception | 所有的Exception子类都是派生自Exception类; | |
10 | 左图中: 大的红圈表示thirowable类的子类error和exception下的子类runtimeException都属于uncheck Exception,小的红圈表示exception的其它子类都属于check Exception |
十二、集合(Collections)
1、Overriding toString()、equals()和hashCode()
序号 | 内容 | |||
1 | 三个方法都是都是属于object类的public的方法,有返回值的方法; | |||
2 | 方法 | 返回类型 | 不覆盖 | 覆盖 |
toString() | String | 默认返回值为: obj.getClass()+@+obj.hashCode() 其中hashCode值为无符号十六进制数; | 当需要了解对象的相关信息时,可以根据程序的要求以及对象中的字段等等去返回一个字符串; | |
equals() | boolean | 在object类中,判断是否引用对象(references)是否指向同一片内存,是则返回true; | 可以在不指向同一片内存但满足程序需求来判断是否返回true,否则返回false; | |
hashCode() | int | 一个无符号的十六进制整数 | 覆盖的话可以根据程序所要求的算法返回一个int类型,尽可能返回具有唯一性的值; | |
3 | 覆盖一个equals()方法,要满足以下条件: Reflexive(反自身的)即 obj.equals(obj) =true应该恒成立; Symmetric(对称的)即obj1.equals(obj2)=true时,obj2.equals(obj1)=true; Transitive(可传递的)即当x.equals(y) =true 并y.equals(z) =true时x.equals(z) =true; Consistent(一致性)即如果x.equals(y) =true或者为false时无论什么时候判断都返回相同的值; | |||
4 | 覆盖一个hashCode()方法,要满足以下条件: a、当obj1.equals(obj2)=true时,obj1.hashCode() = obj2.hashCode()恒成立; b、当obj1.hashCode() = obj2.hashCode()时,obj1.equals(obj2)不见得返回true,也有可能返回false; c、在同一个应用程序中,无论什么时候调用hashCode()方法时,返回值都必须保持一致; | |||
5 | equals()和hashCode()的关系 | |||
方法 | 返回值 | 与hashCode()的关系 | ||
A.equals(B) | true | A与B的hashCode()肯定相等; | ||
false | A与B的hashCode()有可能相等; | |||
一般在覆盖equals()方法时都要覆盖hashCode()方法; If two objects are equal, their hashcodes must be equal as well. | ||||
6 | 在collections中的HashMap 和HashSet 经常用对象的hashCode值来决定它的存储位置或者定位它的存储位置,它有点类似与表中的primaryKey,应该尽可能的使hashCode值具有的唯一性。 |
2、Collections
序号 | 内容 |
1 | 一个implements类如果是sorted类型那么它一定是ordered类型(an implementation class can never be sorted but unordered, because sorting is a specific type of ordering) |
3、Ordered、Sorted
接口 | Implements | Ordered | Sorted | Synchronized | 属性 |
List | ArrayList | √ | × | By index | |
LinkedList | √ | By index | |||
Vector | √ | √ | By index | ||
Set | HashSet | ||||
LinkedHashSet | √ | By insertion order or last access order | |||
TreeSet | √ | By natural order or common comparison rule. | |||
Map | HashMap | ||||
Hashtable | √ | ||||
LinkedHashMap | √ | By insertion order or last access order | |||
TreeMap | √ | By natural order or common comparison rule. |
4、List接口
接口 | 内容 |
List | List是一个有序的集合,有时称为序列,可以包含重复元素 |
ArrayList | 1、我们可以将其看作是能够自动增长容量的数组; 2、利用toArray()返回一个数组; 3、Arrays.asList()返回一个列表; 4、迭代器(Iterator) 给我们提供了一种通用的方式来访问集合中的元素; |
LinkedList | 1、LinkedList是采用双向循环链表实现的。 2、利用LinkedList实现栈(stack)、队列(queue)、双向队列(double-ended queue )。 |
Vector | |
ArrayList和LinkedList的异同: | |
1 | ArrayList底层采用数组完成,而LinkedList是以一般的双向链表完成,其中的元素除了数据本身外,还有两个引用,分别指向前一个元素和后一个元素。 |
2 | ArrayList在遍历时的性能要高于LinkedList,但LinkedList在增加和删除时的性能要高于ArrayList |
Vector与ArrayList的区别: Vector的方法都是synchronized的(多线程安全),而ArrayList是unsynchronized的 |
5、Set接口
接口 | 内容 |
Set | Set的value具有唯一性(Unique);由equals方法来决定是否存在所要加入的值; |
HashSet | 1、实现Set接口的hash table(哈希表),依靠HashMap来实现的。 2、我们应该为要存放到散列表的各个对象定义hashCode()和equals()。 |
TreeSet | 保证它里面的元素根据natural order升序或者根据自己的规则进行排序; |
LinkedHashSet | 它是ordered型的doubly-linked的HashSet, |
HashMap | UnSynchronized for thread,允许一个null Key多个nullValue |
HashSet和TreeSet的比较: HashSet是基于Hash算法实现的,其性能通常都优于TreeSet。 我们通常都应该使用HashSet,在我们需要排序的功能时,我们才使用TreeSet; |
6、Map接口
接口 | 内容 |
Map | Map是一个将key映射到value的对象,其中key是唯一的,每个key与value是一一对应的 |
HashMap | 1、它是一个unordered、unsorted的Map; 2、允许一个为null的key,同时也允许多个为null的value; |
Hashtable | 不允许有为null的key或value; |
LinkedHashtable | Remove或者add元素的效率低于Hashtable,但遍历的效率高于Hashtable; |
TreeMap | 1、保证它里面的元素根据natural order升序或者根据自己的规则进行排序; 2、并根据key值进行排序; |
Hashtable是一个synchronized的HashMap | |
HashMap和TreeMap的异同: HashMap的速度通常都比TreeMap快,只有在需要排序的功能的时候,才使用TreeMap。 | |
HashMap和Hashtable的异同: | |
1. | Hashtable是Dictionary的子类,HashMap是Map接口的一个实现类; |
2. | Hashtable中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。即是说,在多线程应用程序中,不用专门的操作就安全地可以使用Hashtable了;而对于HashMap,则需要额外的同步机制。但HashMap的同步问题可通过Collections的一个静态方法得到解决:Map Collections.synchronizedMap(Map m) , 这个方法返回一个同步的Map,这个Map封装了底层的HashMap的所有方法,使得底层的HashMap即使是在多线程的环境中也是安全的。 |
3. | 在HashMap中,可以允许唯一的一个null值作为键;但可以有一个或多个value值为null。当get()方法返回null值时,即可以表示HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。 |
Map中的key是唯一的; HashMap对key进行散列, TreeMap按照key进行排序。 |
十三、Socket编程
1、什么是socket?
所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。
2、重要的Socket API:
java.net.Socket继承于java.lang.Object,有八个构造器,其方法并不多,下面介绍使用最频繁的三个方法:
1 | . Accept方法用于产生"阻塞",直到接受到一个连接,并且返回一个客户端的Socket对象实例。"阻塞"是一个术语,它使程序运行暂时"停留"在这个地方,直到一个会话产生,然后程序继续;通常"阻塞"是由循环产生的。 |
2 | . getInputStream方法获得网络连接输入,同时返回一个IntputStream对象实例,。 |
3 | . getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。 |
注意:其中getInputStream和getOutputStream方法均会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。 |
3、如何开发一个Server-Client模型的程序?
开发原理:
服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。
客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。
//建立服务端
import java.net.*;
import java.io.*;
public class Server {
private ServerSocket ss;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Server() {
try {
ss = new ServerSocket(10000);
while (true) {
socket = ss.accept();
in = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
String line = in.readLine();
out.println("you input is :" + line);
out.close();
in.close();
socket.close();
}
ss.close();
} catch (IOException e) {
}
}
public static void main(String[] args) {
new Server();
}
}
这个程序建立了一个服务器,它一直监听10000端口,等待用户连接。在建立连接后给客户端返回一段信息,然后结束会话。这个程序一次只能接受一个客户连接。
//建立客户端
import java.io.*;
import java.net.*;
public class Client {
Socket socket;
BufferedReader in;
PrintWriter out;
public Client() {
try {
socket = new Socket("xxx.xxx.xxx.xxx", 10000);
in = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader line = new BufferedReader(new InputStreamReader(System.in));
out.println(line.readLine());
line.close();
out.close();
in.close();
socket.close();
} catch (IOException e) {
}
}
public static void main(String[] args) {
new Client();
}
}
十四、接口与抽象类的异同
相同点:1、均不能生成实例(不能使用new生成实例)
2、可以声明变量,但必须指向子类或者实现类的对象(即不能为private)
3、在接口中可以声明一个标记接口(即没有任何方法声明,表示具有某种功能)
在抽象类中可以声明一个没有抽象方法的抽象类
不同点:1、java只允许子类有一个父类,不允许多重继承,但子类可以实现多个接口
2、接口比抽象类应用更广泛、灵活
3、接口内不能有任何实例字段,但抽象类可以有实例字段以及实现了的方法
4、接口内的所有方法默认为public,而抽象类必须手动标识
5、继承类不必实现抽象类中的所有abstract方法,而实现类必须实现接口中的所有方法
十五、在实际应用开发中怎样抽象一个类?
确定类的方法就是寻找需求分析中的名词,另一方面主要是与需求分析中的动词相对应。在实际的开发中只有依靠经验才能确定究竟哪些名词与名词是必须的。
附录----类的设计技巧:
1、 永远保持数据私有;
2、 永远初始化数据;
3、 在一个类中不要过多的使用基本数据类型,要尽可能的封装;
4、 尽量使类的功能单一化;
十六、throw与throws的区别
1、 throw代表动作,表示抛出一个异常的动作;throws代表一种状态,代表可能抛出的异常;
2、 throw用在方法中实现,而throws用在方法的声明中;
3、 throw只能用在抛出一种异常,而throws可以抛出多个异常。
十七、this的用法:
1) this只能用在一个实例当中,而不能用在static方法中;
2) this是当前执行对象的引用,换句话说:这个对象的引用主要是用来调用正在运行的方法;
3) this可以作为一个方法的参数来调用;
十八、JDBC
1、 数据库驱动程序和URL:
数据库名 | 驱动程序 | URL |
MSSQL Server2000 | com.microsoft.jdbc.sqlserver.SQLServerDriver | jdbc:microsoft:sqlserver://[ip]:[port];databaseName=[databaseName] |
JDBC-ODBC(Access) | sun.jdbc.odbc.JdbcOdbcDriver | jdbc:odbc:[odbcsource] |
Oracle oci8 | oracle.jdbc.driver.OracleDriver | jdbc:oracle:oci8:@ [ip]:[port]:[sid] |
Oracle thin Driver | oracle.jdbc.driver.OracleDriver | jdbc:oracle:thin:@[ip]:[port]:[sid] |
MySQL | org.gjt.mm.mysql.Driver | jdbc:mysql://ip/database |
Cloudscape | COM.cloudscape.core.JDBCDriver | jdbc:cloudscape:database |
2、 数据连接:Connection con = DriverManager.getConnection(url,username,password);
3、 建立会话:Statement st = con.createStatement();
其他知识点:
1、 接口中的变量默认修饰符为:public static final;
2、 所有类的实例都共享类的static的方法和变量,任何该类的对象对static变量的改变,都将影响到其他的对象;
3、 包外的子类只能通过继承的方式去访问包里的父类中protected成员而不能通过父类的实例去访问。同一个包中的任何类都可以访问一个类中的protected成员。英文原文:
For subclass outside the package, the protected member can be accessed only through inheritance, a subclass outside the package can’t access a protected member by using a reference to an instance of the superclass ,in other words, inheritance is the only mechanism for a subclass outside package to access a protected member of its superclass.
4、 OOAD:面向对象的分析设计(Object Oriented Analysis Design)
5、 Java的数组(Array)、Vector、ArrayList、HashMap的异同
序号 | 异同 |
1 | array(数组)和Vector是十分相似的Java构件(constructs),两者全然不同,在选择使用时应根据各自的功能来确定。 Array:arrays的元素个数不能下标越界,保证了Java程序的安全性。 Array可以存放Object和基本数据类型,但创建时必须指定数组的大小,并不能再改变。值得注意的是:当Array中的某一元素存放的是Object reference 时,Java将其初值设为null。 |
2 | Vector:当更多的元素被加入进来以至超出其容量时,Vector的size会动态增长,而Array容量是定死的。同时,Vector在删除一些元素后,其所有下标大于被删除元素的元素都依次前移,并获得新下标比原来的小了。注意:当调用Vector的size()方法时,返回Vector中实际元素的个数。 Vector内部也是通过元素的整数索引来访问元素,但它只能存Object对象,不能用于存放基本类型数据,比如要存放一个整数10,得用Integer包装类对象再放进去。当Vector中的元素个数发生变化时, 其内部的Array必须重新分配并进行拷贝。 Vector同时也实现了List接口,所以也可以算作Collection了,只是它还特殊在:Vector is synchronized。即Vector对象自身实现了同步机制。 |
3 | ArrayList:实现了List接口,功能与Vector一样,只是没有同步机制(ArrayList is not synchronized。),当然元素的访问方式为从List中继承而来,可存放任何类型的对象。 |
4 | HashMap类继承了Map接口,实现用Keys来存储和访问Values,Keys和Values都可以为空,而Hashtable类的Keys不能为null,并Hashtable类有同步机制控制,而HashMap类没有。 |