怎么看网站蜘蛛,网站模板开发平台怎么做,建设部办公厅网站,内容营销的定义Java语言有什么特点#xff1f;如何最大效率的学习#xff1f;深浅拷贝到底有何区别#xff1f;阿里巴巴高级开发工程师为大家带来Java系统解读#xff0c;带你掌握Java技术要领#xff0c;突破重点难点#xff0c;入门面向对象编程#xff0c;以详细示例带领大家Java基…Java语言有什么特点如何最大效率的学习深浅拷贝到底有何区别阿里巴巴高级开发工程师为大家带来Java系统解读带你掌握Java技术要领突破重点难点入门面向对象编程以详细示例带领大家Java基础入门
在学习JAVA编程的同学们可以加我们的学习交流
QQ群370161306群内有相关学习资料
邢凯航花名弗止阿里巴巴Java高级开发工程师香港大学计算机科学硕士16年加入阿里巴巴目前就职于研发效能事业部用户声音及代码智能化团队负责代码中心后端开发。
以下内容根据演讲嘉宾视频分享以及PPT整理而成。
本文将围绕一下几个方面进行介绍
1.Java语言特点
2.如何学习Java
3.JVM概述
4.面向对象入门
5.示例演示
6.扩展阅读
一. Java语言特点
1.Java是一种面向对象的语言以对象为颗粒度对象中包含属性和方法通过对象间的继承和组合构建程序世界。在学习面向对象语言时大家不仅仅应该关注过程还需要对待解决的问题进行抽象和建模最终生成易于维护和扩展的设计方案。这是一个由浅入深、循序渐进的过程。 其次Java具有良好的跨平台特性。Java程序可以不受计算机硬件和操作系统的约束在任何支持Java虚拟机JVM的环境下都可以正常运行。编写的Java程序经过编译后生成的字节码可以被JVM识别JVM为程序运行屏蔽了底层操作系统的差异。 第三个特点是Java具有垃圾回收机制简称GCGarbage Collection。在Java中不需要关心内存空间的回收问题这一切都会交给JVM进行处理。JVM会识别出哪些对象不需要再次被使用进而自动回收其内存空间不需要手动回收大大提高了开发效率。 第四个特性是Java为单根结构。Java中所有的类都继承成自同一个基础类object如此所有类具有同一个通用接口并且在层次结构上都属于同一类型这为编程提供了极大的便利。 另外Java在设计之初就非常注重安全性在多个阶段均提供了安全保证。Java中不支持指针避免了非法内存的操作。在编译运行时提供了多重语法、类型、边界和字节码的检查。 最后Java语言是解释型的语言。Java编译的结果并不会在操作系统上运行而是生成一个中间class文件被JVM加载并解释执行。早期的Java版本因为解释过程运行速度相比C要慢很多但随着Java编译器的优化某些结果甚至已经表明Java会比C运行更快因此如今并没有统一的定论。
二. 如何学习Java
首先Java的学习有两条主线——Java语言和JVM。一方面大家需要学习Java语言编程的语法规则能够熟练使用JDK提供的常用的工具类并通过多线程解决问题。此外还需要熟练掌握一至两个框架快速上手工程的开发。另一方面大家需要了解JVM底层了解Java内部的运行机制。
其次关于工具的选择这里推荐大家使用在业界比较流行的IntelliJ IDEA或Eclipse。一个好的编程工具会提供很多优秀的能力提升开发效率。
第三点建议大家使用较新的JDK版本例如JDK8及以上。JDK在更新过程中会出现一些优秀的类库以及新的语法规则及时更新版本有助于跟上业界新步伐。最后尤为重要的是需要多看、多思考、多实践。多看一些优秀的源码和工程例如JDK源码可以了解好的编码习惯和风格并且通过熟悉底层的原理有助于写出高性能和健壮的程序再例如Tomcat源码阿里Dubbo源码等从中学习软件设计思维。最后还需要多练习实践。
三. JVM概述
1.Java内存区域管理
Java内存区域包括两部分由所有线程共享的数据区和线程隔离的数据区如图所示 在线程隔离的数据区中包括虚拟机栈、本地方法栈和程序计数器。程序计数器可以指示当前线程所执行的字节码的行号字节码解释器会通过更改计数器的值来选取下一条需要执行的字节码指令。每个线程的程序计数器都是独立的确保各线程间计数器互不影响。虚拟机栈也是线程私有的生命周期和线程相同每个方法执行时会创建一个栈针、当前执行方法的局部变量表、操作数、动态链接、方法出口等信息都存储在该区域中。方法的调用和返回对应的栈针在虚拟机栈中的入栈和出栈操作中。本地方法栈的作用与虚拟机栈类似不过本地方法栈存储的是调用native方法时使用的数据结构。方法区是各个线程共享的内存区域它用于存储已被虚拟机加载的类信息、常量和静态变量等数据。堆也是共享内存区域存储对象实例、JVM的垃圾回收等。
2.垃圾回收
Java的垃圾回收机制中首先需要确定哪些对象需要进行垃圾回收这里通常采用可达性分析来进行判断。这个算法的基本思想是设置一系列对象作为起点称为GC Roots节点搜索建立引用链当一个对象到GC Roots没有任何引用链相连时则证明此对象是不可用的。在进行可达性分析时需要让整个系统冻结在某个时间点对外则表现为所有工作进程都停止如此才可以准确获取所有GC Roots这个过程称为stop the world。此外引用计数器算法也可以判断对象是否存活虽然该算法效率较高但如果存在对象间的循环引用即使这些对象不可访问也存在无法回收的情况。
在回收对象实例时有多种算法可供选择。第一种标记-清除算法分为两个阶段首先标记出所有需要回收的对象然后统一进行回收。第二种复制算法针对方法一中内存碎片过多的缺点复制算法将内存按照容量划分为大小相同的两块每次只使用其中的一块当一块用完后将仍存活的对象复制到另一块中然后将使用的那块空间一次性清理如此反复使用。第三种标记-整理算法针对方法二中内存利用率不高的缺点进行改进过程和方法一类似首先对对象进行标记然后将仍存活的对象向一端移动然后清理边界以外的内存区域。方法四分代收集算法将堆划分为新生代和老年代根据对象的生命周期分别放入不同的内存区域中同时针对不同垃圾回收特点的对象采用不同的回收策略。新生代分为一块较大的Eden区和两个较小的survival区因为新生代大部分对象都需要回收所以采用复制算法进行回收。而老年代中需要回收的对象较少因此采用标记-清除或者标记-整理算法进行回收。基于上述垃圾回收算法JVM实现了多个垃圾收集器可以通过一些参数进行设定具体内容可参考扩展阅读。
四. 面向对象入门
在Java语言中所有类都拥有一个共同的父类Object即便没有显式声明。接下来展示Object的一些方法如下图所示 首先它包含一个private方法refisterNatives()该方法与本地注册有关这里不做详细讨论。其次它包含notify()和notifyAll()方法这两种方法比较类似归并为一类另包含三种wait()方法也归为一类。因此Object类共包含8种方法分为以下四类进行讲解。 他们分别回答了四个问题我是谁我从哪里来我到哪里去我与外界如何互相作用的。getClass和hashCode分别让外界知晓当前对象的类型和一个独一无二的标识。equals告诉外界当前对象是否和另一个对象相等。toString用字符串标识当前对象信息。clone方法可以让外界获得当前对象的一个拷贝。finalize方法可以实现对象被回收前最后的清理工作。notify()和notifyAll()方法用于唤醒一个等待在该对象上的一个线程或所有线程。wait方法是让当前线程进入等待状态直至被唤醒或者等待时间结束。注意这里clone方法和finalize方法使用灰色表示因为二者都属于protected方法如果需使用则需要重写其实现。另外在重写clone还要注意深拷贝和浅拷贝的问题finalize方法使用时具有不确定性这里不推荐大家使用。
五. 示例演示
1.整体示例
在类Phone中定义了两个属性brand和serialNum代表品牌和序列号。在构造函数中为两个属性初始化值。同时实现了clone接口覆盖了父类实现。 在main函数中定义了phone1和phone2phone2是phone1的拷贝然后打印出两个变量的基本信息包括手机的类名称、hashCode、表示当前手机的字符串和对比两个手机是否相同。运行结果如下所示 由运行结果可见二者属于同一个类但hashCode不同并且字符串表示也不相同。接下来仔细介绍每个方法。hashCode方法为native表明调用的本地方法代码由非Java代码写出。hashCode返回一个int数值代表内存空间中的一个地址。 equals方法如下所示用双等号来对比两个对象注意因为此处两变量都为引用类型因此这里双等号对比的是二者引用的内存地址是否一致。上例中由打印出的hashCode可见二者内存地址不一致因此equals方法返回false。 toString方法中首先打印类名称加上还有内存地址空间的十六进制表示。 但某些情况下我们认为如果phone的品牌和序列号一致即为二者一致此时便需要尝试修改一些方法的实现。这里可以使用IDE工具自动生成generate的部分代码具体操作详见视频如下所示 此时在equals中首先比较二者的内存地址空间如果一致返回true若不一致则进一步比较二者的类信息若类不一致则返回false若一致则需要继续比较其属性值若属性值都一致则可以认为二者是相同的对象。hashCode中也类似使用其两个属性值生成hashCode。
类似的也可以生成toString的实现使用StringBuffer类来拼接字符串打印出相关属性值。此时再运行主函数得出结果如下
此时两个变量的hashCode值已经一致用字符串表示时也会打印出一些属性信息对比结果也返回true。
2.深浅拷贝示例
类Screen中包含属性值size表示屏幕大小。并且有getSize方法获取屏幕大小以及setSize方法设置size。toString方法将size值打印出来。
接着在上例Phone类中加入属性值Screen并且更新构造函数加入获取和更新屏幕的方法如下所示
重新编写main()函数。首先定义了大小为5的屏幕phone1和phone2与上例一致只是phone1新增了参数变量screen。分别打印出两个phone的屏幕大小然后更改screen的值再打印一次运行结果如下所示
由结果可见在更改screen大小之前两个phone的屏幕大小都为5更改完成后都变为6。这表明此处默认的clone方法实现的为浅拷贝。因为screen中存储的为内存地址空间拷贝后的对象存储的依然是该地址因此改变屏幕size时二者同时变化。下面展示深拷贝代码如图所示
首先从super.clone中获得phone变量为其重新设置屏幕大小设置的值为调用当前screen的clone方法最后返回变化后的拷贝。运行结果如下所示
此时可以看到在第二次更改完size之后只有phone1的屏幕大小变为6而phone2的屏幕大小仍然为之前的值。
在学习JAVA编程的同学们可以加我们的学习交流
QQ群370161306群内有相关学习资料