1、java特点
简单:
易学好用。
面向对象:
基于对象的编程更符合人们的思维模式,使程序员更容易编写程序。
与平台无关:java解决了其他语言编写的程序因系统资源改变或者cpu等运行环境发生改变而不能运行的问题。java的目标是“一处写成,处处运行”,基本得到了实现。这都要归功于JVM,任何安装了JVM的计算机都能运行java程序。
解释型:
与其他编程语言不同的是,java编写的程序编译成字节码(一种接近机器语言的文件),该字节码文件可以再安装了JVM虚拟机的任何系统上被解释执行。
多线程:
内置多线程机制,允许同时执行多个任务。(C++没有内置多线程机制,需要调用系统的多线程功能进行多线程的设计)
安全:
java applet小应用程序,只允许在java运行环境中运行,不允许它访问计算机的其他部分。由此可知,其安全性不错。
动态:
指java可以在分布的环境中动态的维护程序和类库。与C++的区别就是,不必每次类库升级之后,如果让程序具有新类库提供的功能,需要修改程序、重新编译。
2、java运行的三种平台
J2SE
Java标准平台,桌面程序等。
J2EE
Java企业平台,包含了J2SE平台,用于比较大型系统场合。
J2ME
Java小型平台,用于手机,掌上电脑或其他无线设备。
3、什么是jsp
jsp是java Server pages的缩写,sun公司1999年推出的一种动态网页技术标准。jsp是基于java servlet以及整个java体系的web开发技术,利用这一技术可以建立安全、跨平台的先进动态网站,这项技术正在不断的更新和优化中。
4、java中的标示符、关键字和数据类型
标示符:
java规定标示符由字母、下划线、美元符号和数字组成。并且第一个字符不能是数字,区分大小写。
关键字:
java中被赋予了特殊含义的单词,不可以用来做名字。
case、continue、enum、find、native、synchronized等。
基本数据类型:
boolean 、int 、byte、short、long、char、float、double
5、运算符、表达式和语句
运算符与表达式:
加法、减法、乘法、除法、求余%、求整/、自增x++、++x、自减x--、--x、计算的精度排列顺序:byte、short、int、long、float、double
逻辑运算符:
&&:逻辑与 ||逻辑或 !逻辑非
赋值运算符:= 等号运算符:==
位运算符:
&:按位与 |按位或 ^按位异或
insuranceOf:是否是某个对象创建的实例,返回boolean。
6、语句
方法调用语句、表达式语句、复合语句、控制语句等。
控制语句:
条件控制语句:if(){} if(){}else{} //处理关系表达式和逻辑表达式
switch(){
case1:
……
break; //该语句只能处理等式
case2:
……
break;
}
循环语句:
for循环 :for(){}
while循环:while(){}
do—while()循环:do{}while()(循环体至少被执行一次)
break和continue语句
break:整个循环结束
continue:本次循环结束
7、面向对象编程
三个特点:
封装性:将数据和数对数据的操作封装在一起,取共同性质形成一般的概念,如类的概念。
继承:子类通过集成得到了父类的共性,同时还可以拥有自己的特性。
多态:有两种意义的多态,一种是操作名称(重载):多个操作具有相同的名字,但这些操作所接受的信息类型必须不同;另一种和继承有关,指同一个操作(覆盖)被不同对象调用时可能产生不同的行为。
注意:
(1)对成员变量的操作只能放在方法中,方法可以对成员变量和方法体中自己定义的局部变量进行操作。
(2)实例方法既能对类变量操作也能对实例变量进行操作,而类方法只能对类变量进行操作。
(3)一个类中的方法可以相互调用,实例方法可以调用该类中的其他方法;类中的类方法只能该类的类方法,不能调用实例方法。
8、对象:
对象声明(引用,指向的是空对象);分配内存(为对象实体分配内存空间)。
基本数据类型参数传递:向该参数传递的值的级别不能高于该参数的级别。
引用类型参数传递:参数是引用类型时,“传值”传递的是引用,而不是对象的实体。
this关键字:表示某个对象,可以出现在实例方法和构造方法中,但是不能出现在类方法中。
static关键字:类变量,存在于内存中的中的只有一块内存空间。
实例变量和类变量的区别:
不同对象的实例变量将被分配不同的内存空间,如果类中的成员变量有类变量,那么所有对象的这个类变量都分配给相同的一块内存,改变其中一个对象的这个类变量会影响其他对象的这个类变量,即上面所说的对象共享类变量。
实例方法和类方法的区别(分配入口之地的条件不同):
当类的字节码文件被加载到内存的时候,类的实例方法不会被分配入口地址,当该类创建对象后,类中的实例方法才分配入口地址,从而实例方法可以被类创建的任何对象调用执行。需要注意的是:当创建第一个对象时,类中的实例方法就分配了入口地址,当再次创建对象时就不再分配入口地址,即该方法的入口地址被所有的对象共享。当所有的对象都不存在时,入口地址才会被取消。同时,其中的类变量是和其他对象共享的,所以实例方法既可以操作实例变量也可以操作类变量。
对于类中的类方法,在该类被加载到内存时就分配了相应的入口地址。从而类方法不仅可以被类创建的任何对象调用执行,也可以直接通过类名调用。类方法的入口地址知道程序退出才会被取消。在java中有这样一个规定:类方法中出现的成员变量必须是被所有对象共享的变量(类变量),即类方法不可以操作实例变量。原因正是入口地址的分配条件不同。
9、java中常用的包
java.applet:包含所有实现java applet的类
java.awt:包含抽象工具集中的图形、文本、窗口GUI类
java.awt.p_w_picpath:包含窗口工具集中的图像处理类
java.lang:包含所有的基本与眼类
java.io:输入输出类
java.net:包含实现所有网络功能的类
java.util:包含有用的数据类型类
10、类的访问权限
private:在类Tom中,不论是私有变量(包括类变量)还是私有方法(包括类方法),都只能在Tom类中被访问,而不能被其他类访问。换个说法就是,该Tom类很好的保护了自己特有的变量和方法。
public:在类Tom中的变量(包括类变量)和方法(包括类方法)称为共有变量和共有方法。当在任何一个类中用Tom类创建了一个对象后,该对象能访问自己的public变量(类方法)和类中的public方法(类方法)。
不用private、public、protected修饰:这种情况下的,Tom类中的变量(类变量)和方法(类方法)称为友好变量和友好方法。创建对象的类与Tom类在同一个包中的时候,友好变量和友好方法可以被访问。
protected:称为受保护的成员变量(类变量)和方法(类方法)。在另外一个类中用Tom类创建了一个对象后,如果这个类与Tom类在同一个包中,那么该对象能访问自己的protected变量(类变量)和protected方法(类方法)。
public类和友好类:可以在任何一个另外的类中,使用public类创建对象;而对于友好类,在另外一个类中使用友好类创建对象的时候需要保证他们是在同一个包中。
注意:
不能用protected和private修饰类。
访问权限级别排列:public、protected、friendly、private
11、类的继承(java单继承:子类只有一个父类)
父类(超类、基类):具有共同属性和行为的一般类。
子类(派生类):具有父类的共同属性和行为,同时还可以增加自己特有的属性和行为。
子类与父类在同一个包中的继承性:子类继承了父类中不是private属性的变量和方法,同时其访问权限保持不变。
子类和父类不再同一个包中:子类只能继承父类中的public、protected修饰的变量和方法。
成员变量的隐藏和方法重写:子类中变量名称和方法(参数及返回类型)跟父类相同,此时父类中的变量被隐藏,方法被重写(方法重写时,不允许访问级别地低于父类的访问级别)。方法重写可以得到不同的结果。
另一个相似的概念是方法的重载:指方法名称相同(与返回值无关),但是参数不同(个数或类型),此时叫做方法的重载。
final关键字:可修饰类、成员变量(修饰时需要初始化,以后不能发生变化)和方法中的参数(方法中的参数被修饰为final,则该参数能被改变)。不能被继承。如String类就被修饰为final类,增强了安全性。
对象的上转型对象:A a=new B(); A为父类,B为子类,此时称A类对象a是子类对象b的上转型对象。a只能操作继承或隐藏的变量和方法。可以讲a强制转换到B类对象,此时就可以访问子类中新的变量和方法了。反之,不能将父类创建的对象的引用赋值给子类声明的对象。
super关键字:用于使用父类中的方法和变量。
如:父类中有f()方法,子类中调用则super.f();
12、abstract类和abstract方法
abstract类(抽象类):总结出事物的共性,使得代码易记忆、可读性好。
abstract方法(抽象方法):只允许声明,不允许实现,并且不能使用final修饰抽象方法。
(1)抽象类中可以有abstract方法。
(2)抽象类不能用new运算符创建对象。可以产生其子类,由子类创建对象,如果一个类是某抽象类的子类,则必须实现父类中的抽象方法。换句话说,就abstract类强制它的子类实现其中的abstract方法。
13、接口
为克服单继承带来的局限,java中允许一个类实现多个接口,并且也继承了父接口中的所有方法和常量。
接口中的方法默认是public和abstract方法,所以类在实现接口方法时必须给出方法体,并且一定要用public来修饰,另外,接口中的常量默认是public static常量。
14、内部类(类的另一种成员)
在一个类中声明另一个类(把该类当做成员看待),这样的类称为内部类。包含内部类的类称为内部类的外嵌类。内部类的外嵌类的成员变量在内部类中有效,内部类中的方法也可以调用外嵌类的方法。需要注意的是,内部类的类体中不可以有类变量和类方法。
15、匿名类
概念:当使用类创建对象的时候,程序允许把类体与对象的创建组合在一起,也就是说类创建对象时,除了构造方法还有类体,此类被认为是该类的一个子类去掉类声明后的类体,称为匿名类。
匿名类由于无名可用,所以不能用匿名类声明对象,一般用于直接用匿名类创建一个对象。
另外,匿名类一定是内部类,可以访问外嵌类中的成员变量和方法。匿名类中同样也不允许声明static变量和static方法。参数可以是对象引用,也可以是接口。
主要用途:匿名对象的引用必须传递给一个匹配的参数,即想方法的参数传值。
16、异常
异常:就是程序运行时 可能 出现的一些错误。
java中的异常处理:java中使用try-catch 语句来处理异常,将可能出现异常的操作放在try-catch语句的try部分。当try部分的某个语句方式异常后,try部分将立刻结束执行,而转向执行相应的catch部分,所以程序可以将发生异常后的处理部分放在catch部分。
java中出现了try,后面必须有catch或者finally。即try部分不会单独出现。
17、Class类
该类位于java.lang包中,该类的实例用于封装对象运行时的状态。当一个类被加载且创建对象时,和该类相关的一个类型为Class的对象就会自动创建。Class类不能用new运算符和构造方法创建一个Class对象。总之该类的作用就是,封装了当前对象的相关信息,比如类名、类中的方法名称、变量等信息。
实例化一个Class对象:
public static Class forName(String className) throws ClassNotFoundException 返回一个和参数className指定的类相关的Class对象。再让用它调用:
public Object newInstance() throws InstantionException、IllegalAcessException 方法就能得到一个className类的对象。
注意:使用上述方法时,className类必须具有无参构造方法。
18、StringBuffer类
String类:字符串对象,String类创建的字符串对象是不可修改的,也就是说String字符串不能修改、删除或替换字符串中的某个字符。即String对象一旦创建,那么实体就不可以在发生变化的。
StringBuffer类:该类创建可修改的字符串序列,也就是说该类对象的实体的内存空间可以自动改变大小,便于存放一个可变的字符序列。
比如:StringBuffer s = new StringBuffer(“i love you”);调用了append()方法可以得到:s.append(“too!”);
此时内存中就变成了:i love you too!
三个构造方法:StringBuffer()默认16个字符、StringBuffer(int size)实体的初始容量、StringBuffer(String s)初始化16,当长度大于16的时候会自动增加。
其他方法:
append()
StringBuffer insert(int index ,String s):将一个字符串插入实体的字符串序列中,返回当前对象的引用。
StringBuffer delete(int startIndex,int endIndex):删除的字符串从startIndex——endIndex-1
19、java多线程机制
程序、进程与线程
程序:一段静态的代码,是应用软件执行的蓝本。
进程:指程序的一次动态执行过程,它对应了从代码加载、执行至执行完毕的一个完整的过程,这个过程也是进程本身从产生、发展至消亡的过程。
线程:比进程更小的执行单位。一个进程在其执行过程中,可以产生多个线程,形成多条执行线索,每条线索,即每个线程也有它自身的产生、存在和消亡的过程,这是一个动态的概念。
进程与线程的比较: 每个 进程 都有一段专用的内存区域,与此不同的是,线程间可以共享相同的内存单元(包括代码和数据),并利用这些共享单元来实现数据交换、实时通信与必要的同步操作。多线程的程序能更好的表达和解决现实世界的具体问题,是计算机应用开发和程序设计的一个必然发展趋势。
线程的执行:
(1)默认情况先,JVM中的线程调度器将每个线程的优先级设置为 5 (调度器把线程的执行优先级分为10个级别,即1——10之间)。默认情况下得到的线程无优先级之分,都是公平抢占cpu资源。
(2)每个java程序都有一个主线程。java应用程序总是从主类的main()方法开始执行。
(3)过程是:当JVM加载代码,发现main()后,启动一个线程,该线程就被称之为“主线程”,负责执行main()方法。在main()中执行再创建的线程,就称程序中的其他线程。如main()中没有创建其他线程,则main()执行完后,即main()返回时,JVM就会结束java应用程序。当main()创建了其他的线程的时候,JVM就在主线程和其他线程之间轮流切换,目的是保证每个线程都有机会使用cpu资源。注意,这里即使main()执行完了最后的语句,如果还有其他线程存在的话则要等到其他线程都执行完毕之后,应用程序才会结束。即使main()中的线程(包括主线程和其他线程)会全部被执行完毕,只是开始的时候始终是有主线程开始的。
线程状态和生命周期
线程的创建:
(1)使用Thread类及其子类的对象来表示线程。Thread子类创建线程的优点为:可以在子类中增加新的成员变量,使线程具有某种属性,也可以在子类中增加新的方法,使其具有某种功能。
(2)实现Runnable接口,利用构造方法 Thread(Runnable target),代码示例如:
Class Bank implements Runnable{
Thread thread1,thread2;
Bank(){
thread1 = new Thread(this);
thread2 = new Thread(this);
thread1.setName("thread1");
thread2.setName("thread2");
}
}
上面的示例代码就是利用实现Runnable接口创建的两个线程。这里传递的参数是一个实现Runnable接口的实例,该实例被称做所创建线程的目标对象。当线程调用start()后,一旦轮到他来享用cpu资源,目标对象就会自动调用接口中的run()(即接口回调),这一过程是自动实现的。
对于使用同一目标对象的线程,目标对象的成员变量自然就是这些线程共享的数据单元;另外,创建目标对象类在必要时还可以是某个特定类的子类,因此,使用Runnable接口比使用Thread类的子类更具灵活性。
线程在其完整的生命周期中经历的4种状态:
(1)新建:对象被创建时处于新建状态,此时它已经有了相应的内存空间和其他资源。
(2)运行:线程创建之后就具备了运行的条件,一旦轮到它来享用cpu资源,即JVM将cpu的使用权切换给该线程时,此线程就可以 脱离 创建它的主线程,独立开始自己的生命周期了。注意,线程创建之后只是占有了内存资源,在JVM管理的线程中还没有这个线程,此线程必须调用start()(从父类继承的方法)通知JVM,这样JVM就知道有一个新线程排队等候切换了。当该线程得到cpu使用权后,如果线程是Thread的子类创建的,则该类中的run()就立刻执行。在子类中重修父类的run(),目的就是为了告诉该线程需要完成的操作(用户为之赋予的使命);在线程没有结束run()之前,该线程不能再次调用start()方法,否则会发生ILegalThreadStateException异常。
(3)中断:
4种原因的中断:
cpu使用权的交出;
执行了sleep(int millsecond)方法后,立刻进入休眠状态,即让出了cpu使用权,中断指定的时间后再次进入线程队列中排队等候,以便从中断处继续运行;
执行了wait(),使得当前线程进入等待状态。等待状态的线程不会主动进入线程队列中排队等够cpu资源,必须有其他线程调用notify()通知它,使得它重新进入线程队列中排队等待CPU资源,以便从中断处重新运行。(notify():通知处于等待的某一个线程结束等待;notifyAll():通知所有处于等待状态的线程恢复执行,遵循“先中断先继续”原则;wait():修改状态为等待;以上的三个方法用在同步方法中,解决了某个操作由于条件不满足而无法进行的问题)
执行某个操作进入阻塞状态,如读写操作引起的阻塞。进入阻塞状态时线程不能进入排队队列,只有当引起阻塞的原因消失后线程才重新进入线程队列中排队等候cpu资源,从原来引起阻塞饿中断处继续运行。
(4)死亡:线程释放了实体,即释放了所占有的内存资源。
死亡的原因有两个:一个是正常运行的线程完成了其全部工作,即结束了run();另一个原因是线程提前被强制性的终止,即强制结束了run()。
关于线程中的局部变量:
对于具有相同目标对象的线程,每个线程都执行他们各自的run(),而run()的局部变量也被分配在了各自的内存中。即两个线程中的局部变量不会相互干扰,一个线程中的局部变量发生改变不会影响到另一个线程中的局部变量。
线程中的常用方法:
(1)start():启动线程,使之从新建状态进入就绪队列排队。
(2)run():该线程要完成的使命。
(3)sleep(int millsecond):解决优先级低而无法执行的问题。必须在try—catch语句块中调用。
(4)isAlive():线程调用start()并占有cpu资源后,调用该方法返回true,否则返回false。注意,在true 的情况下,如重新为该线程分配实体则线程只能引用最后分配的实体。先前的就会成为垃圾。
(5)currentThread():类方法,返回当前正在使用cpu资源的线程。
(6)interrupt():正在使用cpu资源的线程让处于休眠状态的线程调用该方法“唤醒”自己,即导致休眠的线程发生InterruptedException异常而结束休眠,重新排队。
线程的同步:
若干个线程都需要使用一个synhcronized修饰的方法。达到的效果就是,当一个方法使用synchronized修饰后,一个线程A使用这个方法的时候,其他的线程也想使用这个方法时就必须等待,知道线程A完成该方法。
线程的挂起、恢复和终止
挂起:让线程暂时让出cpu使用权,停止执行,停止的时间不确定,所以不能使用sleep()来暂停线程。需要让其调用wait(),暂时停止执行。
恢复:其他占有cpu资源的线程调用notifyAll(),使其从中断处继续执行。
终止线程:即使其执行run(),进入死亡状态。