飘灵儿 发表于 2015-1-18 11:43:01

JAVA网页设计深切剖析java中类的机关

其实产生见解的过程就是训练自己发现问题,分析问题的能力。根据以上的认识我想谈下传统的学习与通过视频独立学习的优缺点:提要:本文经由过程检察一个经心机关的类布局的运转输入和利用javap工具检察实践天生的java字节码(bytecode)向java程序员展现了一个类在运转时是怎样机关天生的。

  关头字:java机关javap字节码bytecode

  依照java标准,一个类实例的机关历程是遵守以下按次的:

  1.假如机关办法(constructor,也有翻译为机关器和机关函数的)是有参数的则举行参数绑定。

  2.内存分派将非静态成员付与初始值(原始范例的成员的值为划定值,比方int型为0,float型为0.0f,boolean型为false;对象范例的初始值为null),静态成员是属于类对象而非类实例,以是类实例的天生不举行静态成员的机关大概初始化,前面将报告静态成员的天生工夫。

  3.假如机关办法中存在this()挪用(能够是别的带参数的this()挪用)则实行之,实行终了落后进第6步持续实行,假如没有this挪用则举行下一步。

  4.实行显式的super()挪用(能够是别的带参数的super()挪用)大概隐式的super()挪用(缺省机关办法),此步骤又进进一个父类的机关历程并一向上推至Object对象的机关。

  5.实行类声名中的成员赋值和初始化块。

  6.实行机关办法中的别的语句。

  如今来看看经心机关的一个实例:


  classParent
  {
  intpm1;
  intpm2=10;
  intpm3=pmethod();
  {
  System.out.println("Parentsinstanceinitializeblock");
  }
  publicstaticintspm1=10;
  static
  {
  System.out.println("Parentsstaticinitializeblock");
  }
  
  Parent()
  {
  System.out.println("Parentsdefaultconstructor");
  }
  staticvoidstaticmethod()
  {
  System.out.println("Parentsstaticmethod");
  }


 intpmethod()
  {
  System.out.println("Parentsmethod");
  return3;
  }
  }

  classChildextendsParent
  {
  intcm1;
  intcm2=10;
  intcm3=cmethod();
  Otherco;
  publicstaticintscm1=10;
  {
  System.out.println("Childsinstanceinitializeblock");
  }
  static
  {
  System.out.println("Childsstaticinitializeblock");
  }
  
  Child()
  {
  co=newOther();
  System.out.println("Childsdefaultconstructor");
  }
  Child(intm)
  {
  this();
  cm1=m;
  System.out.println("Childsself-defineconstructor");
  }
  staticvoidstaticmethod()
  {
  System.out.println("Childsstaticmethod");
  }
  
  intcmethod()
  {
  System.out.println("Childsmethod");
  return3;
  }

  }

  classOther
  {
  intom1;
  Other(){
  System.out.println("Othersdefaultconstructor");
  }

  }
 publicclassInitializationTest
  {
  publicstaticvoidmain(Stringargs[])
  {
  Childc;
  System.out.println("programstart");
  System.out.println(Child.scm1);
  c=newChild(10);
  System.out.println("programend");
  }
  }





  进进此文件地点的目次,然后
  编译此文件:javacInitializationTest.java
  运转此程序:java?classpath.InitializationTest
  失掉的了局是:


  programstart
  Parentsstaticinitializeblock
  Childsstaticinitializeblock
  10
  Parentsmethod
  Parentsinstanceinitializeblock
  Parentsdefaultconstructor
  Childsmethod
  Childsinstanceinitializeblock
  Othersdefaultconstructor
  Childsdefaultconstructor
  Childsself-defineconstructor
  programend




  假如没有看过下面的关于类的机关的申明,很简单让人曲解为类的机关按次是以下的了局(疏忽参数绑定、内存分派和非静态成员的缺省值赋值):

  1.完成父类的非静态成员初始化赋值和实行初始化块(这个的前后按次取决于源文件中的誊写按次,能够将初始化块置于成员声明前,那末先实行的将是初始化块,将下面的代码稍稍变化一下就能够考证这一点。)

  2.挪用父类的机关办法完成父类机关。

  3.完成非静态成员的初始化赋值和实行初始化块。

  4.挪用机关办法完成对象的机关,实行机关办法体中的别的内容。

  假如依据以上java标准中给出的按次也能够公道的注释程序的输入了局,那末怎样亲眼看到是标准中的按次而不是以上依据程序的输入揣度的按次呢?
  上面就利用JDK自带的javap工具看看实践的按次,这个工具是一个依据编译后的字节码天生一份字节码的助记符格局的文档的工具,就像依据呆板码天生汇编代码那样。


反编译:javap-c-classpath.Child
  输入的了局是(已经由标志,瓜代利用黑体和斜体暗示要解说的每块):


  CompiledfromInitializationTest.java
  classChildextendsParent{
  intcm1;
  intcm2;
  intcm3;
  Otherco;
  publicstaticintscm1;
  static{};
  Child();
  Child(int);
  intcmethod();
  staticvoidstaticmethod();
  }

  Methodstatic{}
  0bipush10
  2putstatic#22<Fieldintscm1>
  5getstatic#20<Fieldjava.io.PrintStreamout>
  8ldc#5<String"Childsstaticinitializeblock">
  10invokevirtual#21<Methodvoidprintln(java.lang.String)>
  13return

  MethodChild()
  0aload_0
  1invokespecial#14<MethodParent()>
  4aload_0
  5bipush10
  7putfield#16<Fieldintcm2>
  10aload_0
  11aload_0
  12invokevirtual#18<Methodintcmethod()>
  15putfield#17<Fieldintcm3>
  18getstatic#20<Fieldjava.io.PrintStreamout>
  21ldc#2<String"Childsinstanceinitializeblock">
  23invokevirtual#21<Methodvoidprintln(java.lang.String)>
  26aload_0
  27new#8<ClassOther>
  30dup
  31invokespecial#13<MethodOther()>
  34putfield#19<FieldOtherco>
  37getstatic#20<Fieldjava.io.PrintStreamout>
  40ldc#1<String"Childsdefaultconstructor">
  42invokevirtual#21<Methodvoidprintln(java.lang.String)>
  45return

  MethodChild(int)
  0aload_0
  1invokespecial#12<MethodChild()>
  4aload_0
  5iload_1


6putfield#15<Fieldintcm1>
  9getstatic#20<Fieldjava.io.PrintStreamout>
  12ldc#4<String"Childsself-defineconstructor">
  14invokevirtual#21<Methodvoidprintln(java.lang.String)>
  17return

  Methodintcmethod()
  0getstatic#20<Fieldjava.io.PrintStreamout>
  3ldc#3<String"Childsmethod">
  5invokevirtual#21<Methodvoidprintln(java.lang.String)>
  8iconst_3
  9ireturn

  Methodvoidstaticmethod()
  0getstatic#20<Fieldjava.io.PrintStreamout>
  3ldc#6<String"Childsstaticmethod">
  5invokevirtual#21<Methodvoidprintln(java.lang.String)>
  8return





  请细心扫瞄一下这个输入并和源代码对照一下。

  上面注释怎样依据这个输入失掉类实例的实践的机关按次,在入手下手申明前先注释一下输入的语句的格局,语句中最后面的一个数字是指令的偏移值,这个我们在此能够不论,第二项是指令助记符,能够从字面上大抵看出指令的意义。

  比方getstatic指令将一个静态成员压进一个称为操纵数仓库(后续的指令就能够援用这个数据布局中的成员)的数据布局,而invokevirtual指令是挪用java假造机办法,第三项是操纵数(#号前面跟一个数字,实践上是类的成员的标志),有些指令没有这一项,由于有些指令好像汇编指令中的某些指令一样是不必要操纵数的(多是操纵数是隐含的大概基本就不必要),这是java中的一个特征。

  假如你间接反省字节码,你会看到成员信息没有间接嵌进指令而是像一切由java类利用的常量那样存储在一个共享池中,将成员信息存储在一个常量池中能够减小字节码指令的巨细,由于指令只必要存储常量池中的一个索引而不是全部常量。

  必要申明的是常量池中的项目标按次是和编译器相干的,因而在你的情况中看到的大概和我下面给出的输入不完整一样,第四项是对后面的操纵数的申明,实践的字节码中也是没有的,依据这个你能很分明的失掉实践上利用的是哪一个成员大概挪用的是哪一个办法,这也是javap为我们供应的便当。

  说完下面这些你如今应当很简单看懂下面的了局和上面将要叙说的内容了。别的更进一步的有关java字节码的信息请本人查找材料。

  先看看最入手下手的部分,很像一个尺度的c++类的声明,的确云云。成员声明的前面没有了成员初始化赋值语句和初始化块,那末这些语句什么时候实行的呢?先不要急,持续往下看。

  第二块,是一个Methodstatic{},对照看看第一部分,它被处置为一个静态的办法(夙昔面的Method能够看出),这就是源代码中的静态初始化块,从前面的语句能够看出它实行的就是System.out.println("Childsstaticinitializeblock")语句,因为这个办法是没无方法名的,以是它不克不及被显式的挪用,它在那边挪用前面会有叙说。
第三块,缺省机关办法的完成,这是本文的重点,上面具体解说。因为源代码中的缺省机关办法没有显式挪用this办法,因而没有this挪用(对照看看下一块的有参的机关办法的前两句),同时也没有显式的super挪用,那末隐式挪用父类的缺省机关办法,也就是前两条语句(次要是语句invokespecial#14<MethodParent()>),它挪用父类的机关办法,和这个类的机关类似(你可使用javap?c?classpath.Parent反编译父类的字节码看看这个类的机关历程);紧接着的是实行源代码中的第一条初始化赋值语句cm2=10(即接上去的三条语句,次要是bipush10和putfield#15<Fieldintcm2>,此处回覆了第一块中的疑问,即初始化赋值语句到哪儿往了。);接上去是实行cm3=cmethod()(接上去的四条语句);然后是实行初始化块中的内容System.out.println("Childsinstanceinitializeblock")(接上去的三条语句);java标准外部商定的内容至此实行终了,入手下手实行机关办法的办法体中的内容,即co=newOther()(接上去的五条语句)和System.out.println("Childsdefaultconstructor")(接上去的三条语句),最初办法实行终了前往(最初一条语句return)。

  剩下的几块信任应当不必注释了吧,有参机关办法挪用无参机关办法然后实行本人的办法体,成员办法cmethod实行一条打印语句然后前往一个常量3,静态办法staticmethod实行一条打印语句。

  别的必要申明一下的是你能够将有参机关办法中的this挪用往失落,然后看看反编译的了局,你会发明两个机关办法十分的相似,假如你将两个机关办法的内容改成一样的,那末反编译后的天生也将是一样的。从这个能够申明本文入手下手的机关按次的申明中机关办法中this挪用的判别是在编译阶段就完成的,而不是在运转阶段(申明中的意义仿佛是这个判别是在运转时举行的)。

  对机关历程的另外一个细节你大概还不信任,就是按次中的第二条关于非静态成员的付与缺省初始值(内存分派部分没法考据,这是java假造机主动完成的),这个你能够经由过程在子类Child的cmethod办法的最入手下手用System.out.println(cm3)打印cm3的值(输入为0,别的范例成员的值能够经由过程相似的办法失掉)。

  上面来说解另外一个还没有办理的成绩:静态成员初始化和静态初始化块的实行是在什么时候完成的?这个能够经由过程一个小小的实验揣度失掉:是在第一次利用该类对象时举行的(注重是类对象而不是类实例,关于类的私有静态成员能够间接经由过程类名举行会见,其实不必要天生一个类实例,这就是一次类对象的利用而非类实例的利用,假如在天生第一个类实例前没有利用过该类对象,那末在机关第一个类实例前先完成类对象的机关(即完成静态成员初始化和实行静态初始化块),然后再实行以上类实例的机关历程),实验的步骤以下:

  1.修正main办法,将个中的System.out.println(Child.scm1)和c=newChild(10)都正文失落(不要删除,前面还必要用到这两个语句),编译运转程序,输入将只要programstart和programend,这申明没有利用类对象也没有天生类实例时不举行静态成员的机关。

  2.将System.out.println(Child.scm1)的正文作废,编译运转后输入多了父类和子类的静态初始化块部分的实行输入(利用子类的类对象将招致天生父类的类对象,父类先于子类机关)。

  3.将System.out.println(Child.scm1)正文失落并作废c=newChild(10)的正文,编译运转后输入只比最入手下手没有正文任何语句时少了一条(输入Child.scm1的值10)

  从以上的实验中我们能够失掉后面的结论。
  本文至此能够说停止了,因为自己的java功底其实不很踏实,java标准看得也不完全,因而文中大概有毛病,假如您以为某些中央有毛病的话,接待经由过程mail接洽。

但是对于JAVA技术类的学习,我觉得大课堂反而会影响自身独立思考的过程,因为上课的时候,老师讲课的速度很快为了不遗漏要点,通常会仔细的听,

精灵巫婆 发表于 2015-1-21 13:05:16

是一种使网页(Web Page)由静态(Static)转变为动态(Dynamic)的语言

仓酷云 发表于 2015-2-1 11:20:30

Java是一个纯的面向对象的程序设计语言,它继承了 C++语言面向对象技术的核心。Java舍弃了C ++语言中容易引起错误的指针(以引用取代)、运算符重载(operator overloading)

蒙在股里 发表于 2015-2-5 08:15:13

Sun公司看见Oak在互联网上应用的前景,于是改造了Oak,于1995年5月以Java的名称正式发布。Java伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。

柔情似水 发表于 2015-2-5 15:03:52

所以现在应用最广泛又最好学的就是J2EE了。 J2EE又包括许多组件,如Jsp,Servlet,JavaBean,EJB,JDBC,JavaMail等。要学习起来可不是一两天的事。那么又该如何学习J2EE呢?当然Java语法得先看一看的,I/O包,Util包,Lang包你都熟悉了吗?然后再从JSP学起。

老尸 发表于 2015-2-11 19:54:29

是一种简化的C++语言 是一种安全的语言,具有阻绝计算机病毒传输的功能

第二个灵魂 发表于 2015-2-14 01:57:02

Sun公司看见Oak在互联网上应用的前景,于是改造了Oak,于1995年5月以Java的名称正式发布。Java伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。

只想知道 发表于 2015-3-4 03:58:09

Java 不同于一般的编译执行计算机语言和解释执行计算机语言。它首先将源代码编译成二进制字节码(bytecode),然后依赖各种不同平台上的虚拟机来解释执行字节码。从而实现了“一次编译、到处执行”的跨平台特性。

变相怪杰 发表于 2015-3-11 16:10:39

http://www.jdon.com/去下载,或到同济技术论坛的服务器ftp://nro.shtdu.edu.cn去下,安装上有什么问题,可以到论坛上去提问。

乐观 发表于 2015-3-13 06:10:30

http://www.jdon.com/去下载,或到同济技术论坛的服务器ftp://nro.shtdu.edu.cn去下,安装上有什么问题,可以到论坛上去提问。

海妖 发表于 2015-3-20 14:44:37

科学超级计算机、移动电话和互联网,同时拥有全球最大的开发者专业社群。

灵魂腐蚀 发表于 2015-3-20 20:50:20

Java自面世后就非常流行,发展迅速,对C++语言形成了有力冲击。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于个人PC、数据中心、游戏控制台

飘灵儿 发表于 2015-3-24 02:26:18

是一种由美国SUN计算机公司(Sun Microsystems, Inc.)所研究而成的语言

若相依 发表于 2015-4-1 17:12:08

任职于太阳微系统的詹姆斯·高斯林等人于1990年代初开发Java语言的雏形,最初被命名为Oak,目标设置在家用电器等小型系统的程序语言

再见西城 发表于 2015-4-7 10:32:04

至于JDBC,就不用我多说了,你如果用java编过存取数据库的程序,就应该很熟悉。还有,如果你要用Java编发送电子邮件的程序,你就得看看Javamail 了。

谁可相欹 发表于 2015-4-8 14:30:00

设计模式是高级程序员真正掌握面向对象核心思想的必修课。设计模式并不是一种具体"技术",它讲述的是思想,它不仅仅展示了接口或抽象类在实际案例中的灵活应用和智慧

分手快乐 发表于 2015-4-10 06:47:17

如果要向java web方向发展也要吧看看《Java web从入门到精通》学完再到《Struts2.0入门到精通》这样你差不多就把代码给学完了。有兴趣可以看一些设计模块和框架的包等等。

小魔女 发表于 2015-4-10 19:11:28

是一种突破用户端机器环境和CPU

山那边是海 发表于 2015-6-11 17:51:42

Jive的资料在很多网站上都有,大家可以找来研究一下。相信你读完代码后,会有脱胎换骨的感觉。遗憾的是Jive从2.5以后就不再无条件的开放源代码,同时有licence限制。不过幸好还有中国一流的Java程序员关注它,外国人不开源了,中国人就不能开源吗?这里向大家推荐一个汉化的Jive版本—J道。Jive(J道版)是由中国Java界大名 鼎鼎的banq在Jive 2.1版本基础上改编而成, 全中文,增加了一些实用功能,如贴图,用户头像和用户资料查询等,而且有一个开发团队在不断升级。你可以访问banq的网站
页: [1]
查看完整版本: JAVA网页设计深切剖析java中类的机关