空谷悠悠-J2SE
Jar 命令
-c 创建新的jar文件
-f 指定jar文件的名称
jar cf test.jar test
讲当前目录下的test目录中的所有文件压缩到test.jar文件中
Jdk的安全机制:
编译器编将一个.java文件后编译成.Class文件,首先由类装载器(classLoader)负责把类文件加载到java虚拟机中,它通过区分本地文件系统的类和网络系统导入的类增加安全,这可以限制任何的特洛伊木马程序,因为本地机上的类文件总是先被加载的,一旦所有的类文件被加载完,执行文件的内存的划分就固定了。然后字节码校验器进行校验,字节码校验器不检查那些可信任的编译器所生成的类文件。字节码校验器主要执行下面的检查:加载的类符合jvm规范的类文件格式,代码没有造成堆溢出,没有非法的数据类型转换。字节码校验器在java源程序中,会执行try-catch-finally语句并捕获和响应java的程序错误。如果字节码校验通过,java解析器负责把该文件解释成机器码进行执行。
体系的中立指java编译器通过伪编译后,生成一个与任何计算机无关的字节码。
实例成员包括实例成员方法和实例成员变量;类成员包括类成员方法和类成员变量
实例变量又称为成员变量;类变量是用关键字static声明的实例变量。
实例变是在类被加载时创建的,因此类变量的生存周期是类的生存周期。量是在new xxx()创建该类的实例时被创建,因此生命周期与改类的实例相同。
类变量
类的普通方法可以访问类的所有的成员和方法,而静态方法只能访问类的静态成员和静态方法。
public class valueORcite {
static int x=1; public void setValue(int x){ } public static void main(String[] args){ //int x=1; System.out.println("x1="+x); x++; System.out.println("x2="+x); public void Test(){ } int i,j,n; i =100; while(i>0){ } j=i*5; n=n+1; i--;
1
空谷悠悠-J2SE
} } valueORcite v = new valueORcite(); v.setValue(x); System.out.println("x3="+x);
输出值:
x1=1
x2=2
x3=1
方法中定义的变量成为形参,在调用该方法时传入的常数是实参。
下面介绍传地址:如果传递的是指向对象的引用,那么就会将对象的地址传递给形参
Test t = new Test();
trySet(t)
标示符的定义规则:以字母、美元符$、下划线_开头,以字母、美元符$、下划线_、数字结尾 String s = 魏飞 ----这也是合法的定义,因为java中使用的时Unicode字符集
/**/ 文档注释符,可以通过javadoc命令生成所编程序的API
==用来判断两个变量指向的是否为同一对象;equals()用来判断两个变量指向的对象的值是否相等。
Equals()只能比较引用类型,而==还可以比较基本类型。
X++ = y+1;
Java程序中,总共有8种基本数据类型,又可细分为4种整形数据 byte(8)、short(16)、int(32)、long(64);一种字符型char(16);2种浮点型float单精度(32)、double双精度(64)和一种布尔型boolean。
实数类型也称为浮点类型
浮点数既是小数,小数在默认情况下为double型;
float f = 3.14f ;long l = 10000L;
根据进制,又可分为10进制、8进制、16进制。其中8进制以0开头,16进制以0x或0X开头
基本类型和包装类之间的转换:
Integer it = new Integer(5)
int i = it.intValue();
基本类型和复合类型之间的转换
String s = Integer.toString(5);
String s = “123”;
int i = Integer.praseInt(s);
byte b = Byte.praseByte(s);
2
空谷悠悠-J2SE
int s= 0;
}
Final 变量只可以被赋值一次。在方法调用时,final 形参被赋予实参的值。在方法内部,不能对final参数进行重新修改或是赋值。
Static void User(fianl x ,int y){
}
public class Test{
} A b2[0][1] = b;
B b[0][0] = b3; C b2[1][1][0] = b[0][0];
D b2[0][1][0][0] = b[0][0]; E b2[1][2][0] = b;
F b2[0][1] = big;
Java.lang.String类是final类型的,因此不可以继承且修改这个类。
异常:在java的lang包有一个Throwable类,它是所有异常的父类或间接父类。每个异常类型都是Throwable类的子类,这其中有两个直接子类:Error和Exception。Error类及其子类是用来处理系统内部及程序运行环境的异常,由系统直接处理,不需要程序员在程序中处理。
Exception类是程序能够捕获到的异常情况。它又可以分为两大类:运行时异常RuntimeException和检查型异常(也称非运行时异常),列举常见的运行时异常:ArithmeticException、ArrayIndexOutOfBoundsException、ArrayStoreException、ClassCastException、indexOutOfBoundsException、nullPointerException、NumberFormatException
classNotfoundException 等等;检查型异常、public static void mian(String [] args){ byte[][] big = new byte[7][7]; byte[][]b = new byte[2][1]; byte b3 = 5; byte b2[][][][] = new byte[2][3][1][2]; } X++; X = z; if(++s){
线程、数据库等操作必须添加捕获检查型异常的程序。即java编译器必须声明抛出可能发生的所有非运行时异常,但是并不要求必须声明抛出未捕获的运行事异常,因为系统会自动处理运行时异常。
异常处理方式一 try/catch 捕获异常
3
空谷悠悠-J2SE
Int a =0;
Try{
int z = 5/a;
}catch(Arithmetic e){
System.out.println(“o不能作为除数”);
}
System.out.println(“end”)
异常处理方式二:throws 声明异常
声明异常是指一个方法不处理它产生的异常,而是向上传递,谁调用这个方法,这个异常就由谁来处理。声明异常在方法的头部通过关键字throws表示。某个方法(包括mian方法)调用时,该方式需要中内部try catch捕获异常。
异常处理方式三:throw 抛出异常
当一个方法发生异常时,可以通过throw关键字来抛出异常,把异常跑给它的上一级的调用者,抛出的可以异常引用,也可以是异常对象。
一个方法如果使用throw来抛出异常,要么自己捕获它,要么声明抛出一个异常。
内存管理:
垃圾回收需要占用系统的资源,因此在执行应用的过程中执行垃圾回收将导致应用程序的延迟。由于不知道何时进行垃圾回收,因吃应用程序的延迟是无法预知的。----垃圾回收的主要的问题是程序无法估计时间延迟而导致的应用程序的延迟。
垃圾回收算法一般要做两件基本的事情:发现无用信息对象;回收被无用信息对象占用的资源。Java的垃圾回收机制一般包括10种算法,其中最简单的一个:引用计数法。当某对象的引用数为0时,便可以进行垃圾收集了。
并不是对象被丢弃,就立即回收:
Jvm进程做空间回收是有较大的系统开销的。在实际的项目开发中,丢弃、创建一个对象这样的操作不计其数。如果某一应用进程丢弃一个对象,jvm就立即回收它的空间,势必会使整个系统的运行效率非常底下。
Java垃圾回收机制是为所有的java应用程序服务的,而不是为某个特定的进程服务的。因此任何一个进程都没有权利去命令垃圾回收机制做什么、怎么做或做多少。
Finalize()方法:jvm垃圾收集器收集一个对象前,一般要求程序调用适当的方法释放资源,但在没有明确释放资源的情况下,java提供了默认的机制来终止化该对象并释放资源,这个方法就是finalize
根据java语言规范,jvm保证调用finalize函数之前,这个对象是不可达的,但是jvm不保证这个函数一定会被调用。另外,规范还保证finalize函数最多运行一次。
不能保证一个无用的对象一定会被垃圾收集器收集,也不能保证垃圾收集器在一段java语言代码中一定会被执行。因此在程序执行过程中被分配的内存空间可能会一直保留到该程序执行完毕,除非该空间被重新分配或被其它方法回收。由此可见,完全彻底的根绝内存渗漏体的产生也是 不可能。
4
空谷悠悠-J2SE
Java语言使用一种“标记交换区的垃圾收集算法”。该算法会遍历程序中的每个对象的句柄,为被引用的对象做标记,然后回收尚未做标记的对象。
Java语言允许程序员为任何方法添加finalize方法,该方法会在垃圾收集器交换回收对象之前被调用,但不要过分的依赖方法对系统资源进行回收和再利用,因为该方法调用后的执行结果是不可预知的。
File 类的构造器:
Public File(String pathname):使用指定的路径,创建一个file对象。
Public File(String parent,String child):使用指定的路径和字符串创建一个file对象。
File 类的方法:
Public string []list():若对象代表目录,则将目录下的文件名存储于string数组中,并返回,若当前对象不是目录,则返回null。
Public File[] listFiles():若对象代表目录,则将当前目录下的所有文件转换成File对象,在返回File数组,否则返回null。
RandomAccessFile类,它支持随机存取文件的读取和写入,可以转跳到文件的任意位置处读写数据。常用的方法:
RandomAccessFile(File file ,String mode):指定的模式打开file文件对象供读写
public static void main(String[] args) throws FileNotFoundException{
File file = new File("G:\\myeclipse工作空间","data.txt"); byte[] bf = new byte[(int)file.length()]; RandomAccessFile rf = new RandomAccessFile(file,"rw"); try { rf.read(bf);//将文件中的内容全部读入字节数组中 for(int i = 0;i<bf.length;i++){ bf[i]= (byte)(bf[i]+12);//数据加密算法,对每个字节加12. } rf.setLength(0);//将文件中以前的内容清除掉 rf.write(bf);//将字节数组中的内容读入到文件中 } catch (IOException e) { } File f = new File("G:\\myeclipse工作空间","data1.txt"); RandomAccessFile rf1 = new RandomAccessFile(f,"rw"); byte[] b1 = bf; try { // TODO Auto-generated catch block e.printStackTrace();
5
空谷悠悠-J2SE
} rf1.read(b1); for(int i =0;i<b1.length;i++){ b1[i]=(byte)(b1[i]-12);//按照上面的算法,对文件进行解密 } rf1.setLength(0); rf1.write(b1); // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { }
流stream就是数据流向某个对象,并且到达这个对象的过程。根据数据类型的不同,流可以分为两种:一种就是字节流(byte流),一次读写8位二进制数;一种就是字符流(character流),一次读取16位二进制数。
字节流的两大父类:InputStream和OutputStream
InputStream中的方法:
Int available():返回流中可供读入的(或跳过)字节数目。
Void close():关闭输入流。释放相关的资源。
Abstract int read():从流中读入一个字节的数据。
Int read(byte【】 b):从流中读入最多b.length大小的数据,并存储到b中。
Int read(byte 【】b,int off ,int ;len):读入最多len个数据存储到b中,off指示开始存放的偏移位置。
Void mark(int readlimit):标记输入流中的目前的位置。
Void reset():将流重新定位到mark方法最后一次执行的位置。
Long skip(int n)
InputStream的直接子类:FileInputStream,ObjectInputStream,PipedInputStream,SequenceInputStream,StringBufferInputStream,ByteArrayInputStream,FilterInputStream
OutputStream的直接子类:
FileOutputStream,ObjectOutputStream,FilterOutputStream,ByteArrayOutputStream,PipedOutputStream.
InputStream和OutputStream都是抽象类,并不能直接使用,需要使用它的子类来创建对象。
FileInputStream是InputStream的直接子类,其对象的构造方法如下:
FileInputStream(File file):以指定名字的文件对象为数据源建立文件输入流。
FileInputStream(FileDescriptor fdobj):以指定文件描述符为对象建立一个文件输入流。
FileInputStream(String name):以指定名字的文件为数据源建立文件输入流。
OutputStream,其对象的构造方法如下:
FileOutputStream(File file):以指定名字的文件对象为接收端建立文件输出流。 6
空谷悠悠-J2SE
FileOutputStream(File file,boolean append):以指定名字的文件对象为接收端建立输出流,append为true时,输出的数据将被追加到文件尾,否则将以覆盖的方式写文件。 FileOutputStream(String name):以指定名字的文件为接收端建立文件输出流。 FileOutputStream(String name ,boolean append):以指定名字的文件为接收端建立输出流,append为true时,输出的数据将被追加到文件尾,否则将以覆盖的方式写文件。
public static void main(String[] args) throws FileNotFoundException{ File f = new File("G:/myeclipse工作空间
/purejava/src","Groups.java");
byte[] b = new byte[(int)f.length()]; FileInputStream fis = new FileInputStream(f); try { fis.read(b); File fi = f.createTempFile("CopyNameClass",".java", new File("G:/myeclipse工作空间"));
FileOutputStream fos = new FileOutputStream(fi);
字符流,可以对16位字符进行处理,也就是一次性处理两个字节的流。字符流分为两类Reader和Writer,这两个类也是抽象类,所以实际中使用的是它们的子类。Reader和Writer也有较多的子类,其中InputStreamReader和OutputStreamWriter是由字节流转换到字符流的通道。
Reader的子类有:
BufferReader,CharArrayReader,StringReader,InputStreamReader,PipedReader,FilterReader
Writer的子类有:
BufferWriter,CharArrayWriter,StringWriter,OutputStreamWriter,PrintWriter,PipedWriter,FilterWriter
InputStreamReader的构造函数如下:
InputStreamReader(InputStream in):创建一个建立在输入流in的对象之上,采用系统默认的编码方式。
InputStreamReader(InputStream in,Charset cs ):创建一个建立在输入流in的对象之上,采用cs对象指定的字符集。
InputStreamReader(InputStream in,CharserDecoder dec):创建一个建立在输入流in的对象之上,采用dec指定的解码方式。 } } fos.write(b); fos.close(); fis.close(); // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) {
7
空谷悠悠-J2SE
InputStreamReader(InputStream in,String charsetName):创建一个建立在输入流in的对象之上,采用指定名称的字符集。
OutputStreamWriter的构造函数与上面对应的非常工整。
FileReader和FileWriter分别是InputStreamReader和OutputStreamWriter类的子类,用来读取字符文件和写入字符文件的便捷类,并且可以直接指定文件名称或File对象打开指定的文件。字符转换根据系统默认的编码类型,如果用户要指定编码,就使用Inputstreamreader与OutputStreamWriter。
缓存字符流BufferWriter和BufferReader类的使用可以提高字符流的处理效率。
public static void main(String[] args) throws IOException { // TODO Auto-generated method stub //BufferedReader br = new BufferedReader(new BufferedReader br = new BufferedReader(new FileReader(new InputStreamReader(System.in)); File("G:\\myeclipse工作空间\\purejava\\src\\io","Buffer.java"))); BufferedWriter bw = new BufferedWriter(new FileWriter(new File("G:\\myeclipse工作空间","buffer.txt")));
String input = null;
面向对象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象包括两个方面,一是过程抽象,二是数据抽象。
继承:是指能够直接获得已有的性质和特征,而不必重复定义它们,在面向对象中,继承是子类自动地共享父类中定义的数据和方法的机制。
封装:是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象的程序设计实现了对象的封装,使用户不必关心对象的行为是怎么实现的,java封装的目的是为了减少复杂性。 多态:指的是对象根据所接受的消息而做出的动态,同样的消息为不同的对象所接受时可导致完全不同的行动,多态性包括参数化多态性和包含多态性。
面试题:Java中实现多态的机制是什么?
方法的重写和重载,重写overriding是父类与子类之间的多态性的一种表现;重载overloading是一个类中多态性的一种表现。
内部类:是对java的重大改进,它对于简化事件处理非常有用。内部类也称为嵌套类。内部类允许一个类定义在另一个类,或一个语句甚至一个表达式中。在内部类中是不允许声明任何static成员。
外部类可以调用静态类的静态成员和非静态成员,而静态内部类只能访问外部类的静态成员。 } //System.out.println("please inpur character,and endwith end"); while(!(input=br.readLine()).equals(" ")){ } bw.newLine(); bw.close(); br.close(); bw.write(input); 8
空谷悠悠-J2SE
内部类的具体特征如下:
1、 内部类可以被定义在方法中,它可以访问外部类的final变量,并且方法本身传递给内部
类的参数也是fianl。
2、 内部类可以被定义为abstract抽象类。
3、 内部类可以被声明为private或protected。
4、 内部类可以作为一个接口,由另一个内部类去实现。
5、 非静态内部类不能声明任何static成员
抽象类:
面试题:抽象方法是否可同时为static,是否可同时为native,是否可同时为synchronized?
首先static的方法只能被子类static的方法覆盖,不能表现出多态性,因为多态性是通过引用来实现的,所以abstract和static不可以同时使用。Native的方法是通过引入c/c++或其它本地语言来实现,所以不能同时使用abstract和native。Synchronized和abstract也不能混合使用,因为synchronized同步的视同于对象。而不是不同实现的不同对象。
接口:是抽象类的变体,也具有数据成员与抽象方法。在java中接口是用于实现多继承的一种机制。
面试题:抽象类与接口有什么区别?
抽象类的特征如下:
1、 抽象类和抽象方法都必须用abstract关键字来修饰。
2、 抽象方法必须定义在抽象类中,抽象类的子类必须实现父类中的抽象方发,否则这个类还是
一个抽象类。
3、 数据成员可以是static fianl也可以不添加。
接口中的特征如下:
1、 接口没有构造方法。
2、 接口中声明的变量确均是final、static、public。
3、 接口中定义的方法均为抽象的和公共的。
4、 接口里的数据成员必须初始化,且数据成员均为常量。
在同一个类的不同构造方法中调用该类的其它构造方法时,需要使用this的形式,而且必须是在构造方法的第一行调用。
Java在执行子类的构造方法之前,会先调用父类中的无参构造方法,其目的ishi为了继承自父类的成员做初始化的操作,当父类有数个构造方法时,如果调用特定的构造方法,则可在子类的构造方法中第一行,通过super来完成。
多线程
在传统的程序语言中,大多数大的程序设计者习惯上考虑怎样使程序从头到尾顺序地执行个任务的方法,即一个程序只用一条执行路线,但是在生活中会有很多过程是同时发生的。多线程编程的含义是将程序任务分成几个并行的子任务,在多线程的程序中,多个线程可以共享一块内存区 域和资源。
面试题:什么是线程以及线程的基本状态?
线程指在程序执行过程中,能够执行程序代码的一个执行单位,每个程序至少都有一个线程,也 9
空谷悠悠-J2SE
就是程序本身。Java中的线程有5种状态:创建、就绪、运行、阻塞、终止
线程的创建包括线程体和线程对象两部分。线程体是由run定义的。创建线程有两种方式:继承Thread类、实现Runnable接口。
继承Thread和实现Runnable接口的区别?
Runnable接口除了拥有Thread类一样的功能以外,还具有一下功能:
1、 适合多个相同程序代码的线程处理同意资源的情况,可以把线程同程序中的数据有效分离,
较好的体现了面向对象的设计思想。
2、 可以避免由于java单继承特性带来的局限。
3、 增强代码的健壮性,代码能够被多线程共同访问,代码与数据是独立的。多个线程操作相同
的数据,与它们的代码无关。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例。
下面给一个Runnable接口创建多线程的实例。
package thread;
public class RunnableDemo extends ThreadRun implements Runnable {
}
Thread t2 = null; public void RDemo(RunnableDemo r1){ Thread t1 = new Thread(r1,"第一线程"); System.out.println("正在运行的是"+t1); t2 = new Thread(r1,"第二线程"); System.out.println("创建第二线程"); System.out.println("第一线程开始休眠"); t2.start(); try { t1.sleep(400); } catch (InterruptedException e) { System.out.println("第一线程错误"); } System.out.println("第一线程恢复运行"); } public void run() { for(int i =0;i<800;i+=100){ } System.out.println("第二线程错误"); System.out.println("第二线程的休眠时间:"+i); t2.sleep(i); try { } catch (InterruptedException e) { } System.out.println("第二线程结束"); }
10
空谷悠悠-J2SE
package thread;
public class ThreadRun {
}
package thread;
public class TestDemo_1 {
}
运行结果如下:
正在运行的是Thread[第一线程,5,main]
创建第二线程
第一线程开始休眠
第二线程的休眠时间:0
第二线程的休眠时间:100
第二线程的休眠时间:200
第二线程的休眠时间:300
第一线程恢复运行
我是RunnableDemo的父亲
第二线程的休眠时间:400
第二线程的休眠时间:500
第二线程的休眠时间:600
第二线程的休眠时间:700
第二线程结束
在操作系统中,进程通常被看作是系统资源的分配单位和独立运行的基本单位。一个任务就是一个进程;线程则是一个比较新的概念,它具有提高系统资源利用率、改善用户之间的通信效率等显著的作用
多线程是实现并发机制的一种有效手段。进程和线程一样,都是实现并发的一个基本单位。它们的主要差别体现在一下两个方面:
1、 同样作为基本的执行单位,线程是比进程更小的执行单位。
2、 每个进程都有一段专用的内存区域。一个进程碰溃后,在保护模式下 不会对其它的进程产
生影响,线程是进程内部单一的一个顺序控制流。与此相反,线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,线程共享内存单元(包括数据和代码),通过共享的内存单元来实现数据交换、实现通信与必要的同步操作。 public static void main(String[] args) { } RunnableDemo r1 = new RunnableDemo(); r1.RDemo(r1); System.out.println(r1.print()); public String print(){ return "我是RunnableDemo的父亲"; }
11
空谷悠悠-J2SE
深入学习:
多进程操作系统能同时运行多个进程(程序),由于cpu具备分时机制,所以每个进程都能循环获得自己的cpu时间片。由于cpu运行速度非常快,使得程序好像是在“同时”运行一样。 线程基本上不拥有系统资源,但是它可以与同属于一个进程的其它线程共享进程所拥有的所有资源。
进程在执行过程中拥有独立的内存单元,每个独立的进程都有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。一个线程可以创建和撤销另一个线程。同一个进程中的多个线程之间可以并发执行。
同步是各线程协调使用共享资源的一种方式,也就是说如果一个对象(或变量)同时被多个其它线程访问,那么这个对象必须使用线程同步。为了保证线程对共享资源使用的完整性,用关键字synchronized为共享资源加锁解决这个问题。其实每个对象都有一个“锁标志”,当某个对象的一个线程访问该对象的某个数据时,这个对象所有被synchronized修饰的数据将被锁上(因为锁标志被当前线程占用了),只用当前线程访问完它要访问的数据时,当前线程才会释放锁标志,这样同一对象的其它线程才用机会访问synchronized数据。
下面给出多项程的同步代码:
package thread;
public class TextThread implements Runnable {
private int num = 5; public void run() { while (true) { synchronized (this) { if(num>0){ try { Thread.sleep(100); System.out.println("睡醒了"); } catch (Exception e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName()+"数字为
"+num--);
}
package thread;
/**
* 是否能说明main线程优先级高于子线程 }else{ System.out.println(Thread.currentThread().getName()+"退出了"); break; } } } }
12
空谷悠悠-J2SE
* @author Administrator
*
*/
public class test {
}
运行结果如下:
main thread is over1
main thread is over2
睡醒了
Thread-0数字为5
睡醒了
Thread-1数字为4
睡醒了
Thread-0数字为3
睡醒了
Thread-1数字为2
睡醒了
Thread-0数字为1
Thread-1退出了
Thread-0退出了
在同一个类中,只要有可能访问类成员变量的方法均被声明为synchronized,这些synchronized方法可以在多个线程之间同步,当有一个线程进入了有synchronized修饰的方法时,其它线程就不能进入同一个对象使用synchronized来修饰的多有方法,直到第一个线程执行完它所有进入的synchronized修饰的方法为止。
面试题:线程同步的方法?
同步是线程间协调使用共享资源的一种。各线程间的相互通讯是实现同步的重要的因素。所以java提供了wait、notify等方法来使线程间可以相互通讯。
Wait:是线程进入等待状态,并且释放所持有对象的lock所以与notify方法配合使用。 Sleep:使一个运行的线程进入阻塞状态,但设定时间过后,线程重新进入可执行状态。
Notify:唤醒一个处于等待状态的线程,但并不确定的唤醒哪一个线程,而是由jvm确定,不是由优先级确定。
notifyAll:唤醒所有处于等待状态的线程,注意并不是给所有的线程一个对象的lock,而是让它们竞争,只有获得lock的线程才能进入可执行状态。
Yield方法是指暂停当前正在执行的线程对象,并执行其他线程。暂停执行是指在前线程放弃所 分得的cpu资源,并不是使线程处于阻塞状态,即线程仍处于可执行状态,随时可能再次分得public static void main(String[] args) { } System.out.println("main thread is over1"); TextThread t1 = new TextThread(); new Thread(t1).start(); new Thread(t1).start(); System.out.println("main thread is over2"); 13
空谷悠悠-J2SE
cpu。调用yield的效果相当于调度程序认为该线程已经执行了足够的时间而转到另一个线程。
编程题:创建两个线程,每个线程打印出线程的名字后再睡眠,给其它线程以执行的机会,每个线程前后睡眠5次,最后打印线程结束信息。
public class mytest extends Thread {
int time ; public mytest(int t ){ } public synchronized void run(){ for(int i = 1;i<=5;i++){ System.out.println(Thread.currentThread().getName()+" " + i
try {
Thread.sleep(time);
//System.out.println("我决定不睡觉了");
} catch (Exception e) {
}
if(5==i){
System.out.println(Thread.currentThread().getName()+" "
e.printStackTrace(); time =t; +"次"); + i +"退出了"); }
}
打印结果如下:
线程1 1次
线程2 1次
线程2 2次
线程1 2次
线程1 3次
线程2 3次
线程1 4次
线程2 4次
线程1 5次 } } public static void main(String[] args) { } mytest m1 = new mytest(500); m1.setName("线程1"); m1.start(); mytest m2 = new mytest(500); m2.setName("线程2"); m2.start();
14
空谷悠悠-J2SE
线程2 5次
线程2 5退出了
线程1 5退出了
编程题:
设计4个线程,其中两个线程每次对j增加1,两个线程每次对j减少1. public class ThreadIncOrDec {
private int j ;
public static void main(String[] args) { } private synchronized void incValue(){ } private synchronized void decValue(){ } public class IncThread extends Thread{ } public class DecThread extends Thread{ public DecThread(String name){ } public void run(){ super(name); public IncThread(String name){ } public void run(){ } for(int i =0;i<5;i++) incValue(); super(name); j--; System.out.println(Thread.currentThread().getName()+"-dec j++; System.out.println(Thread.currentThread().getName()+"-inc ThreadIncOrDec tid = new ThreadIncOrDec(); IncThread inc1 = tid.new IncThread("自增线程1"); IncThread inc2 = tid.new IncThread("自增线程2"); DecThread dec1 = tid.new DecThread("自减线程1"); DecThread dec2 = tid.new DecThread("自减线程2"); inc1.start(); inc2.start(); dec1.start(); dec2.start(); "+j); "+j);
15
空谷悠悠-J2SE
} } } for(int i =0;i<5;i++) decValue();
线程的运行结果随意性。
类集框架:将常用的数据结构和算法封装在里面。
Collection接口是构造类集框架的基础,因为所有的类集实现了Collection,以下给出了这些方法:
Boolean add(object obj)、boolean addAll(Collection c) 、void clear() Boolean contains(object obj)、boolean containAlls(Collection c) boolean remove(Object obj)、boolean removeAll(Collection c)、object[] toArray(), int size()、boolean isEmpty()等等
List接口扩展了Collection并声明存储一系列元素的类集的特性,处理对象的列表。除了有Collection定义的方法之外,还定义了一些自己的方法:
Void add(int index,object obj):任何已经存在的,在插入点以及插入点之后的元素将前移,因此没有元素被覆盖。
Void addAll(int index,Collection c)、Object get(int index)、int indexof(Object obj)、object remove(int index)
Object set(int index,Object obj),用obj对列表内index指定的位置进行赋值,以前的元素将被覆盖
List subList(int start,int end) 返回一个列表,该列表包括了调用列表从start到end-1的元素。
Set接口扩展了Collection,用来处理集合。是一个不包含重复元素的集合,包含的方法有: Int size()、boolean isEmpty()、Boolean add(object obj)、boolean addAll(Collection c) 、void clear()
Boolean contains(object obj)、boolean containAlls(Collection c) boolean remove(Object obj)、boolean removeAll(Collection c)、object[] toArray()
描述Collection和Collections的区别是什么?
Collection是集合类的上级接口,继承它的接口主要有Set和List。Collections是针对集合类的一个帮助类,它提供了一系列静态方法实现对各种集合的搜集、排序、线程安全化等操作。
给段程序:
public class ListTest {
public static void main(String[] args) { List list = new ArrayList(); list.add("1"); list.add("2"); list.add(1,"3"); List list2 = new LinkedList(list); list.addAll(list2);
16
空谷悠悠-J2SE
} } System.out.println(list); list2 = list.subList(2,5); //list2.clear(); System.out.println(list);
运行结果为
[1, 3, 2, 1, 3, 2]
[1, 3, 2, 1, 3, 2]
给出几行代码
Calendar rightnow = Calendar.getInstance();
Date d = rightnow.getTime();
System.out.println(d);
结果如下:Tue Jan 19 16:02:14 CST 2010
List接口的实现类:
LinkedList链表类,实现了List接口,允许null元素。除了继承了的方法外,LinkedList类本身还定义了一些方法,如addFirst()方法可以在列表头增加元素;addLast()方法在列表的尾部增加元素;getFirst方法可以获得第一个元素;getLast方法得到最后一个元素;removeFirst方法可以删除第一个元素;removeLast可以删除最后一个元素。这些操作使LinkedList可以被用作堆栈stack、队列queue或双向队列,它具有两个构造函数: LinkedList();LinkedList(Collection c)
LinkedList没有同步方法,如果多个线程同时访问一个List,则必须自己实现访问同步,一种解决方法是创建list时构建一个同步的List。
List list = Collections.synchronizedList(new LinkedList(……));
ArrayList数组列表类:
ArrayList是对象引用的一个变长数组,也就是说能动态的增加或减小。和LinkedList一样,也是非同步的。
Vector存储类:
Vector非常类似于ArrayList,但它是同步的。
Stack 栈类:
Stack继承自Vector,实现一个后进先出的堆栈。基本方法有push()、pop()、还有peek方法,用来得到栈顶的元素。Empty方法测试堆栈是否为空。Search方法检测一个元素在堆栈中的位置。
Set接口的实现类
HashSet类使用散列表进行存储。而散列表通过使用称之为散列法的机制来存储信息。在散列(hashing)中,一个关键字的信息内容被用来确定唯一值,称之为散列码(hash code)。而散列码被用来当做与关键字相连的数据的存储的下标。关键字到散列码的转换是自动执行的----看不到散列码本身。
TreeSet类使用树结构进行储存的Set接口提供了一个工具,对象按首字母升序存储。
17
空谷悠悠-J2SE
Map 映射接口
Map没有继承Collection接口,它提供了key到value的映射。Map中不能包含相同的key,每个key只能映射一个value。Map接口提供3种集合的视图,map的内容可以被当作一组key集合、一组value集合或一组key-value映射
Hashtable继承了Map接口,实现了一个key-value映射的哈希表。添加数据方法put(key,value),取得数据的方法get(key)Hashtable通过initial capacity和loadfactor两个参数调整性能。通常默认的loadf.actor0.75较好的实现了时间和空间的均衡,增大了loadfactor可以节省空间,但相应的查找时间也将增大,这会影响get和put的操作.
Hashtable 是同步的,他可以存储重载由Object定义的hashCode和equals()方法的对象。hashCode方法计算和返回对象的散列码。
Hashmap和Hashtable类似,不同之处在于hashmap是非同步的,并且允许null,即null key和null value。。hashmap仍然使用哈希函数来计算关键字的哈希码,并存储在对应的位置上,所以记录之间是无序的,但它的存储和查找都很快,远远超过其它的类型集合。
面试题:Hashmap和Hashtable的区别
Hashmap是Hashtable的轻量级实现(非线程安全的实现),它们都完成map接口,主要区别在于hashmap允许将null作为一个entry的key或者value。Hashmap把Hashtable的contains方法去掉了,改成了containkey和containvalue。Hashtable继承自
Dicitionary类,而hashmap是java1.2引进的map interface的一个实现
两者最大的区别是,Hashtable的方法是synchronize的,而hashmap不是的,在多线程的访问中,hashmap就得自己为它的方法实现同步。Hashtable和hashmap采用的hash/rehash算法几乎都是一样的,所以性能不会有很大的差别。
Heap和stack有什么区别?
栈是一种线性集合,是自动分配变量以及函数调用时使用的一些空间。地址是由高向低减少的。其添加和删除元素的操作应同步完成。栈按照后进先出的方式处理。堆是栈的一个组成元素,它是有malloc之类的函数分配的空间所在地。地址是由低向高增长的。
List、map、set这3个接口在存取元素时各有什么特点?
List以特定次序来持有元素,可有重复元素。Set无法拥有重复元素和内部排序。Map保存key-value值,value可多个值。
ArrayList、Vector、LinkedList的存储性能和特性
ArrayList和Vector都是使用数组方式储存数据,此数组元素大于实际存储的数据以便增加和插入元素,它们都允许直接安序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据比插入数据快。由于Vector使用了synchronized方法,通常在性能上较
ArrayList差,而LinkedList使用双向链表实现储存,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后即可,所有插入数据较快。
数据库—基本数据定义
建立索引:
Create table user(id Integer [(100)] constraint user_id primary key) ----创建user表,将id字段设置成主键
18
空谷悠悠-J2SE
更改表字段
Alter table user add column name char(10)
----增加字段
Alter table user alter column name char(20)
----修改字段
Alter table user drop column name
----删除字段
Alter table user drop constraint user_id
----删除索引
数据库基本数据擦操作
增加数据:
更新数据
Update user set sex=’boy’ where id=’02’
删除数据
Delete from user where id=’03’
查询数据
Select * from user where id=’03’
在查询的时候使用谓词,从而得到更佳的查询结果。
Select distinct name from user
Select top 5 * from user order by id desc ----按序号排序的最后5条记录。
Group by 子句。由它指定字段中所有值相等的记录会被归为一组
Select avg(sal) from emp group by deptno
----求出每个部门的平均工资
Having子句,对搜索出来的数据继续过滤
Select avg(sal) from emp group by deptno having(avg(sal))>2000 -----求出平均工资不少与2000的部门的平均工资。
Order by 子句指定查询结果按照哪一个字段来排序。默认为升序asc,降序为desc。
按部门号求出每个部门工资在1200以上、所有人的平均工资,然后过滤掉平均工资小于1500的部门,最后按工资升序排序
Select avg(sal) from emp where sal>1200 group by deptno having (avg(sal))>1500 order by avg(sal)
Connection 类提供了3种事物处理方法。
setAutoCommit(boolean),是否自动提交事物,默认为自动提交事物。
Commit:提交事物
Rollback:回滚事物
19