2023年6月20日发(作者:)
JavaSEJava的特点(一)简单易学1、java的风格类似于C++2、java摒弃了C/C++中容易引发程序错误并难以掌握的一些特性,如指针、结构、以及内存管理等3、Java提供了丰富的类库,可以帮助我们很方便的开发java程序4、Java是完全面向对象的语言(二)安全性高1、java是一种强类型的语言,其类型检查比C/C++还要严格。类型检查帮助我们检查出许多开发早期出现的错误2、Java提供了垃圾回收机制,有效的避免了C/C++中最头疼的内存泄漏问题3、Java禁止非法内存访问,在没有授权的情况下是不能访问内存的。所有这些措施,使java程序员不用担心内存的崩溃总结:java去掉C和C++中影响程序健壮性的部分,使程序更安全,例如指针、内存申请和释放(三)跨平台Java作为一种网络语言,其源代码被编译成一种结构中立的中间文件格式。只要有java运行系统的机器都能执行这种中间代码。Java源程序被编译成一种与机器无关的字节码格式,在java虚拟机上运行Java源代码和字节码是与机器无关的,但JVM是与机器有关的。装有不同操作系统的机器上,需要有专门为该操作系统开发的JVM,JVM是与机器有关的(四)多线程的Java语言的一个重要特性就是在语言级支持多线程的程序设计。使得一个程序能够同时执行多个任务运行时注意的问题vaA不能写javaTest,编译时必须写文件名,运行时写的是文件中的类名Java语言的基本元素——标识符标识符:程序员对程序中的各个元素加以命名时使用的命名记号称为标识符(identifier),包括:类名、变量名、常量名、方法名、...Java语言中,标识符是以字母、下划线、美元符($)开始的一个字符序列,后面可以跟字母、下划线、美元符、数字。什么是类把一类事物的静态属性和动态可以执行的操作组合在一起所得的这个概念就是类什么是对象类的一个个体(如果将对象比作汽车,那么类就是汽车的设计图纸)类的定义classPerson{intage;voidshout(){n(“oh,mygod!Iam”+age);}}age是类的属性,也叫类数据成员,也叫字段,也叫域shout是方法,也叫类的成员函数shout方法可以直接访问同一个类中的age变量classA{inti;intj;}classTestMemo{publicstaticvoidmain(String[]args){Aaa=newA();//(A*)malloc(sizaof(A));//newA();在堆中动态分配一块区域,被当做了A对象//aa本身的内存是在栈中分配的//堆中内存的地址付给了aa//aa指向堆中的内存,aa代表了堆中的内存//aa.i代表:aa这个静态指针变量所指向的动态内存中的A对象的i这个成员变量//aa.j代表:aa这个静态指针变量所指向的动态内存中的A对象的j这个成员变量aa.i=10;aa.j=20;}}类的访问控制符类的访问控制符有四种:publicprotect默认【即不加任何修饰符】private在一个类的内部,所有的成员可以相互访问,访问控制符是透明的;访问控制符是针对外部访问而言的在一个类的外部:通过(类对象名.私有成员名)的方式是无法访问该对象中的私有成员的,这样写编译时会出错外部访问包括两种方式:通过类名访问类内部的成员、通过类对象名访问类内部成员函数的重载:同名的函数通过不同的形参做类似的事情,这就叫函数的重载函数重载的要求:函数的形参个数函数的形参顺序函数的形参数据类型这三个至少有一个是不一样的如果两个函数只是函数的返回值不一样,其他都一样,这构不成函数的重载,并且编译时会报错StaticA类的多个对象公用一个static属性static属性i是属于类本身,或者讲:没有对象,我们仍然可以直接通过类名的方式访问该类内部的static属性static属性和方法虽然属于类本身,虽然可以通过类名的方式访问,但是static属性和方法很明显也属于类对象,当然也可以通过类对象名的方式访问只有非private的static成员才可以通过类名的方式访问,static只是表明了该成员具有了可以通过类名访问的潜在特征。但是否可以通过类名访问,还必须满足一个条件:该成员必须是非private静态方法不能访问非静态成员,非静态方法可以访问静态成员classA{privateinti;Privatestaticintcnt=0;PublicA(){++cnt;}PublicA(inti){This.i=i;++cnt;}PublicstaticintgetCnt(){Returncnt;}}PublicclassTestStatic_1{Publicstaticvoidmain(String[]args){(“当前时刻A对象的个数是:”,);Aaa1=newA();(“当前时刻A对象的个数是:”,);Aaa2=newA();(“当前时刻A对象的个数是:”,);}}一个类的属性可以是个类对象ClassA{Publicinti=20;PrivatestaticAaa=newA();PrivateA(){}PublicstaticAgetA(){Returnaa;}}PublicclassTestStatic_2{Publicstaticvoidmain(String[]args){Aaa1=();Aaa2=();aa.1=99;(“%dn”,aa2.i);}}继承什么叫继承:一个新类从已有的类那里获得其已有的属性和方法,这种现象叫类的继承这个新类被称为子类,也叫派生类。已有的那个类叫做父类,也叫做基类继承的好处:代码得到极大的重用;形成一种类的层次体系结构;为多态创造条件继承的实现方式:classSubClassextendsSuperClass//static一定不能省略{}同包继承权限问题1、子类内部可以访问父类非私有的成员,私有成员无法被子类方法访问2、通过子类对象名只能访问从父类继承过来的非私有成员总结:私有不能被继承(私有物理上已经被继承过来,只不过逻辑上程序员不能去访问它,因此继承必须慎重,否则会浪费内存)继承的原则何时选择继承?一个很好的经验:“B是一个A吗?”如果是则让B做A的子类Java只支持单继承,不允许多重继承单继承就是一个类只能有一个父类多继承就是一个类可以有多个父类可以有多层继承,即一个类可以继承某一个类的子类,如类B继承了类A,类C又可以继承类B,那么类C也间接继承了类A子类可以继承父类所有的成员变量和成员方法,但子类永远无法继承父类的构造方法。在子类的构造方法中可使用语句super(参数列表)调用父类的构造方法子类访问父类成员的三种方式:在子类内部访问父类成员;通过子类对象名访问父类成员;通过子类的类名访问父类成员。经验证,子类通过上述三种方式的任何一种都无法访问父类私有成员,因此,我们可以得出结果:私有成员无法被子类继承Super1、每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种构造函数,那么编译的时候就会报错2、如果显示的写出super()语句,则必须保证该语句是第一条语句,否则会出错3、Super()如果不写,则编译器会自动添加,所以此时如果父类没有无参的构造函数就会出错4、既可以显示写super(),前提是父类必须有无参的构造函数也可以显示写super(实参),前提是父类必须有带参的构造函数5、调用父类的构造函数的语句必须借助于super,不能直接写父类的类名6、一个构造函数中不能写多个super(实数列表)语句方法重写什么叫方法重写:指在子类中重新定义父类中已有的方法重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型子类中不允许出现与父类同名同参但不同返回类型的方法,如果出现了,编译时会出错重写方法时,不能使用比父类中被覆盖的方法更严格的访问权限ClassHuman{PrivateStringname;Privateintage;PublicHuman(){}PublicHuman(Stringname,int{=name;=age;}age)PublicvoidsetName(Stringname){=name;}PublicvoidsetAge(intage){=age;}PublicStringgetInfor(){StringstrInf=name+“:”+age;ReturnstrInf;}}ClassStudentextendsHuman{PublicStringschool;PublicStudent(){}PublicStudent(Stringname,int{Supper(name,age);=school;}age,Stringschool)PublicvoidsetSchool(Stringschool){=school}PublicStringgetInfor(){StringstrInf=or+”:”+school;ReturnstrInf;}}PublicclassTestStudent{Publicstaticvoidmain(String[]args){Studentst1=newStudent(“张三”,22,“路家”);(“%sn”,or());}}多态一个父类的引用类型变量它既可以指向父类对象也可以指向子类对象,它可以根据当前时刻指向的不同,自动调用不同对象的方法,这就是多态多态的优点利用多态可以实现:同一段代码做不同事情多态注意事项子类对象可以直接赋给父类引用,但父类对象在任何情况下都不能直接赋给子类引用,因为子类是父类的一种,但父类不是子类的一种。通过父类引用只能访问子类对象从父类继承过来的成员,通过父类应用不能访问子类对象特有的成员父类引用永远不可能直接赋给子类引用,只有在父类引用本身指向的就是一个子类对象时,才可以把父类引用强制转化为子类引用抽象类抽象类的由来:利用抽象类是为了更好的对类加以分类。抽象类通常用来作为一个类族的最顶层的父类,用最底层的类表示现实中的具体事物,用最顶层的类表示该类族所有事物的共性抽象方法在定义java方法时可以只给出方法头,而不给出方法内部实现代码,这样的方法称为抽象方法。凡是没有方法体的方法必须得使用关键字abstract修饰为抽象方法。凡是含有抽象方法的类都必须得声明为抽象类。抽象类用abstract关键字来修饰一个类时,该类叫做抽象类包含抽象方法的类必须声明为抽象类。但是一个抽象类中却可以不包含任何抽象方法,尽管比较少见。抽象类不一定有抽象方法,有抽象方法的一定是抽象类FinalFinal可以修饰:整个类,类中的若干个属性,类中的若干个方法Final修饰整个类,表示该类不能被继承,如果认为一个类已经很完美不需要定义子类来继承它时,可以使用它。Final修饰类中的若干属性表示该属性必须被赋值并且只能被赋一次值(注意默认值不算真正的赋值)初始化方式有两种(只能选择其中的一种):在定义成员变量的同时初始化;在类中所有的构造函数中初始化注意:一个类的所有普通方法内部都不可以修改final修饰过的成员变量的值接口接口的定义:就是抽象方法和常量的集合。从本质上讲,接口是一种特殊的抽象类。接口的格式:【public】interfaceinterfaceName【extendsSuperInterfaceList】{......//常量定义和方法定义}1、接口中定义的属性必须是publicstaticfinal的,而接口中定义的方法则必须是publicabstract的,因此这些修饰符可以部分或全部省略2、接口中定义的属性的值在实现类中不能被修改3、一个类智能实现某个接口,不能继承某个接口。但接口可以继承接口4、接口不但可以继承接口,而且可以继承多个接口,即接口可以允许多继承5、如果一个类只实现了一个接口的部分方法,则该类必须得声明为抽象类6、一个类可以在继承一个父类的同时实现一个或多个接口,但extends关键字必须得在implements之前7、不可以new接口对象,但可以定义一个接口引用类型的变量并将其指向实现接口的对象,达到多态的目的接口的作用1、通过接口可以实现不相关类的相同行为。如:java规定所有可以完成自我复制功能的类都必须得实现ble接口,但该接口却是空的,该接口中没有任何内容,目的只是为了起个标志作用2、接口提供了不同对象进行协作的平台,如:事件处理3、接口可以实现多继承,从一定程度上弥补了类只能单继承的缺陷4、接口是我们了解一个类功能的重要途径。如:java整个容器框架就是以接口的方式建立起来的,实现不同接口的类完成的是不同的功能,接口是我们了解一个类功能的重要途径接口与抽象类的区别1、接口中的方法不允许有方法体,但抽象类却允许2、Java类不允许多继承,接口却允许多继承。包1、Package语句必须得是第一条语句2、表示:把该文件中所有的类放入这个包中,并且该文件中所有的类真正名字将是包名和类名的组合。如:类TestPackage的名字将变成ckage,而不再是TestPackage3、编译时建议使用,尽量不要使用因为后者要自己手动建立包目录4、如果不再当前路径下运行程序,则必须保证class文件的最上层目录的父目录位于classpath下(ckage解析:先检测当前目录下是否有zhangsan/lisi这个包-包即文件夹,如果有,再检测该包下是否有ckage这个类,如果没有,编译器将再去classpath设置的路径中一次查找。如果都查找失败,则运行时出错)同包不同类的相互访问因为类A和类B默认是在同一个无名的包中所以彼此可以相互访问,只要是非私有成员都可以被同包的另一个类访问不同包类的相互访问:建议一起编译使用不同包中类的方式:1、使用一个类的全名,如:=.A();2、使用import语句导入一个包中所有的类,如:.*;3、使用import语句导入一个包中特定的类,如:.A;注意:导入父包的类并不会自动导入子包的类。如:importzhangsan.*;只会导入zhangsan这个包下的所有类,并不会导入zhangsan子包lisi这个包中的类不同包访问修饰符问题1、在同一个包中只有私有的不能被另一个类访问,也只有私有的不能被继承2、在不同包没有任何关系的两个类,只有public类的public成员才可以被另一个包中的类访问3、在不同包中有继承关系的两个类,只有public类的public成员和public类的protected成员可以被另一个包中的子类在内部使用,但是在子类的外部,通过子类对象名只能访问父类的public成员Jar使用举例格式:jar-cvf要生成的包名.Jar*举例:1、*功能:把当前路径下所有的文件即文件夹下所有的内容打包成2、功能:在DOS下显示这个包解压后的文件的内容3、jar-xfd:功能:把d:这个文件中的内容解压到当前目录下异常处理什么是异常:异常(Exception)是程序运行过程中发生的事件,该事件可以中断程序指令的正常执行流程异常的处理机制:1、当Java程序运行时出现问题时,系统会自动检测到该错误,并立即生成一个与该错误对应的异常对象2、然后把该异常对象提交给Java虚拟机3、Java虚拟机会自动寻找相应的处理代码来处理这个异常,如果没有找到,则由Java虚拟机做一些简单的处理后,程序被强行终止4、程序员可以自己编写代码来捕捉可能出现的异常,并编写代码来处理相应的异常为什么要使用异常处理r;ismatchException;PublicclassTestExcep_3{Publicstaticvoidmain(String[]args){Inti;Scannersc=newScanner();Try{I=t();(“i=%dn”,i);}Catch(InputMismatchExceptione){//tackTrace();该方法在调试时使用,用来显示异常信息(“输入数据不合法,程序被终止!n”)}}}异常的分类凡是继承自Exception但又不是RuntimeException子类的异常我们都必须得捕捉并进行处理异常处理步骤Try{可能出现异常的代码块}Catch(ExceptionName1e){当产生ExceptionName1异常时的处理措施}Catch(ExceptionName2e){当产生ExceptionName2异常时的处理措施}........Finally{无论是否捕捉到异常都必须处理的代码}Finally的作用1、无论try所指定的程序块中是否抛出异常,也无论catch语句的异常类型是否与所抛出的异常的类型一致,finally中的代码一定得到执行2、Finally语句为异常处理提供一个统一的出口,使得在控制流程转到程序的其他部分以前,能够对程序的状态作统一的管理3、通常在finally语句中可以进行资源的清除工作,如关闭打开的文件,删除临时文件等ThrowThrow用来抛出异常格式:thrownew异常名(参数);假设f方法抛出了A异常,则f方法有两种方式来处理A异常:1、throwsA,谁调用f方法,谁处理A异常,f方法本身不处理A异常2、Try{...}catch(){......},f方法本身自己来处理A异常注:要抛出的异常必须得是Throwable的子类ThrowsVoidf()throwsA{......}ThrowsA表示调用f方法时f方法可能会抛出A类异常,建议调用f方法时最好对f方法可能抛出的A类异常进行捕捉ThrowsA不表示f方法一定会抛出A类异常。ThrowsA不表示调用f方法时,必须得对A异常进行捕捉。假设A是RuntimeException子类异常,由于RuntimeException的子类异常可以处理也可以不处理,所以编译器允许调用f方法时,对f方法抛出的RuntimeException子类异常不进行处理强烈建议:1、对throws出的所有异常进行处理2、如果一个方法内部已经对A异常进行了处理,就不要再throwsA注意问题:1、所有的catch只能有一个被执行。有可能所有的catch都没有执行。2、先catch子类异常再catch父类异常3、Catch与catch之间是不能有其他代码的4、重写方法抛出异常的范围不能大于被重写方法抛出的异常范围异常的优缺点:1、强制程序员考虑程序的安全性与健壮性2、增强了程序员对程序的可控性3、有利于代码的调试4、把错误处理代码从常规代码中分离出来注意:1、异常并不一定能够使程序的逻辑更清晰(因为有时我们必须得编写代码捕捉异常,所以可能会导致程序的逻辑非常混乱)2、异常并不能解决所有的问题toString1、所有的类都默认自动继承了Object类2、Object类中的toString方法返回的是类的名字和该类对象哈希吗组成的一个字符串3、n(类对象名);实际输出的是该对象的toString()方法所返回的字符串4、为了实际需要,建议子类重写从父类Object继承的toString方法Object类的equals方法1、所有类都从Object类中继承了equals方法2、Object类中equals方法源代码如下:Publicbooleanequals(Objectobj){Returnthis==obj;}3、Object中的equals方法是直接判断this和obj本身的值是否相等,即用来判断调用equals的对象和形参obj所引用的对象是否是同一对象,所谓同一对象就是指是内存中同一块存储单元,如果this和obj指向的是同一块内存对象,则返回true,如果this和obj指向的不是同一块内存,则返回false。注意:即便是内容完全相等的两块不同的内存对象,也会返回false4、如果是同一块内存,则Object中的equals方法返回true,如果是不同的内存,则返回false何时需要重写equals方法1、用一个类构造出来的不同内存的两个对象,如果内存中的值相等,我们一般情况下也应该认为这两个对象相等,很明显Object中的equals()无法完成这样的重任,Object中的equals()方法只有在两个对象是同一块内存时,才返回true,这时我们就有必要重写父类Object中的equals方法2、如果希望不同内存但相同内容的两个对象equals时返回true,则我们需要重写父类的equals方法String类1、类对象表示不可修改的Unicode编码字符串2、在java中双引号括起来的字符串也被当做String对象如:n(“abc”.length());//输出n(“abc”.equals(“abc”));//输出trueString类的equals方法1、String类已经重写了Object中的equals方法如:假设str1和str2都是String对象。(str2):是用来比较str1变量本身所占内存的值所指向的对象和str2变量本身所占内存的值所指向的对象的内容是否相等,如果相等则返回true,否则返回false2、String类的equals方法是用来判断两个对象的内容是否相等的,Object类的equals方法是用来判断两个对象是否是同一个对象StringBuffer类的由来1、String类对象一旦创建就不可更改2、如果经常对字符串内容进行修改,则使用StringBuffer3、如果经常对字符串内容进行修改而使用String的话,就会导致既耗空间又耗时间4、StringBuffer对象的内容是可以改变的5、因此String类中没有修改字符串的方法,但是StringBuffer类中却有大量修改字符串的方法StringBuffer类的构造函数PublicStringBuffer()创建一个空的没有任何字符的StringBuffer对象PublicStringBuffer(intcapacity)创建一个不带字符,但具有指定初始容量的字符串缓冲区PublicStringBuffer(Stringstr)创建一个StringBuffer对象,包含与str对象相同的字符序列什么叫程序所谓“程序”,是一个严格有序的指令集合。程序规定了完成某一任务时,计算机所需做的各种操作,以及这些操作的执行顺序。单道程序设计环境中程序特点单道程序设计环境是指:计算机中除了操作系统之外,只存在一个用户程序,即用户程序独享整个计算机资源。单道程序有如下特点:1、资源的独占性2、执行的顺序性3、结果的再现性多道程序设计环境中程序特点多道程序设计是指:计算机中除了操作系统之外,存在多个用户程序,这些程序同时运行。多道程序设计有如下特点:1、间断性:由于资源共享和合作,并发程序间相互制约,造成合作执行间断2、失去封闭性:程序执行受外界影响3、不可再现性:重复执行时,可能得到不同结果进程的由来一方面为了保持程序“是一个在时间上严格有序的指令集合,是静态的保存在存储介质上”这个概念的原有含义,另一方面为了刻画多个程序共同运行时呈现出的这些特征,在操作系统中,以“程序”为基础,又引入了“进程”这一新概念。按照大多数教材的说法,为了使程序能并发执行,且为了对并发执行的程序加以描述,所以人们引入了进程。什么叫进程进程是程序在某个数据集上的执行。进程是一个动态的实体,它有自己的生命周期。它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而被撤销。线程的定义线程是一个程序里的不同执行路径以前所编写的程序,每个程序都只有一个入口,一个出口以及一个顺序执行的序列,在程序执行过程中的任何指定时刻,都只有一个单独的执行点。事实上,在单个程序内部是可以在同一时刻进行多种运算的,这就是所谓的多线程。多线程的优势1、多线程编程简单,效率高(能直接共享数据和资源,多进程不能)2、适合于开发服务程序(如Web服务,聊天服务等)创建一个线程的第一种方法1、创建一个继承Thread的类(假定类名为A),并重写Thread中的run方法2、构造一个A类对象,假定对象名为aa3、调用aa的start方法【start方法是从Thread继承过来的】注意的问题1、Thread中start()方法的功能就是创建一个新的线程,并自动调用该线程的run()方法,直接调用run()方法是不会创建一个新的线程的2、执行一个线程实际就是执行该线程run方法中的代码3、执行完();后并不表示aa所对应的线程就一定会立即得到执行,();执行完后只是表示aa线程具有了可以立即被CPU执行的资格,但由于想抢占CPU执行的线程很多,CPU并不一定会立即去执行aa所对应的线程4、一个Thread对象能且只能代表一个线程5、一个Tread对象不能调用两次start()方法,否则会抛出lThreadStateException异常创建一个新线程的第二种方法1、定义一个实现了Runnable接口的累,假定为A2、创建A类对象aa,代码如下:Aaa=newA();3、利用aa构造一个Thread对象tt,代码如下:Threadtt=newThread(aa);4、调用tt中的start方法,代码如下:();Thread的常用方法PublicfinalvoidsetName(Stringname)设置当前线程的名字PublicstaticThreadcurrentThread()返回对当前正在执行的线程对象的引用PublicfinalStringgetName()返回当前线程的名字线程优先级线程的优先级用数字来表示,范围从1到10。主线程的缺省优先级是5,子线程的优先级默认与其父线程相同线程的休眠1、线程休眠——暂停执行当前运行中的线程,使之进入阻塞状态,待通过指定的“延迟时间”后再醒来并转入到就绪状态2、Thread类提供的相关方法Publicstaticvoidsleep(longmillis)Publicstaticvoidsleep(longmillis,intnanos)3、由于是静态方法,可以由Thread直接调用4、Sleep()方法会抛出InterruptedException异常,我们必须得对其进行捕捉。(无论是继承Thread类的run方法还是实现Runnable接口的run方法,都不能抛出任何异常——原因:重写方法抛出异常的范围不能大于被重写方法抛出的异常范围)线程的让步1、让出CPU,给其他程序执行的机会2、让运行中的线程主动放弃当前获得的CPU处理机会,但不是使该线程阻塞,而是使之转入就绪状态3、Publicstaticvoidyield()线程的串行化1、在多线程程序中,如果在一个线程运行的过程中要用到另一个线程的运行结果,则可进行线程的串行化处理2、Publicfinalvoidjoin()throwsInterruptedException买票程序ClassAimplementsRunnable{Publicinttickets=100;Stringstr=newString(“哈哈”);Public{voidrun()While(true){Synchronized(str){If(tickets>0){(“%s线程正在卖出第%d张票n”,tThread().getName(),tickets);--tickets;}Else{Break;}}}}}Public{classTestTicketsPublicstaticvoidmain(String[]args){Aaa=newA();Threadt1=newThread(aa);();Threadt2=newThread(aa);();}}Synchronized关键字1、Synchronized可以用来修饰:一个方法;一个方法内部的某个代码块2、格式:Synchronized(类对象名aa){同步代码块}3、功能:synchronized(类对象名aa)的含义是:判断aa是否已经被其他线程霸占,如果发现已经被其他线程霸占,则当前线程陷入等待中,如果发现aa没有被其他线程霸占,则当前线程霸占住aa对象,并执行同步代码块内容,在当前线程执行同步代码块时,其他线程将无法再执行同步代码块内容(应为当前线程已经霸占了aa对象),当前线程执行完同步代码块内容后,会自动释放对aa对象的霸占,此时当前线程和其他线程会相互竞争对aa的霸占,最终CPU会选择其中的某一个线程执行4、最终导致的结果是:一个线程正在操作某资源的时候,将不允许其他线程操作该资源,即一次只允许一个线程处理该资源生产消费ClassSynStack{Privatechar[]data=newchar[6];Privateintcnt=0;//表示数组有效元素的个数Publicsynchronizedvoidpush(charch){While(cnt==){Try{();//7行}Catch(Exceptione){}}();//10行Data[cnt]=ch;++cnt;(“生产线程正在生产第%d个产品,该产品是:%cn”,cnt,ch);}Publicsynchronizedcharpop(){While(cnt==0){Try{();}Catch(Exceptione){}}();//20行Ch=data[cnt-1];(“消费线程正在生产第%d个产品,该产品是:%cn”,cnt,ch);--cnt;Returnch];//23行}}ClassProducerimplementsRunnable{PrivateSynStackss=null;PublicProducer(SynStackss){=ss;}Publicvoidrun(){Charch;Try{(2000);}Catch(Exceptione){}For(inti=0;i<20;++i){Try{(2000);}Catch(Exceptione){}Ch=(char)(‘a’+i);();}}}ClassConsumerimplementsRunnable{PrivateSynStackss=null;PublicConsumer(SynStackss){=ss;}Publicvoidrun(){For(inti=0;i<20;++i){Try{(2000);}Catch(Exceptione){}();}}}PublicclassTestPC{Publicstaticvoidmain(String[]args){SynStackss=newSynStack();Producerp=newProducer(ss);Consumerc=newConsumer(ss);Threadt1=newThread(p);();Threadt2=newThread(c);();}}如上述程序,假设现在有两个线程P(生产)和C(消费)。P生产已满,执行7行代码陷入阻塞状态,同时释放P线程对this的锁定,这时候C线程会得到this对象的标志位开始运行。另外C线程执行完20行代码后,程序并不会立即转到P线程开始执行,因为执行notify,只是叫醒P,让P从因为waitthis对象而陷入阻塞的状态进入就绪状态。记住:一个线程notify该线程并不会释放对this的锁定,只有C执行完23行的代码后,C才会释放对this的代码锁定,这时候C和P会同时争夺this的锁定,具体执行那个由系统调度器决定。()’功能:将执行()的当前线程转入阻塞状态,让出CPU的控制权,释放对aa的锁定();功能:不是叫醒正在执行();的当前线程,而是叫醒一个现在正在waitthis对象的其他线程。如果有多个线程正在waitthis对象,通常是叫醒最先waitthis对象的线程。但是具体叫醒哪个是由系统调度器控制,程序员无法控制。例如:假设执行();的当前线程为T1,如果当前时刻有其他线程因为执行了()而陷入了阻塞状态,则叫醒其中的一个。所谓叫醒某个线程就是令该线程从因为wait而陷入阻塞的状态转入就绪状态。例如:假设现在有T1、T2、T3、T4四个线程。我们在T4线程中执行了()语句,则即便此时T1、T2、T3没有一个线程因为waitaa对象而陷入阻塞状态,T4线程中执行方法时也不会有任何错误。执行方法时如果一个线程都没有叫醒,这是可以的。All()叫醒其他所有的因为执行了()而陷入阻塞状态的线程GUI组件组件(Component)是图形用户界面的基本组成元素,凡是能够以图形化方式显示在屏幕上并能够与用户进行交互的对象均为组件,如菜单、按钮、标签、文本框、滚动条等。组件分类1、mponent2、说明:抽象类ent是出菜单相关组件之外所有javaAWT组件类的根父类,该类规定了GUI组件的基本特性,如尺寸、位置和颜色效果等,并实现了作为一个GUI不见所应具备的基本功能。容器1、组件通常不能独立地显示出来,必须将组件放在一定的容器中才可以显示出来。2、有一类特殊的组件是专门用来包含其他组件的,这类组件叫做容器,ner是所有容器的父类,ner继承自ent3、容器类对象本身也是一个组件,具有组件的所有性质,但反过来组件却不一定是容器布局管理器1、容器对其中所包含组件的排列方式,包括组件的位置和大小设定,被称为容器的布局(Layout)2、为了使图形用户界面具有良好的平台无关性,Java语言提供了布局管理器来管理容器的布局,而不建议直接设置组件在容器中的位置和尺寸3、每个容器都有一个默认的布局管理器,当容器需要对某个组件进行定位或判断其大小尺寸时,就会自动调用其对应的布局管理器布局管理器总结1、Frame是一个顶级窗口,Frame的缺省布局管理器为BorderLayout2、Panel无法单独显示,必须添加到某个容器中。Panel的缺省布局管理器为FlowLayout3、当把Panel作为一个组件添加到某个容器中后,该Panel仍然可以有自己的布局管理器4、使用布局管理器时,布局管理器负责各个组件的大小和位置,因此用户无法在这种情况下设置组件大小和位置属性,如果试图使用Java语言提供的setLocation(),setSize(),setBounds()等方法,则都会被布局管理器覆盖5、如果用户确实需要亲自设置组件大小或位置,则应取消该容器的布局管理器,方法为:setLayout(null);事件处理事件(Event)用户对组件的一个操作,称之为一个事件事件源(EventSource)能够产生事件的GUI组件对象,如按钮、文本框等事件处理方法(EventHandler)能够接收、解析和处理事件类对象,实现与用户交互功能的方法事件监听器(EventListener)可以处理事件的一个类事件处理步骤假设事件为XXXX1、向事件源注册某种事件的事件监听器对象addXXXXListener(...);2、设计好可以处理这种事件的事件监听器Class类名implementsXXXXListener{重写XXXXListener接口中的方法}说明:要想设计出能够处理XXXX事件的监听器,只需要编写出实现了XXXXListener接口的类就OK了,因为XXXXListener接口中已经定义了可以处理XXXX事件的方法。事件处理相关概念1、默认情况下事件源不会自动产生任何事件,程序员需要做两件事:告诉事件源可以自动产生哪类事件,即:向事件源注册某种事件的时间监听器对象。设计好可以处理这种时间的时间监听器。2、一旦完成了这两步操作,当用户对事件源进行操作时,事件源就会自动产生事件,事件源就会自动把产生的事件封装成一个事件对象,事件源就会自动把封装好的事件对象传递给事件监听器。3、事件监听器收到事件源发送过来的事件时,事件监听器就会自动调用相应的事件处理方法来对该事件进行相应的处理。事件有哪些包中含有所有的事件,常用的事件有:1、ActionEvent:激活组件时发生的事件2、KeyEvent:操作键盘时发生3、MouseEvent:操作鼠标时发生4、WindowEvent:操作窗口时发生的事件,如最大化或最小化某一窗口(一个事件源可以自动产生哪些事件,第三方软件会自动显示,不需要人为记忆。)十个按钮的设计.*;PublicclassTestGUI{Publicstaticvoidmain(String[]args){Framef=newFrame();e(300,300);out(newGridLayout(2,1));Panelp1=newPanel();out(newBorderLayout());Panelp1-1=newPanel();out(newGridLayout(2,1));Buttonbn1=newButton(“BUTTON1”);Buttonbn2=newButton(“BUTTON2”);Buttonbn3=newButton(“BUTTON3”);Buttonbn4=newButton(“BUTTON4”);(bn1,);(bn3);(bn4);(p1-1,);(bn2,);Panelp2=newPanel();out(newBorderLayout());Panelp2-2=newPanel();out(newGridLayout(2,2));Buttonbn5=newButton(“BUTTON5”);Buttonbn6=newButton(“BUTTON6”);Buttonbn7=newButton(“BUTTON7”);Buttonbn8=newButton(“BUTTON8”);Buttonbn9=newButton(“BUTTON9”);Buttonbn10=newButton(“BUTTON10”);(bn5,);(bn6,);(bn7);(bn8);(bn9);(bn10);(p2-2,);(p1);(p2);();ible(true);}}三个文本框相加事例.*;.*;PublicclassTestTextField{PublicstaticTextFieldtf1,tf2,tf3;Publicstaticvoidmain(String[]args){tf1=newTextField(30);tf2=newTextField(30);tf3=newTextField(30);Buttonbn=newButton(“=”);LabelLb=newLabel(“+”);Framef=newFrame(“文本框相加事例”)out(newFlowLayout());(tf1);(Lb);(tf2);(bn);(tf3);ionListener(newMyMonitor());();ible(true);}}ClassMyMonitorimplementsActionListener{@OverridePublicvoidactionPerformed(ActionEvente){Stringstr1=t();Stringstr2=t();Intnum1=nt(str1);Intnum2=nt(str2);Intnum3=num1+num2;Integerit=newInteger(num3);Stringstr3=ng();t(str3);}}.*;.*;PublicclassTestTextField{PublicstaticTextFieldtf1,tf2,tf3;Publicstaticvoidmain(String[]{TFtf=newTF();();}}ClassTF{PublicTextFieldtf1,tf2,tf3;Publicvoidlaunch(){tf1=newTextField(30);tf2=newTextField(30);tf3=newTextField(30);Buttonbn=newButton(“=”);LabelLb=newLabel(“+”);Framef=newFrame(“文本框相加事例”)out(newFlowLayout());(tf1);(Lb);(tf2);(bn);(tf3);ionListener(newMyMonitor(this));();ible(true);}}ClassMyMonitorimplementsActionListener{args)PrivateTFtf;PublicMyMonitor(TF{=tf;}tf)@OverridePublicvoidactionPerformed(ActionEvent{Stringstr1=t();Stringstr2=t();Intnum1=nt(str1);Intnum2=nt(str2);Intnum3=num1+num2;Integerit=newInteger(num3);Stringstr3=ng();t(str3);}}e)可运行jar包生成步骤1、新建一个记事本文件,假设为,文件内容为:Main-Class:可运行类的名字附注:记得敲回车2、dos下命令:记住:只有GUI程序生成的class文件才可以作为mainclass流流的定义:流就是程序和设备之间嫁接起来的一根用于数据传输的管道,这个管道上有很多按钮,不同的按钮可以实现不同的功能。这根带按钮的用于数据传输的管道就是流。流的分类标准:按数据流的方向不同可以分为输入流和输出流按处理数据单位不同可以分为字节流和字符流按照功能不同可以分为节点刘和处理流流与类的关系:如果一个类是用作设备和程序之间的数据传输,则这个类有一个新的名字叫流。流一定是类,但类不一定是流在Java中一个字符占两个字节InputStream流中常用的方法publicintread();throwIOException读取一个字节并以整数形式返回如果读取到输入流的末尾则返回-1publicintread(byte[]b)throwIOException从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中。以整数形式返回实际读取的字节数如果b的长度为0,则不读取任何字节并返回0;如果因为流位于文件末尾而没有可用的字节,则返回值-1publicintread(byte[]b,intoff,intlen)throwIOException从输入流中最多读取len个字节的数据并存入byte数组中b表示读取的数据要存入的数组的名字off表示第一个读出的数据要存入的位置,是下标len表示最多能读取的字节数尝试读取len个字节,但读取的字节也可能小于该值。以整数形式返回实际读取的字节数。如果读到了文件的末尾,则返回-1voidclose()throwIOException关闭此输入流并释放与该流关联的所有系统资源longskip(longn)throwIOException跳过和丢弃此输入流中数据的n个字节文件流文件流包括FileInputStreamFileOutputStream字节流,FileReaderFileWriter字符流InputStream是用来读取字节的,是个抽象类,我们通常使用的是该类的子类FileInputStream是InputStream的子类,利用FileInputStream可以将一个文件的内容按字节为单位读取出来FileInputStream有一个常用的构造函数publicFileInputStream(StringfileName)throwsFileNotFoundException利用该构造函数可以实现将输入流连接到某个文件的功能必须对本构造函数抛出的异常进行捕捉如果用字符串来表示操作系统的文件路径时,我们可以使用和/两种方式来作为文件夹的路径分隔符字节流与字符流的区别FileInputStream和FileOutputStream可以完成所有格式文件的复制FileReader和FileWriter只可以完成文本文件的复制,却无法完成视频格式文件的复制因为字节是不需要解码和编码的,将字节转化为字符才存在解码和编码的问题字节流可以从所有格式的设备中读写数据,但字符流只能从文本格式的设备中读写数据.*;publicclassTestFileReaderWriterCopy{publicstaticvoidmain(String[]args)throwsException{FileReaderfr=newFileReader(“D:”);FileWriterfw=newFileWriter(“E:”);intch;ch=();while(-1!=ch){(ch);ch=();}();();();}}缓冲流缓冲流就是带有缓冲区的输入输出流缓冲流可以显著的减少我们对IO访问的次数,保护我们的硬盘缓冲流本身就是处理流(处理流也叫包裹流),缓冲流必须得依附于节点流(节点流也叫原始流)处理流是包裹在原始节点流上的流,相当于包裹在管道上的管道.*;publicclassTestBufferedInputSteamCopy{publicstaticvoidmain(String[]args)throwsException{BufferedInputSteambis=newBufferedInputSteam(newFileReader(“D:”));BufferedInputSteambos=newBufferedInputSteam(newFileWriter(“E:”));byte[]buf=newbyte[1024];intlen;len=(buf);while(-1!=len){(buf,0,len);len=(buf);}();();();}}.*;publicclassTestBufferedReaderCopy{publicstaticvoidmain(String[]args)throwsException{BufferedReaderbr=newBufferedIReader(newFileReader(“D:”));BufferedWriterbw=newBufferedWriter(newFileWriter(“E:”));Stringstr=null;while(null!=(str=ne()))//ne()读一行,不包含换行符{(str);e();//写入一个换行符这行不能省}();();();}}数据流编程实现将long类型数据写入byte数组,然后再从byte数组中把该数据读出来附注:这是Socket编程中经常要完成的功能因为网络编程中经常要把数值型数据存入byte数组中,然后把byte数组打包成数据包(即DatagramPacket),再把数据包经过网络传输到目的机,目的机再从byte数组中把原数值型数据还原回来.*;publicclassTestData{publicstaticvoidmain(String[]args)throwsException{ByteArrayOutputStreambaos=newByteArrayOutputStream();DataOutputStreamdos=newDataOutputStream(baos);longm=1234567;ong(m);();byte[]buf2=Array();ByteArrayInputStreambais=newByteArrayInputStream(buf2);DataInputStreamdis=newDataInputStream(bais);longn;n=ng();n(“n=”+n);}}转换流OutputStreanmWriter流是把OutputStream流转化成Writer流的流InputStreamReader是把InputStream转化成ReaderOutputStreamWriter和InputStreamReader都是包裹流例子:如何将键盘输入的字符组成字符串直接赋给String对象.*;publicclassTestString{Publicstaticvoidmain(String[]args){Stringstr=null;try{BufferedReaderbr=newBufferedReader(newInputStreamReader());str=ne();n(“str=”+str);}catch(Exceptione){}}}str=ne();如果直接输入回车的话1、ne()会丢弃回车符,而不是返回回车符,即ne()遇到回车符时终止读取,并且会把读取到的回车符自动丢弃掉2、ne()返回的是””而不是null,””表示空字符串,null表示空指针,空指针就是空地址,空地址就是不指向任何存储单元的意思Print流Print流只有输出,没有输入分类:PrintWriter输出字符,PrintStream输出字节tackTrace();默认是把错误信息输出到所关联的设备中对象的序列化所谓序列化是指:把一个Object对象直接转化为字节流,然后把这个字节流直接写入本地硬盘或网络中。如果要想把某个对象序列化,则必须得实现Serializable接口。Serializable接口中并没有任何方法,这种类型的接口被称为标记接口,如果一个类实现了Serializable接口,潜在含义就是告诉编译器这个类是允许被序列化的,如果程序中存在序列该对象的代码,编译器就会自动进行相应的处理以完成该对象的序列化,如果该对象没有实现Serializable接口,程序中却存在该对象被序列化的代码,编译器编译时就会报错。在Java中transient修饰的成员变量在对象序列化时不被序列化
2023年6月20日发(作者:)
JavaSEJava的特点(一)简单易学1、java的风格类似于C++2、java摒弃了C/C++中容易引发程序错误并难以掌握的一些特性,如指针、结构、以及内存管理等3、Java提供了丰富的类库,可以帮助我们很方便的开发java程序4、Java是完全面向对象的语言(二)安全性高1、java是一种强类型的语言,其类型检查比C/C++还要严格。类型检查帮助我们检查出许多开发早期出现的错误2、Java提供了垃圾回收机制,有效的避免了C/C++中最头疼的内存泄漏问题3、Java禁止非法内存访问,在没有授权的情况下是不能访问内存的。所有这些措施,使java程序员不用担心内存的崩溃总结:java去掉C和C++中影响程序健壮性的部分,使程序更安全,例如指针、内存申请和释放(三)跨平台Java作为一种网络语言,其源代码被编译成一种结构中立的中间文件格式。只要有java运行系统的机器都能执行这种中间代码。Java源程序被编译成一种与机器无关的字节码格式,在java虚拟机上运行Java源代码和字节码是与机器无关的,但JVM是与机器有关的。装有不同操作系统的机器上,需要有专门为该操作系统开发的JVM,JVM是与机器有关的(四)多线程的Java语言的一个重要特性就是在语言级支持多线程的程序设计。使得一个程序能够同时执行多个任务运行时注意的问题vaA不能写javaTest,编译时必须写文件名,运行时写的是文件中的类名Java语言的基本元素——标识符标识符:程序员对程序中的各个元素加以命名时使用的命名记号称为标识符(identifier),包括:类名、变量名、常量名、方法名、...Java语言中,标识符是以字母、下划线、美元符($)开始的一个字符序列,后面可以跟字母、下划线、美元符、数字。什么是类把一类事物的静态属性和动态可以执行的操作组合在一起所得的这个概念就是类什么是对象类的一个个体(如果将对象比作汽车,那么类就是汽车的设计图纸)类的定义classPerson{intage;voidshout(){n(“oh,mygod!Iam”+age);}}age是类的属性,也叫类数据成员,也叫字段,也叫域shout是方法,也叫类的成员函数shout方法可以直接访问同一个类中的age变量classA{inti;intj;}classTestMemo{publicstaticvoidmain(String[]args){Aaa=newA();//(A*)malloc(sizaof(A));//newA();在堆中动态分配一块区域,被当做了A对象//aa本身的内存是在栈中分配的//堆中内存的地址付给了aa//aa指向堆中的内存,aa代表了堆中的内存//aa.i代表:aa这个静态指针变量所指向的动态内存中的A对象的i这个成员变量//aa.j代表:aa这个静态指针变量所指向的动态内存中的A对象的j这个成员变量aa.i=10;aa.j=20;}}类的访问控制符类的访问控制符有四种:publicprotect默认【即不加任何修饰符】private在一个类的内部,所有的成员可以相互访问,访问控制符是透明的;访问控制符是针对外部访问而言的在一个类的外部:通过(类对象名.私有成员名)的方式是无法访问该对象中的私有成员的,这样写编译时会出错外部访问包括两种方式:通过类名访问类内部的成员、通过类对象名访问类内部成员函数的重载:同名的函数通过不同的形参做类似的事情,这就叫函数的重载函数重载的要求:函数的形参个数函数的形参顺序函数的形参数据类型这三个至少有一个是不一样的如果两个函数只是函数的返回值不一样,其他都一样,这构不成函数的重载,并且编译时会报错StaticA类的多个对象公用一个static属性static属性i是属于类本身,或者讲:没有对象,我们仍然可以直接通过类名的方式访问该类内部的static属性static属性和方法虽然属于类本身,虽然可以通过类名的方式访问,但是static属性和方法很明显也属于类对象,当然也可以通过类对象名的方式访问只有非private的static成员才可以通过类名的方式访问,static只是表明了该成员具有了可以通过类名访问的潜在特征。但是否可以通过类名访问,还必须满足一个条件:该成员必须是非private静态方法不能访问非静态成员,非静态方法可以访问静态成员classA{privateinti;Privatestaticintcnt=0;PublicA(){++cnt;}PublicA(inti){This.i=i;++cnt;}PublicstaticintgetCnt(){Returncnt;}}PublicclassTestStatic_1{Publicstaticvoidmain(String[]args){(“当前时刻A对象的个数是:”,);Aaa1=newA();(“当前时刻A对象的个数是:”,);Aaa2=newA();(“当前时刻A对象的个数是:”,);}}一个类的属性可以是个类对象ClassA{Publicinti=20;PrivatestaticAaa=newA();PrivateA(){}PublicstaticAgetA(){Returnaa;}}PublicclassTestStatic_2{Publicstaticvoidmain(String[]args){Aaa1=();Aaa2=();aa.1=99;(“%dn”,aa2.i);}}继承什么叫继承:一个新类从已有的类那里获得其已有的属性和方法,这种现象叫类的继承这个新类被称为子类,也叫派生类。已有的那个类叫做父类,也叫做基类继承的好处:代码得到极大的重用;形成一种类的层次体系结构;为多态创造条件继承的实现方式:classSubClassextendsSuperClass//static一定不能省略{}同包继承权限问题1、子类内部可以访问父类非私有的成员,私有成员无法被子类方法访问2、通过子类对象名只能访问从父类继承过来的非私有成员总结:私有不能被继承(私有物理上已经被继承过来,只不过逻辑上程序员不能去访问它,因此继承必须慎重,否则会浪费内存)继承的原则何时选择继承?一个很好的经验:“B是一个A吗?”如果是则让B做A的子类Java只支持单继承,不允许多重继承单继承就是一个类只能有一个父类多继承就是一个类可以有多个父类可以有多层继承,即一个类可以继承某一个类的子类,如类B继承了类A,类C又可以继承类B,那么类C也间接继承了类A子类可以继承父类所有的成员变量和成员方法,但子类永远无法继承父类的构造方法。在子类的构造方法中可使用语句super(参数列表)调用父类的构造方法子类访问父类成员的三种方式:在子类内部访问父类成员;通过子类对象名访问父类成员;通过子类的类名访问父类成员。经验证,子类通过上述三种方式的任何一种都无法访问父类私有成员,因此,我们可以得出结果:私有成员无法被子类继承Super1、每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种构造函数,那么编译的时候就会报错2、如果显示的写出super()语句,则必须保证该语句是第一条语句,否则会出错3、Super()如果不写,则编译器会自动添加,所以此时如果父类没有无参的构造函数就会出错4、既可以显示写super(),前提是父类必须有无参的构造函数也可以显示写super(实参),前提是父类必须有带参的构造函数5、调用父类的构造函数的语句必须借助于super,不能直接写父类的类名6、一个构造函数中不能写多个super(实数列表)语句方法重写什么叫方法重写:指在子类中重新定义父类中已有的方法重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型子类中不允许出现与父类同名同参但不同返回类型的方法,如果出现了,编译时会出错重写方法时,不能使用比父类中被覆盖的方法更严格的访问权限ClassHuman{PrivateStringname;Privateintage;PublicHuman(){}PublicHuman(Stringname,int{=name;=age;}age)PublicvoidsetName(Stringname){=name;}PublicvoidsetAge(intage){=age;}PublicStringgetInfor(){StringstrInf=name+“:”+age;ReturnstrInf;}}ClassStudentextendsHuman{PublicStringschool;PublicStudent(){}PublicStudent(Stringname,int{Supper(name,age);=school;}age,Stringschool)PublicvoidsetSchool(Stringschool){=school}PublicStringgetInfor(){StringstrInf=or+”:”+school;ReturnstrInf;}}PublicclassTestStudent{Publicstaticvoidmain(String[]args){Studentst1=newStudent(“张三”,22,“路家”);(“%sn”,or());}}多态一个父类的引用类型变量它既可以指向父类对象也可以指向子类对象,它可以根据当前时刻指向的不同,自动调用不同对象的方法,这就是多态多态的优点利用多态可以实现:同一段代码做不同事情多态注意事项子类对象可以直接赋给父类引用,但父类对象在任何情况下都不能直接赋给子类引用,因为子类是父类的一种,但父类不是子类的一种。通过父类引用只能访问子类对象从父类继承过来的成员,通过父类应用不能访问子类对象特有的成员父类引用永远不可能直接赋给子类引用,只有在父类引用本身指向的就是一个子类对象时,才可以把父类引用强制转化为子类引用抽象类抽象类的由来:利用抽象类是为了更好的对类加以分类。抽象类通常用来作为一个类族的最顶层的父类,用最底层的类表示现实中的具体事物,用最顶层的类表示该类族所有事物的共性抽象方法在定义java方法时可以只给出方法头,而不给出方法内部实现代码,这样的方法称为抽象方法。凡是没有方法体的方法必须得使用关键字abstract修饰为抽象方法。凡是含有抽象方法的类都必须得声明为抽象类。抽象类用abstract关键字来修饰一个类时,该类叫做抽象类包含抽象方法的类必须声明为抽象类。但是一个抽象类中却可以不包含任何抽象方法,尽管比较少见。抽象类不一定有抽象方法,有抽象方法的一定是抽象类FinalFinal可以修饰:整个类,类中的若干个属性,类中的若干个方法Final修饰整个类,表示该类不能被继承,如果认为一个类已经很完美不需要定义子类来继承它时,可以使用它。Final修饰类中的若干属性表示该属性必须被赋值并且只能被赋一次值(注意默认值不算真正的赋值)初始化方式有两种(只能选择其中的一种):在定义成员变量的同时初始化;在类中所有的构造函数中初始化注意:一个类的所有普通方法内部都不可以修改final修饰过的成员变量的值接口接口的定义:就是抽象方法和常量的集合。从本质上讲,接口是一种特殊的抽象类。接口的格式:【public】interfaceinterfaceName【extendsSuperInterfaceList】{......//常量定义和方法定义}1、接口中定义的属性必须是publicstaticfinal的,而接口中定义的方法则必须是publicabstract的,因此这些修饰符可以部分或全部省略2、接口中定义的属性的值在实现类中不能被修改3、一个类智能实现某个接口,不能继承某个接口。但接口可以继承接口4、接口不但可以继承接口,而且可以继承多个接口,即接口可以允许多继承5、如果一个类只实现了一个接口的部分方法,则该类必须得声明为抽象类6、一个类可以在继承一个父类的同时实现一个或多个接口,但extends关键字必须得在implements之前7、不可以new接口对象,但可以定义一个接口引用类型的变量并将其指向实现接口的对象,达到多态的目的接口的作用1、通过接口可以实现不相关类的相同行为。如:java规定所有可以完成自我复制功能的类都必须得实现ble接口,但该接口却是空的,该接口中没有任何内容,目的只是为了起个标志作用2、接口提供了不同对象进行协作的平台,如:事件处理3、接口可以实现多继承,从一定程度上弥补了类只能单继承的缺陷4、接口是我们了解一个类功能的重要途径。如:java整个容器框架就是以接口的方式建立起来的,实现不同接口的类完成的是不同的功能,接口是我们了解一个类功能的重要途径接口与抽象类的区别1、接口中的方法不允许有方法体,但抽象类却允许2、Java类不允许多继承,接口却允许多继承。包1、Package语句必须得是第一条语句2、表示:把该文件中所有的类放入这个包中,并且该文件中所有的类真正名字将是包名和类名的组合。如:类TestPackage的名字将变成ckage,而不再是TestPackage3、编译时建议使用,尽量不要使用因为后者要自己手动建立包目录4、如果不再当前路径下运行程序,则必须保证class文件的最上层目录的父目录位于classpath下(ckage解析:先检测当前目录下是否有zhangsan/lisi这个包-包即文件夹,如果有,再检测该包下是否有ckage这个类,如果没有,编译器将再去classpath设置的路径中一次查找。如果都查找失败,则运行时出错)同包不同类的相互访问因为类A和类B默认是在同一个无名的包中所以彼此可以相互访问,只要是非私有成员都可以被同包的另一个类访问不同包类的相互访问:建议一起编译使用不同包中类的方式:1、使用一个类的全名,如:=.A();2、使用import语句导入一个包中所有的类,如:.*;3、使用import语句导入一个包中特定的类,如:.A;注意:导入父包的类并不会自动导入子包的类。如:importzhangsan.*;只会导入zhangsan这个包下的所有类,并不会导入zhangsan子包lisi这个包中的类不同包访问修饰符问题1、在同一个包中只有私有的不能被另一个类访问,也只有私有的不能被继承2、在不同包没有任何关系的两个类,只有public类的public成员才可以被另一个包中的类访问3、在不同包中有继承关系的两个类,只有public类的public成员和public类的protected成员可以被另一个包中的子类在内部使用,但是在子类的外部,通过子类对象名只能访问父类的public成员Jar使用举例格式:jar-cvf要生成的包名.Jar*举例:1、*功能:把当前路径下所有的文件即文件夹下所有的内容打包成2、功能:在DOS下显示这个包解压后的文件的内容3、jar-xfd:功能:把d:这个文件中的内容解压到当前目录下异常处理什么是异常:异常(Exception)是程序运行过程中发生的事件,该事件可以中断程序指令的正常执行流程异常的处理机制:1、当Java程序运行时出现问题时,系统会自动检测到该错误,并立即生成一个与该错误对应的异常对象2、然后把该异常对象提交给Java虚拟机3、Java虚拟机会自动寻找相应的处理代码来处理这个异常,如果没有找到,则由Java虚拟机做一些简单的处理后,程序被强行终止4、程序员可以自己编写代码来捕捉可能出现的异常,并编写代码来处理相应的异常为什么要使用异常处理r;ismatchException;PublicclassTestExcep_3{Publicstaticvoidmain(String[]args){Inti;Scannersc=newScanner();Try{I=t();(“i=%dn”,i);}Catch(InputMismatchExceptione){//tackTrace();该方法在调试时使用,用来显示异常信息(“输入数据不合法,程序被终止!n”)}}}异常的分类凡是继承自Exception但又不是RuntimeException子类的异常我们都必须得捕捉并进行处理异常处理步骤Try{可能出现异常的代码块}Catch(ExceptionName1e){当产生ExceptionName1异常时的处理措施}Catch(ExceptionName2e){当产生ExceptionName2异常时的处理措施}........Finally{无论是否捕捉到异常都必须处理的代码}Finally的作用1、无论try所指定的程序块中是否抛出异常,也无论catch语句的异常类型是否与所抛出的异常的类型一致,finally中的代码一定得到执行2、Finally语句为异常处理提供一个统一的出口,使得在控制流程转到程序的其他部分以前,能够对程序的状态作统一的管理3、通常在finally语句中可以进行资源的清除工作,如关闭打开的文件,删除临时文件等ThrowThrow用来抛出异常格式:thrownew异常名(参数);假设f方法抛出了A异常,则f方法有两种方式来处理A异常:1、throwsA,谁调用f方法,谁处理A异常,f方法本身不处理A异常2、Try{...}catch(){......},f方法本身自己来处理A异常注:要抛出的异常必须得是Throwable的子类ThrowsVoidf()throwsA{......}ThrowsA表示调用f方法时f方法可能会抛出A类异常,建议调用f方法时最好对f方法可能抛出的A类异常进行捕捉ThrowsA不表示f方法一定会抛出A类异常。ThrowsA不表示调用f方法时,必须得对A异常进行捕捉。假设A是RuntimeException子类异常,由于RuntimeException的子类异常可以处理也可以不处理,所以编译器允许调用f方法时,对f方法抛出的RuntimeException子类异常不进行处理强烈建议:1、对throws出的所有异常进行处理2、如果一个方法内部已经对A异常进行了处理,就不要再throwsA注意问题:1、所有的catch只能有一个被执行。有可能所有的catch都没有执行。2、先catch子类异常再catch父类异常3、Catch与catch之间是不能有其他代码的4、重写方法抛出异常的范围不能大于被重写方法抛出的异常范围异常的优缺点:1、强制程序员考虑程序的安全性与健壮性2、增强了程序员对程序的可控性3、有利于代码的调试4、把错误处理代码从常规代码中分离出来注意:1、异常并不一定能够使程序的逻辑更清晰(因为有时我们必须得编写代码捕捉异常,所以可能会导致程序的逻辑非常混乱)2、异常并不能解决所有的问题toString1、所有的类都默认自动继承了Object类2、Object类中的toString方法返回的是类的名字和该类对象哈希吗组成的一个字符串3、n(类对象名);实际输出的是该对象的toString()方法所返回的字符串4、为了实际需要,建议子类重写从父类Object继承的toString方法Object类的equals方法1、所有类都从Object类中继承了equals方法2、Object类中equals方法源代码如下:Publicbooleanequals(Objectobj){Returnthis==obj;}3、Object中的equals方法是直接判断this和obj本身的值是否相等,即用来判断调用equals的对象和形参obj所引用的对象是否是同一对象,所谓同一对象就是指是内存中同一块存储单元,如果this和obj指向的是同一块内存对象,则返回true,如果this和obj指向的不是同一块内存,则返回false。注意:即便是内容完全相等的两块不同的内存对象,也会返回false4、如果是同一块内存,则Object中的equals方法返回true,如果是不同的内存,则返回false何时需要重写equals方法1、用一个类构造出来的不同内存的两个对象,如果内存中的值相等,我们一般情况下也应该认为这两个对象相等,很明显Object中的equals()无法完成这样的重任,Object中的equals()方法只有在两个对象是同一块内存时,才返回true,这时我们就有必要重写父类Object中的equals方法2、如果希望不同内存但相同内容的两个对象equals时返回true,则我们需要重写父类的equals方法String类1、类对象表示不可修改的Unicode编码字符串2、在java中双引号括起来的字符串也被当做String对象如:n(“abc”.length());//输出n(“abc”.equals(“abc”));//输出trueString类的equals方法1、String类已经重写了Object中的equals方法如:假设str1和str2都是String对象。(str2):是用来比较str1变量本身所占内存的值所指向的对象和str2变量本身所占内存的值所指向的对象的内容是否相等,如果相等则返回true,否则返回false2、String类的equals方法是用来判断两个对象的内容是否相等的,Object类的equals方法是用来判断两个对象是否是同一个对象StringBuffer类的由来1、String类对象一旦创建就不可更改2、如果经常对字符串内容进行修改,则使用StringBuffer3、如果经常对字符串内容进行修改而使用String的话,就会导致既耗空间又耗时间4、StringBuffer对象的内容是可以改变的5、因此String类中没有修改字符串的方法,但是StringBuffer类中却有大量修改字符串的方法StringBuffer类的构造函数PublicStringBuffer()创建一个空的没有任何字符的StringBuffer对象PublicStringBuffer(intcapacity)创建一个不带字符,但具有指定初始容量的字符串缓冲区PublicStringBuffer(Stringstr)创建一个StringBuffer对象,包含与str对象相同的字符序列什么叫程序所谓“程序”,是一个严格有序的指令集合。程序规定了完成某一任务时,计算机所需做的各种操作,以及这些操作的执行顺序。单道程序设计环境中程序特点单道程序设计环境是指:计算机中除了操作系统之外,只存在一个用户程序,即用户程序独享整个计算机资源。单道程序有如下特点:1、资源的独占性2、执行的顺序性3、结果的再现性多道程序设计环境中程序特点多道程序设计是指:计算机中除了操作系统之外,存在多个用户程序,这些程序同时运行。多道程序设计有如下特点:1、间断性:由于资源共享和合作,并发程序间相互制约,造成合作执行间断2、失去封闭性:程序执行受外界影响3、不可再现性:重复执行时,可能得到不同结果进程的由来一方面为了保持程序“是一个在时间上严格有序的指令集合,是静态的保存在存储介质上”这个概念的原有含义,另一方面为了刻画多个程序共同运行时呈现出的这些特征,在操作系统中,以“程序”为基础,又引入了“进程”这一新概念。按照大多数教材的说法,为了使程序能并发执行,且为了对并发执行的程序加以描述,所以人们引入了进程。什么叫进程进程是程序在某个数据集上的执行。进程是一个动态的实体,它有自己的生命周期。它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而被撤销。线程的定义线程是一个程序里的不同执行路径以前所编写的程序,每个程序都只有一个入口,一个出口以及一个顺序执行的序列,在程序执行过程中的任何指定时刻,都只有一个单独的执行点。事实上,在单个程序内部是可以在同一时刻进行多种运算的,这就是所谓的多线程。多线程的优势1、多线程编程简单,效率高(能直接共享数据和资源,多进程不能)2、适合于开发服务程序(如Web服务,聊天服务等)创建一个线程的第一种方法1、创建一个继承Thread的类(假定类名为A),并重写Thread中的run方法2、构造一个A类对象,假定对象名为aa3、调用aa的start方法【start方法是从Thread继承过来的】注意的问题1、Thread中start()方法的功能就是创建一个新的线程,并自动调用该线程的run()方法,直接调用run()方法是不会创建一个新的线程的2、执行一个线程实际就是执行该线程run方法中的代码3、执行完();后并不表示aa所对应的线程就一定会立即得到执行,();执行完后只是表示aa线程具有了可以立即被CPU执行的资格,但由于想抢占CPU执行的线程很多,CPU并不一定会立即去执行aa所对应的线程4、一个Thread对象能且只能代表一个线程5、一个Tread对象不能调用两次start()方法,否则会抛出lThreadStateException异常创建一个新线程的第二种方法1、定义一个实现了Runnable接口的累,假定为A2、创建A类对象aa,代码如下:Aaa=newA();3、利用aa构造一个Thread对象tt,代码如下:Threadtt=newThread(aa);4、调用tt中的start方法,代码如下:();Thread的常用方法PublicfinalvoidsetName(Stringname)设置当前线程的名字PublicstaticThreadcurrentThread()返回对当前正在执行的线程对象的引用PublicfinalStringgetName()返回当前线程的名字线程优先级线程的优先级用数字来表示,范围从1到10。主线程的缺省优先级是5,子线程的优先级默认与其父线程相同线程的休眠1、线程休眠——暂停执行当前运行中的线程,使之进入阻塞状态,待通过指定的“延迟时间”后再醒来并转入到就绪状态2、Thread类提供的相关方法Publicstaticvoidsleep(longmillis)Publicstaticvoidsleep(longmillis,intnanos)3、由于是静态方法,可以由Thread直接调用4、Sleep()方法会抛出InterruptedException异常,我们必须得对其进行捕捉。(无论是继承Thread类的run方法还是实现Runnable接口的run方法,都不能抛出任何异常——原因:重写方法抛出异常的范围不能大于被重写方法抛出的异常范围)线程的让步1、让出CPU,给其他程序执行的机会2、让运行中的线程主动放弃当前获得的CPU处理机会,但不是使该线程阻塞,而是使之转入就绪状态3、Publicstaticvoidyield()线程的串行化1、在多线程程序中,如果在一个线程运行的过程中要用到另一个线程的运行结果,则可进行线程的串行化处理2、Publicfinalvoidjoin()throwsInterruptedException买票程序ClassAimplementsRunnable{Publicinttickets=100;Stringstr=newString(“哈哈”);Public{voidrun()While(true){Synchronized(str){If(tickets>0){(“%s线程正在卖出第%d张票n”,tThread().getName(),tickets);--tickets;}Else{Break;}}}}}Public{classTestTicketsPublicstaticvoidmain(String[]args){Aaa=newA();Threadt1=newThread(aa);();Threadt2=newThread(aa);();}}Synchronized关键字1、Synchronized可以用来修饰:一个方法;一个方法内部的某个代码块2、格式:Synchronized(类对象名aa){同步代码块}3、功能:synchronized(类对象名aa)的含义是:判断aa是否已经被其他线程霸占,如果发现已经被其他线程霸占,则当前线程陷入等待中,如果发现aa没有被其他线程霸占,则当前线程霸占住aa对象,并执行同步代码块内容,在当前线程执行同步代码块时,其他线程将无法再执行同步代码块内容(应为当前线程已经霸占了aa对象),当前线程执行完同步代码块内容后,会自动释放对aa对象的霸占,此时当前线程和其他线程会相互竞争对aa的霸占,最终CPU会选择其中的某一个线程执行4、最终导致的结果是:一个线程正在操作某资源的时候,将不允许其他线程操作该资源,即一次只允许一个线程处理该资源生产消费ClassSynStack{Privatechar[]data=newchar[6];Privateintcnt=0;//表示数组有效元素的个数Publicsynchronizedvoidpush(charch){While(cnt==){Try{();//7行}Catch(Exceptione){}}();//10行Data[cnt]=ch;++cnt;(“生产线程正在生产第%d个产品,该产品是:%cn”,cnt,ch);}Publicsynchronizedcharpop(){While(cnt==0){Try{();}Catch(Exceptione){}}();//20行Ch=data[cnt-1];(“消费线程正在生产第%d个产品,该产品是:%cn”,cnt,ch);--cnt;Returnch];//23行}}ClassProducerimplementsRunnable{PrivateSynStackss=null;PublicProducer(SynStackss){=ss;}Publicvoidrun(){Charch;Try{(2000);}Catch(Exceptione){}For(inti=0;i<20;++i){Try{(2000);}Catch(Exceptione){}Ch=(char)(‘a’+i);();}}}ClassConsumerimplementsRunnable{PrivateSynStackss=null;PublicConsumer(SynStackss){=ss;}Publicvoidrun(){For(inti=0;i<20;++i){Try{(2000);}Catch(Exceptione){}();}}}PublicclassTestPC{Publicstaticvoidmain(String[]args){SynStackss=newSynStack();Producerp=newProducer(ss);Consumerc=newConsumer(ss);Threadt1=newThread(p);();Threadt2=newThread(c);();}}如上述程序,假设现在有两个线程P(生产)和C(消费)。P生产已满,执行7行代码陷入阻塞状态,同时释放P线程对this的锁定,这时候C线程会得到this对象的标志位开始运行。另外C线程执行完20行代码后,程序并不会立即转到P线程开始执行,因为执行notify,只是叫醒P,让P从因为waitthis对象而陷入阻塞的状态进入就绪状态。记住:一个线程notify该线程并不会释放对this的锁定,只有C执行完23行的代码后,C才会释放对this的代码锁定,这时候C和P会同时争夺this的锁定,具体执行那个由系统调度器决定。()’功能:将执行()的当前线程转入阻塞状态,让出CPU的控制权,释放对aa的锁定();功能:不是叫醒正在执行();的当前线程,而是叫醒一个现在正在waitthis对象的其他线程。如果有多个线程正在waitthis对象,通常是叫醒最先waitthis对象的线程。但是具体叫醒哪个是由系统调度器控制,程序员无法控制。例如:假设执行();的当前线程为T1,如果当前时刻有其他线程因为执行了()而陷入了阻塞状态,则叫醒其中的一个。所谓叫醒某个线程就是令该线程从因为wait而陷入阻塞的状态转入就绪状态。例如:假设现在有T1、T2、T3、T4四个线程。我们在T4线程中执行了()语句,则即便此时T1、T2、T3没有一个线程因为waitaa对象而陷入阻塞状态,T4线程中执行方法时也不会有任何错误。执行方法时如果一个线程都没有叫醒,这是可以的。All()叫醒其他所有的因为执行了()而陷入阻塞状态的线程GUI组件组件(Component)是图形用户界面的基本组成元素,凡是能够以图形化方式显示在屏幕上并能够与用户进行交互的对象均为组件,如菜单、按钮、标签、文本框、滚动条等。组件分类1、mponent2、说明:抽象类ent是出菜单相关组件之外所有javaAWT组件类的根父类,该类规定了GUI组件的基本特性,如尺寸、位置和颜色效果等,并实现了作为一个GUI不见所应具备的基本功能。容器1、组件通常不能独立地显示出来,必须将组件放在一定的容器中才可以显示出来。2、有一类特殊的组件是专门用来包含其他组件的,这类组件叫做容器,ner是所有容器的父类,ner继承自ent3、容器类对象本身也是一个组件,具有组件的所有性质,但反过来组件却不一定是容器布局管理器1、容器对其中所包含组件的排列方式,包括组件的位置和大小设定,被称为容器的布局(Layout)2、为了使图形用户界面具有良好的平台无关性,Java语言提供了布局管理器来管理容器的布局,而不建议直接设置组件在容器中的位置和尺寸3、每个容器都有一个默认的布局管理器,当容器需要对某个组件进行定位或判断其大小尺寸时,就会自动调用其对应的布局管理器布局管理器总结1、Frame是一个顶级窗口,Frame的缺省布局管理器为BorderLayout2、Panel无法单独显示,必须添加到某个容器中。Panel的缺省布局管理器为FlowLayout3、当把Panel作为一个组件添加到某个容器中后,该Panel仍然可以有自己的布局管理器4、使用布局管理器时,布局管理器负责各个组件的大小和位置,因此用户无法在这种情况下设置组件大小和位置属性,如果试图使用Java语言提供的setLocation(),setSize(),setBounds()等方法,则都会被布局管理器覆盖5、如果用户确实需要亲自设置组件大小或位置,则应取消该容器的布局管理器,方法为:setLayout(null);事件处理事件(Event)用户对组件的一个操作,称之为一个事件事件源(EventSource)能够产生事件的GUI组件对象,如按钮、文本框等事件处理方法(EventHandler)能够接收、解析和处理事件类对象,实现与用户交互功能的方法事件监听器(EventListener)可以处理事件的一个类事件处理步骤假设事件为XXXX1、向事件源注册某种事件的事件监听器对象addXXXXListener(...);2、设计好可以处理这种事件的事件监听器Class类名implementsXXXXListener{重写XXXXListener接口中的方法}说明:要想设计出能够处理XXXX事件的监听器,只需要编写出实现了XXXXListener接口的类就OK了,因为XXXXListener接口中已经定义了可以处理XXXX事件的方法。事件处理相关概念1、默认情况下事件源不会自动产生任何事件,程序员需要做两件事:告诉事件源可以自动产生哪类事件,即:向事件源注册某种事件的时间监听器对象。设计好可以处理这种时间的时间监听器。2、一旦完成了这两步操作,当用户对事件源进行操作时,事件源就会自动产生事件,事件源就会自动把产生的事件封装成一个事件对象,事件源就会自动把封装好的事件对象传递给事件监听器。3、事件监听器收到事件源发送过来的事件时,事件监听器就会自动调用相应的事件处理方法来对该事件进行相应的处理。事件有哪些包中含有所有的事件,常用的事件有:1、ActionEvent:激活组件时发生的事件2、KeyEvent:操作键盘时发生3、MouseEvent:操作鼠标时发生4、WindowEvent:操作窗口时发生的事件,如最大化或最小化某一窗口(一个事件源可以自动产生哪些事件,第三方软件会自动显示,不需要人为记忆。)十个按钮的设计.*;PublicclassTestGUI{Publicstaticvoidmain(String[]args){Framef=newFrame();e(300,300);out(newGridLayout(2,1));Panelp1=newPanel();out(newBorderLayout());Panelp1-1=newPanel();out(newGridLayout(2,1));Buttonbn1=newButton(“BUTTON1”);Buttonbn2=newButton(“BUTTON2”);Buttonbn3=newButton(“BUTTON3”);Buttonbn4=newButton(“BUTTON4”);(bn1,);(bn3);(bn4);(p1-1,);(bn2,);Panelp2=newPanel();out(newBorderLayout());Panelp2-2=newPanel();out(newGridLayout(2,2));Buttonbn5=newButton(“BUTTON5”);Buttonbn6=newButton(“BUTTON6”);Buttonbn7=newButton(“BUTTON7”);Buttonbn8=newButton(“BUTTON8”);Buttonbn9=newButton(“BUTTON9”);Buttonbn10=newButton(“BUTTON10”);(bn5,);(bn6,);(bn7);(bn8);(bn9);(bn10);(p2-2,);(p1);(p2);();ible(true);}}三个文本框相加事例.*;.*;PublicclassTestTextField{PublicstaticTextFieldtf1,tf2,tf3;Publicstaticvoidmain(String[]args){tf1=newTextField(30);tf2=newTextField(30);tf3=newTextField(30);Buttonbn=newButton(“=”);LabelLb=newLabel(“+”);Framef=newFrame(“文本框相加事例”)out(newFlowLayout());(tf1);(Lb);(tf2);(bn);(tf3);ionListener(newMyMonitor());();ible(true);}}ClassMyMonitorimplementsActionListener{@OverridePublicvoidactionPerformed(ActionEvente){Stringstr1=t();Stringstr2=t();Intnum1=nt(str1);Intnum2=nt(str2);Intnum3=num1+num2;Integerit=newInteger(num3);Stringstr3=ng();t(str3);}}.*;.*;PublicclassTestTextField{PublicstaticTextFieldtf1,tf2,tf3;Publicstaticvoidmain(String[]{TFtf=newTF();();}}ClassTF{PublicTextFieldtf1,tf2,tf3;Publicvoidlaunch(){tf1=newTextField(30);tf2=newTextField(30);tf3=newTextField(30);Buttonbn=newButton(“=”);LabelLb=newLabel(“+”);Framef=newFrame(“文本框相加事例”)out(newFlowLayout());(tf1);(Lb);(tf2);(bn);(tf3);ionListener(newMyMonitor(this));();ible(true);}}ClassMyMonitorimplementsActionListener{args)PrivateTFtf;PublicMyMonitor(TF{=tf;}tf)@OverridePublicvoidactionPerformed(ActionEvent{Stringstr1=t();Stringstr2=t();Intnum1=nt(str1);Intnum2=nt(str2);Intnum3=num1+num2;Integerit=newInteger(num3);Stringstr3=ng();t(str3);}}e)可运行jar包生成步骤1、新建一个记事本文件,假设为,文件内容为:Main-Class:可运行类的名字附注:记得敲回车2、dos下命令:记住:只有GUI程序生成的class文件才可以作为mainclass流流的定义:流就是程序和设备之间嫁接起来的一根用于数据传输的管道,这个管道上有很多按钮,不同的按钮可以实现不同的功能。这根带按钮的用于数据传输的管道就是流。流的分类标准:按数据流的方向不同可以分为输入流和输出流按处理数据单位不同可以分为字节流和字符流按照功能不同可以分为节点刘和处理流流与类的关系:如果一个类是用作设备和程序之间的数据传输,则这个类有一个新的名字叫流。流一定是类,但类不一定是流在Java中一个字符占两个字节InputStream流中常用的方法publicintread();throwIOException读取一个字节并以整数形式返回如果读取到输入流的末尾则返回-1publicintread(byte[]b)throwIOException从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中。以整数形式返回实际读取的字节数如果b的长度为0,则不读取任何字节并返回0;如果因为流位于文件末尾而没有可用的字节,则返回值-1publicintread(byte[]b,intoff,intlen)throwIOException从输入流中最多读取len个字节的数据并存入byte数组中b表示读取的数据要存入的数组的名字off表示第一个读出的数据要存入的位置,是下标len表示最多能读取的字节数尝试读取len个字节,但读取的字节也可能小于该值。以整数形式返回实际读取的字节数。如果读到了文件的末尾,则返回-1voidclose()throwIOException关闭此输入流并释放与该流关联的所有系统资源longskip(longn)throwIOException跳过和丢弃此输入流中数据的n个字节文件流文件流包括FileInputStreamFileOutputStream字节流,FileReaderFileWriter字符流InputStream是用来读取字节的,是个抽象类,我们通常使用的是该类的子类FileInputStream是InputStream的子类,利用FileInputStream可以将一个文件的内容按字节为单位读取出来FileInputStream有一个常用的构造函数publicFileInputStream(StringfileName)throwsFileNotFoundException利用该构造函数可以实现将输入流连接到某个文件的功能必须对本构造函数抛出的异常进行捕捉如果用字符串来表示操作系统的文件路径时,我们可以使用和/两种方式来作为文件夹的路径分隔符字节流与字符流的区别FileInputStream和FileOutputStream可以完成所有格式文件的复制FileReader和FileWriter只可以完成文本文件的复制,却无法完成视频格式文件的复制因为字节是不需要解码和编码的,将字节转化为字符才存在解码和编码的问题字节流可以从所有格式的设备中读写数据,但字符流只能从文本格式的设备中读写数据.*;publicclassTestFileReaderWriterCopy{publicstaticvoidmain(String[]args)throwsException{FileReaderfr=newFileReader(“D:”);FileWriterfw=newFileWriter(“E:”);intch;ch=();while(-1!=ch){(ch);ch=();}();();();}}缓冲流缓冲流就是带有缓冲区的输入输出流缓冲流可以显著的减少我们对IO访问的次数,保护我们的硬盘缓冲流本身就是处理流(处理流也叫包裹流),缓冲流必须得依附于节点流(节点流也叫原始流)处理流是包裹在原始节点流上的流,相当于包裹在管道上的管道.*;publicclassTestBufferedInputSteamCopy{publicstaticvoidmain(String[]args)throwsException{BufferedInputSteambis=newBufferedInputSteam(newFileReader(“D:”));BufferedInputSteambos=newBufferedInputSteam(newFileWriter(“E:”));byte[]buf=newbyte[1024];intlen;len=(buf);while(-1!=len){(buf,0,len);len=(buf);}();();();}}.*;publicclassTestBufferedReaderCopy{publicstaticvoidmain(String[]args)throwsException{BufferedReaderbr=newBufferedIReader(newFileReader(“D:”));BufferedWriterbw=newBufferedWriter(newFileWriter(“E:”));Stringstr=null;while(null!=(str=ne()))//ne()读一行,不包含换行符{(str);e();//写入一个换行符这行不能省}();();();}}数据流编程实现将long类型数据写入byte数组,然后再从byte数组中把该数据读出来附注:这是Socket编程中经常要完成的功能因为网络编程中经常要把数值型数据存入byte数组中,然后把byte数组打包成数据包(即DatagramPacket),再把数据包经过网络传输到目的机,目的机再从byte数组中把原数值型数据还原回来.*;publicclassTestData{publicstaticvoidmain(String[]args)throwsException{ByteArrayOutputStreambaos=newByteArrayOutputStream();DataOutputStreamdos=newDataOutputStream(baos);longm=1234567;ong(m);();byte[]buf2=Array();ByteArrayInputStreambais=newByteArrayInputStream(buf2);DataInputStreamdis=newDataInputStream(bais);longn;n=ng();n(“n=”+n);}}转换流OutputStreanmWriter流是把OutputStream流转化成Writer流的流InputStreamReader是把InputStream转化成ReaderOutputStreamWriter和InputStreamReader都是包裹流例子:如何将键盘输入的字符组成字符串直接赋给String对象.*;publicclassTestString{Publicstaticvoidmain(String[]args){Stringstr=null;try{BufferedReaderbr=newBufferedReader(newInputStreamReader());str=ne();n(“str=”+str);}catch(Exceptione){}}}str=ne();如果直接输入回车的话1、ne()会丢弃回车符,而不是返回回车符,即ne()遇到回车符时终止读取,并且会把读取到的回车符自动丢弃掉2、ne()返回的是””而不是null,””表示空字符串,null表示空指针,空指针就是空地址,空地址就是不指向任何存储单元的意思Print流Print流只有输出,没有输入分类:PrintWriter输出字符,PrintStream输出字节tackTrace();默认是把错误信息输出到所关联的设备中对象的序列化所谓序列化是指:把一个Object对象直接转化为字节流,然后把这个字节流直接写入本地硬盘或网络中。如果要想把某个对象序列化,则必须得实现Serializable接口。Serializable接口中并没有任何方法,这种类型的接口被称为标记接口,如果一个类实现了Serializable接口,潜在含义就是告诉编译器这个类是允许被序列化的,如果程序中存在序列该对象的代码,编译器就会自动进行相应的处理以完成该对象的序列化,如果该对象没有实现Serializable接口,程序中却存在该对象被序列化的代码,编译器编译时就会报错。在Java中transient修饰的成员变量在对象序列化时不被序列化
发布评论