Java基础知识学习_第1页
Java基础知识学习_第2页
Java基础知识学习_第3页
Java基础知识学习_第4页
Java基础知识学习_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

合肥达内总结的几大点合肥达内总结的几大点Java知识,供学习IT的人参考文章出门:文章出门:http://www.aiitaieiui.coni具体详悄可以百度“合肥达内合肥达内总结的几大点合肥达内总结的几大点Java知识,供学习IT的人参考文章出门:文章出门:http://www.aiitaieiui.coni具体详悄可以百度“合肥达内合肥达内总结的几大点合肥达内总结的几大点Java知识,供学习IT的人参考文章出门文章出门:http:/,‘www-ahtaienacom 具体详情可以百■度“合肥达内Java语言中接口优于抽象类Java语言设计提供了两种机制,可以用来定义允许多个实现的类型:接II和抽象类。因为Java只允许单继承,所以抽象类作为类型定义受到了极人的限制。现有的类可以很容易被更新,以实现新的接口。一般来说,无法更新现有的类来扩展新的抽彖类。如果你希塑两个类来扩展一个抽彖类,就必须把抽象类放到类型层次的高处,以便这两个类的一个祖先成为他的子类。这样会间接的伤害到类的层次,迫使这个公共祖先的所有后代类都扩展这个新的抽象类,无论他对于这个后代类是否合适。接II是定义mixin(混合类型)的理想选择。类除了实现他的“基本类型(pnmarytype)”之外,还可以实现这个mixin类型,以表示提供了某些可供选择的行为。接II允许我们构造非层次结构的类型框架。包装类(wrapperclass)模式,接II使得安全地增强类的功能成为可能。通过对你导出的每个重要接II都提供一个抽彖的骨架实现(skeletalimplementation)类,把这个抽象类的优点结合起来。必须认真研究接II,并确定哪些方法是最为基本的(pimutive),其他的方法则可以根据他们来实现。这些基本的方法将成为骨架实现类中抽象方法o然后,必须为接II中所有其他的方法提供具体的实现。抽象类的演变比接II的演变要容易的多。接II一旦被公开发行,并且已被广泛实现,再想改变这个接口几乎是不可能的。java的动态绑定所谓的动态绑定就是指程执行期间(而不是在编译期间)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。java继承体系中的覆盖就是动态绑定的,看一下如下的代码:classFather{publicvoidmethod(){System.out.pimtlii("ThisisFather'smethod");}}classSonlextendsFather{publicvoidmethod(){System.out.piiiitlii(nThisisSonfsmethodH);}}classSoii2extendsFather{publicvoidmethod(){System.out.piiiitlii(nThisisSoii2fsmethodH);}}publicclassTest{publicstaticvoidmain(Stnng[]args){Fathersi=newSonl();sl.method();Fathers2=newSon2();s2.method();}}运行结果如下:TinsisSonfsmethodTinsisSon2*smethod通过运行结果可以看到,尽管我们引用的类型是Father类型的,但是运行时却是调用的它实际类型(也就是Sonl和Soii2)的方法,这就是动态绑定。在jaw语言中,继承中的覆盖就是是动态绑定的,当我们用父类引用实例化子类时,会根据引用的实际类型调用相应的方法。java的静态绑定相对于动态绑定,静态绑定就是指在编译期就已经确定执行哪一个方法。在java中,方法的重载(方法名相同而参数不同)就是静态绑定的,重载时,执行哪一个方法在编译期就已经确定下来了。看一下代码:classFather{}classSon!extendsFather{}classSoii2extendsFather{}classExecute{publicvoidmethod(Fatherfathei){System.out.pimtlii(nThisisFather'smetliod");}publicvoidmethod(Sonlson){System.out.prmtlii(nThisisSonfsmethodH);}publicvoidmethod(Son2son){System.out.prmtlii(nThisisSoii2fsmethodH);}}publicclassTest{publicstaticvoidmam(Stnng[]args){Fatherfather=newFatherQ;Fathersi=newSonl();Fathers2=newSon2();Executeexe=newExecute();exe.method(fatlieij;exe.method(sl);exe.method(s2);}}运行结果如下:TlusisFathersmethodTlusisFathersmethodTlusisFathersmethod在这里,程序在编译的时候就已经确定使用metliod(Fatherfather)方法了,不管我们在运行的时候传入的实际类型是什么,它永远都只会执行method(Fatherfatlier)这个方法。也就是说,java的重载是静态绑定的。Java面向对象设计构造函数设计在Javascript面向对象设计 我们将使用构造函数模式将工厂模式进行改写。fiinctionEmploye亡(name,ageJob){=name;this.age=age;this.job=job;this.savName=function(){alert(tlus.naine);};}varJun=newEmplovee(njimM,22,nSoftWaieEngmeer*');合肥达内总结的几大点合肥达内总结的几大点Java知识,供学习IT的人参考文章出文章出i'I:http:/,‘www-ahtaienacom 具体详情可以百■度"合肥达内合肥达内总结的几大点合肥达内总结的几大点Java知识,供学习IT的人参考文章出文章出i'I:http:/,‘www-ahtaienacom 具体详情可以百■度"合肥达内合肥达内总结的几大点合肥达内总结的几大点Java知识,供学习IT的人参考文章出白:文章出白:http:力ahtarenacom具体详情可以百度"合肥达内"varSun=newEmployee("Sun",24,"Doctor");JmisayNameQ;Sun.sayName();在以上代码中Employee函数取代了CreateEniployee函数,Employee中的代码与CieateEmployee中的代码不同如下:没有显示的创建对彖直接将属性和方法赋给了tlus对彖没有lemin语句要创建Employee类的新实例,必须使用new操作符,实际会经历四个步骤:创建一个新对彖将构造函数的作用域赋给新的对彖执行构造函数中代码返回新对彖以上代码最后Jun和Sun中分别保存着Employee的两个不同实例,这两个实例都有一个constmctor(构造函数)属性,该属性指向Employee,可以做如卞测试aleil(JiininstanceofEniployee);"truealeil(SuniiistaiiceofEmployee)^/tme同时这两个对彖又都是Object类型的,可通过如下代码检测。aleil(JiininstanceofObject);//truealeil(SuniiistaiiceofObject);//tiiie创建自定义的构造函数意味着将来可以把它的实例标石为一种特定的类型,而这也正是构造函数模式胜过工厂模式的地方。卜•面详细讲解一下构造函数:将构造函数当做函数构造函数与其他函数的唯一区别就在于调用它们的方式不同。但是构造函数也是函数,不存在定义构造函数的特殊语法。其实,任何函数,只有通过new来调用,那他就可以作为构造函数,例如,Employee除了以上用new方法调用外,还可以用如下方式来调用。〃作为普通函数调用Employee(MSun,\2&”SoftwareEngmeer");//添加到window中window.savNameQ;//Sun〃在另一个对象的作用域中调用varo=newObjectQ;Employee.call(o,HSunf\28,HSoftWareEngmeern);o.savNameQ;//Sum这样就解决了两个函数做同一件爭情的问题,但是新的问题又会出现了,这个在全局作用域中定义的函数,实际上只能被某个对象引用,而且最要命的问题是,如果对彖需要定义很多方法,那么就需要定义很多个全局函数,所以这个自定义的引用类型,就没有任何封装性可言了。java按权重选取目标一个测试题假设权重总和是total,那么在这个范围内产生一个随机数,观察这个随机数的所在区间,就能确定在哪个权重的范围之内了。举个例子,有三个武将A、B、C,他们的出现机率分别是30%、40%和30%。首先产生一个随机数,这里的权重总和是100,分为三个区间,1〜30,31〜70,71~100。自然随机数的范围也在100以内。假如这个随机数是49,很明显49是在31~70这个区间内,那么可确定该次随机产生的武将是B。思路是这样,但是怎么用算法去实现呢?对于确定的情况,一个最简单的方法是这样:iiitrand=49;//随机数,这里假设是个给定值iiitA=30;intB=40;mtC=30;if(rand>0&&rand<=A){returnA;}elseif(rand>A&&rand<=A+B){retmnB;}elseiRrand>A+E&&iand<=A+B+C){returnC;}但是上面说过,这个权重的总和是不确定的,武将个数也不确定,这样做肯定不行。后来想到了一个简单的办法:iiitrand=49;//随机数intsum=0;List<one>list=newAiiayList<one>();//假设这是一个武将列表for(mti=0;i合肥达内总结的几大点合肥达内总结的几大点Java知识,供学习IT的人参考合肥达内总结的几大点合肥达内总结的几大点Java知识,供学习IT的人参考Java的package到底有何用处让我们先了解一下,Jaw的package到底有何用处。其实,package名称就像是我们的姓,而class名称就像是我们的名字。package名称有很多。的,就好像是复姓。比如说java.lang.String,就是复姓java.lang,名字为Strmg的类别:java.io.IiiputStieam则是复姓java.io,名字为IiiputStream的类别。Java会使用package这种机制的原因也非常明显,就像我们取姓名一样,光是一间学校的同一届同学中,就有可能会出现不少同名的同学,如果不取姓的话,那学校在处理学生数据,或是同学彼此之间的称呼,就会发生很人的困扰。相同的,全世界的Java类别数量,恐怕比台湾人口还多,而且还不断的在成长当中,如果类别不使用套件名称,那在用到相同名称的不同类别时,就会产生极大的困扰。幸运的是,Java的套件名称我们可以自己取,不像人的姓没有太人的选择(所以有很多同名同姓的),如果依照Sun的规范来取套件名称,那理论上不同人所取的套件名称不会相同(请参阅“命名惯例”的相关文章),也就不会发生名称冲突的情况。可是问题来了,因为很多套件的名称非常的长,在写程序时,会多打好多字,花费不少时间,比如说:java.io.IiiputStreamis=java.lang.System.in;java.io.IiiputStreaniReaderisi-newjava.lo.InputStieaiiiReader(is):java.io.BufieiedReaderbr=newjava.io.BufifeiedReader(isr);实在是不美观又麻烦。于是,Sun想了一个办法,就是import.这个import就是在程序一开头的时候,先说明程序中会用到那些类别的简称,也就是只称呼名字,不称呼他的姓。首先,在档案开头写:miportjavaSystem;miportjava.io.LiputStieam;miportjava.io.LiputStieamReader;文章出白:http:具体详情可以百度"合肥达内"合肥达内总结的几大点合肥达内总结的几大点Java知识,供学习IT的人参考文章出门:文章出门:具体详情可以百度“合肥达内合肥达内总结的几大点合肥达内总结的几大点Java知识,供学习IT的人参考文章出门:文章出门:具体详情可以百度“合肥达内合肥达内总结的几大点合肥达内总结的几大点Java知识,供学习IT的人参考文章出白文章出白:http:/.,' 具体详情可以百度"合肥达内”miportjava.io.BufieiedReader;这几行说明了这四个姓名的类别,在程序中只用他的名字来称呼,所以当程序中提到System就是指java.lang.System,而Inputstream就是指java.io.Inputstream,依此类推。于是原来的程序就变成:Inputstream=Svstem.in;LiputStreamReaderisr=newIiiputStreaniReader(is):BufieredReaderbr=newBufferedReader(isr):这样看起来是不是清爽多了呢?如果这些类别用的次数很多,那就更能体会到import的好处了。可是这样还是不够,因为懒是人的天性,还是会有人觉得打太多miport了也很浪费时间,于是Sun又提供了一个方法:miportjava」ang.*;miportjava.io.*;意思就是,等一下程序中提到的没有姓名的类别,不是姓jaw.lang,就是姓jaw.io,如果这两个里面有同样名字的类别,而不幸的你又只用名字称呼这个类别,那编译器仍然会跟你抱怨,因为它还是不知道你说的这个类别指那一个姓的类别。那可不可以再懒一点呢,只写:miportjava.*;历史告诉我们,人可以懒,但不能太懒,这样是不行的。因为那些类别是姓java.io而不是姓java.就像姓「诸葛」的人应该不会喜欢你称他为I■诸」先生吧。为甚么我一开始说import跟存include不同呢?因为import的功能到此为止,它不像^include一样,会将档案内容载入进来。import只是请编译器帮你打字,让编译器把没有姓的类别加上姓,并不会把别的文件的程式码写进来。如果你想练习打字,可以不要使用unpoit,只要在用到类别的时候,用它的全部姓名来称呼它就行了(就像例子一开始那样),跟使用import完全没有甚么两样。另外,虽然人不可以太懒,但是Sun还是帮我们多偷了一点懒。因为java.lang这个套件实在是太常太常太常用到了,几乎没有程序不用它的,所以不管你有没有写impoitjava.laiig;,编译器都会自动帮你补上,也就是说编译器只要看到没有姓的类别,它就会自动去java.lang里面找找看,看这个类别是不是属于这个套件的。所以我们就不用特别去unportjava.langTojava中的String问题大剖析String是一个对象因为对彖的默认值是null,所以Strmg的默认值也是null:但它又是一种特殊的对彖,有其它对象没有的一些特性。首先Strmg不属于8种基本数据类型(byte,chai;short,int,float,long,double,boolean)newStimgO和newStimg(“”)都是申明一个新的空字符串,是空串不是null:StniigstKIcvil严Stringstr=newString(“kvill”);的区别:在这里,我们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念。常量池(constantpool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包松字符串常量。例1:[java]viewplaincopvprmt?privatestaticvoidtestOl(){StrmgsO=忖11”;Strmgsi=忖11”;Strmgs2=+Ull”;System,out.piiiitlii(sO=si); //tmeSystem,out.piiiitlii(sO=s2); //tme}结果为:tnie合肥达内总结的几大点合肥达内总结的几大点Java知识,供学习IT的人参考文章出门:文章出门:http:〃具体详惜可以百度“合肥达内合肥达内总结的几大点合肥达内总结的几大点Java知识,供学习IT的人参考文章出门:文章出门: 具体详悄可以百度“合肥达内”合肥达内总结的几大点合肥达内总结的几大点Java知识,供学习IT的人参考文章出白:文章出白:http:具体详情可以百度"合肥达内”true首先,我们要知道Jaw会确保一个字符串常量只有一个拷贝。因为例子中的sO和si中的”kvill”都是字符串常量,它们在编译期就被确定了,所以sO==sl为true:而”kv”和”山”也都是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s2也同样在编译期就被解析为一个字符串常量,所以s2也是常量池中”kvill”的一个引用。所以我们得出s0==sl==s2;用newStrmg()创建的字符串不是常量,不能在编译期就确定,所以newStrmgQ创建的字符串不放入常量池中,它们有自己的地址空间。例2:[java]viewplaincopypriiit?privatestaticvoidtestO2(){StrmgsO="kvill”;Stringsi=newStiing("kvill");Strmgs2=”kv”+newStnng("ill”);System.out.pimtlii(sO==sl);//falseSystem.out.pimtlii(sO==s2);//falseSystem.out.pimtlii(s1==s2);//false}结果为:falsefalsefalse例2中sO还是常量池中”kvill”的应用,si因为无法在编译期确定,所以是运行时创建的新对象”kvill”的引用,s2因为有后半部分newStnng(“ill”)所以也无法在编译期确定,所以也是一个新创建对象”kvill”的应用;明白了这些也就知道为何得出此结果了。Sern()再补充介绍一点:存在T.class文件中的常量池,在运行期被JVM装载,并且可以扩充oStrmg的intem()方法就是扩充常量池的一个方法;当一个String实例str调用intem()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一

个Unicode等于str的字符串并返回它的引用;看例3就清楚了例3:[java]viewplaincopvprmt?privatestaticvoidtestO3(){StrmgsO=Hkxair,;Stringsi=newStnng(,,k\Tiir,);Strings2=newStnng(,,k\Tiir,);//false//false//true//false//false//true//trues2=s2.iiitern();System,out.piiiitlii(sO==si);System,out.piiiitlii(sO==sl.mtern());System,out.piiiitlii(sO==s2);}结果为:falsefalse//虽然执行了ernQ,但它的返回值没有赋给sitme〃说明sl.mternO返回的是常量池中”kvill”的引用true最后我再破除一个错误的理解:有人说,"使用Sem()方法则可以将一个String类保存到一个全局String表中,如果具有相同值的Umcode字符串已经在这个表中,那么该方法返回表中已有字符串的地址,如果在表中没有相同值的字符串,则将自己的地址注册到表中“如果我把他说的这个全局的Strmg表理解为常量池的话,他的最后一句话,“如果在表中没有相同值的字符串,则将自己的地址注册到表中”是错的:例4:[java]viewplaincopypriiit?privatestaticvoidtest04(){Stringsi=newStnng(,,k\Tiir,);Strings2=sl.iiiternO;Strmgs3=忖11”;

//false//kvillkvill//true//true//false//kvillkvill//true//trueSystem.out.piiiitlii(s1+""+s2);System.out.prmtlii(s2==sl.mteniQ);System.out.prmtlii(s2==s3);}结果:falsekvillkxdll在这个类中我们没有声明一个”kvill”常量,所以常量池中一开始是没有”kvill”的,当我们调用sl.mternO^就在常量池中新添加了一个”kvill”常量,原来的不在常量池中的”kvill”仍然存在,也就不是“将自己的地址注册到常量池中"了。sl==sl.m

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论