您的位置:首页 > 游戏 > 游戏 > 建站之星最新版本_东莞seo外包公司费用_宁波网络营销有哪些_专业做网站

建站之星最新版本_东莞seo外包公司费用_宁波网络营销有哪些_专业做网站

2025/1/6 12:14:03 来源:https://blog.csdn.net/weixin_52836217/article/details/144147471  浏览:    关键词:建站之星最新版本_东莞seo外包公司费用_宁波网络营销有哪些_专业做网站
建站之星最新版本_东莞seo外包公司费用_宁波网络营销有哪些_专业做网站

Java基础入门篇


三、面向对象和JVM底层分析

3.1 面向过程&面向对象

面向过程:代表是C语言,重点关注的是程序如何执行,适用于过程简单不需要协作的事务。

面向对象:代表是Java语言C++语言,重点关注的是如何设计这个事物,而不是按照什么步骤来执行,适用于需要协作的复杂事务。

举一个简单的例子来区分一下面向过程和面向对象:把大象装进冰箱,我们思考的是需要哪些步骤(打开冰箱,把大象放进冰箱,关上冰箱…)——面向过程。而当我们思考如何制造一辆汽车的时候,我们会去想汽车都包含哪些零部件(车轮,发动机,车门…),然后再去分别进行加工,最后制造出一辆汽车——面向对象。

面向对象可以帮助我们从宏观角度把握分析整个系统,但是从微观上看,面向对象本质上也是有一定的执行顺序一步一步执行的,因此仍然是面向过程。

如果从执行者与设计者来进行比喻的话,面向对象就是一种“设计者思维”,而面向过程则是一种“执行者思维”,这两种方法密切相关且不可分割。

    /**   构建一个类,并且创建一个对象*/public static class Stu{int id;int age;String name;public void study(){System.out.println("正在学习...");}public void kickball(){System.out.println("正在踢球...");}}

3.2 JVM内存分析

(一)简单内存分析

JVM是Java的虚拟机,也是Java程序实际运行的地方,在JVM的内存中分为三个部分分别是:栈区、堆区、方法区。

**栈区(Stack):**是存放执行方法的地方,例如main方法,

**堆区(Heap):**存放的是创建的对象

**方法区(Method Area):**存放的是类的信息,例如:属性、方法

(二 )创建对象的步骤

创建对象分为四步:1.分配对象空间,并将对象成员变量初始化为0或空、2.执行属性值的显示初始化、3.执行构造方法、4.返回对象的地址给相关的变量。

其中构造器的方法名必须和类名一致,通过new关键字调用,构造器虽然有返回值,但是不能定义返回值类型(即,不能在构造器中定义return)。如果没有定义构造器,则编译器会自动定义一个无参的构造方法,如果已定义则编译器不会自动添加。

/**   构造器练习*   定义一个点(Point)类,用来表示二维空间中的点,有两个坐标,要求:*   1.可以生成具有特定坐标的点对象*   2.提供可以设置坐标的方法*   3.提供可以计算该点距另外一点距离的方法*/public static class Point{double x;double y;// 定义一个空的构造器Point(){}// 重载构造器Point(double _x, double _y){this.x = _x;this.y = _y;}Point(double _x){this.x = _x;}public void distance(Point p){double dis = Math.sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y));System.out.println("两点间距离是:"+dis);}}public void testConstructor(){Point p1 = new Point(3.0, 4.0);Point p2 = new Point(0.0, 0.0);p1.distance(p2);}

在这里插入图片描述

(三)进阶内存分析

Java的虚拟机内存模型:由多份线程组成,每一个线程都有独立的(虚拟机栈、本地方法栈、程序计数器),“堆”中包括新生代和老年代(涉及垃圾回收),“方法区”(存放一些唯一的不变信息,例如类信息,常量池),“栈”描述的是方法执行的内存空间,每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)。
JVM为每一个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等),“栈”属于线程私有,不能实现线程间的共享,存储特性是后进先出。“栈”是由系统自动分配,速度快,同时栈是一个连续的内存空间
JVM中的“堆”用于存储创建好的对象和数组(数组也是对象),JVM只有一个堆,被所有线程共享。“堆”是一个不连续的内存空间,分配灵活,速度慢。“堆”被所有的线程所共享,在堆上的区域会被垃圾回收器做进一步划分,例如新生代、老年代的划分。
“方法区”本质上也是“堆”,是Java虚拟机的规范,可以有不同的实现,JDK7以前是“永久代”,JDK8是“元数据空间”和“堆”结合起来,去除“永久代”的静态变量、字符串常量池,挪到了堆内存中。“JVM”只有一个方法区,被所有线程共享,用于存储“类、常量等相关信息”,即用来存放程序中永远不变或者唯一的内容
“常量池”主要存放常量,例如文本字符串、final常量值。

(四)垃圾回收机制

Java中引入了垃圾回收机制,应对令C++程序员头疼的内存管理问题,所以说Java虽然“运行效率”不如C++,但是“开发效率”高于C++。Java的内存管理很大程度上就是指的:“堆中对象的管理”,包括对象空间的分配和释放(分配——new关键字,释放——将对象赋值null即可)
垃圾回收过程一般要做两件基本的事情:

  1. 发现无用的对象
  2. 回收无用对象占用的内存空间。

“无用的对象”指的是没有任何变量引用该对象,Java的垃圾回收器通过相关算法,发现无用对象,并进行清除和整理。垃圾回收相关算法:

  1. 引用计数法,

  2. 引用可达法(根据搜索算法)

“引用计数法”:堆中的每一个对象都对应一个引用计数器,当有引用指向这个对象时,引用计数器+1,而当指向该对象的引用失效时(引用变为null),引用计数器-1,如果最后该对象的引用计数器值=0,则Java垃圾回收器会判断该对象为无用对象,并对其进行垃圾回收
“引用可达法”:程序把所有的引用关系看作是一张图,从一个节点GC ROOT开始,寻找对应的引用节点,找到这个节点之后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点被认为是没有被引用到的无用节点
“引用计数法”的优点是算法简单,缺点是
循环引用
无用的对象则无法识别。
通用的
“分代”垃圾回收机制
,主要是指回收“堆”中的信息,堆包含三部分“年轻代”、“年老代”、“永久代”(本质上就是方法区,用于存放一些不变的内容,在JDK7以前存在,JDK8中永久代用元数据空间——metaspace和堆取代),一般垃圾回收指的是前两类。
“年轻代”包含三个部分(Eden、Survivor1区、Survivor2区)存储从未被垃圾回收的新对象的区域叫做“Eden区”,当Eden区存满了之后,会触发“Minor GC”(专门用来清理年轻代区域),清理无用对象(指的是清理整个年轻代的无用对象),然后将有用的对象复制到“Survivor1区”和“Survivor2区”,同时Suvivor1区和2区中存储的对象在经过Minor GC清理无用对象后,会循环复制存储内容。当年轻代Survivor中交换>15次后仍然存在的对象被认为是重要的,存储到“年老代”(Tenured区)中,年老代中的垃圾清理机制叫做“Major GC”,Minor GC相较于Major GC更加轻量,启动速度更快。
还有
Full GC(全量回收)
:用于清理年轻代、年老代、永久代,启动成本较高,会对系统性能产生影响。
年轻代Minor GC的目标是尽可能快速的手机掉生命周期短的对象,年老代中存放的是一些生命周期较长的对象,随着年老代中存储对象的增多,需要通过Major GC和Full GC来一次大扫除,全面清理整个堆区的三个部分。
JVM调优的过程中很大一部分工作就是对Full GC的调节,触发Full GC的原因“可能”是:

  1. 年老代(Tenured)被写满

  2. 永久代(Perm)被写满

  3. System.gc()被显示调用

  4. 上一次GC之后堆(Heap)的各域分配策略动态变化

/**   循环引用示例
*/public class GarbageCollection{int id;GarbageCollection friend;public void testGarbage(){/**   创建两个对象,同时进行相互的循环引用,当两个对象的引用赋值为null之后,由于存在相互引用导致引用计数器为1≠0,*   因此无法被识别为无用对象,但是实际上已经无用了*/GarbageCollection g1 = new GarbageCollection();GarbageCollection g2 = new GarbageCollection();g1.friend = g2;g2.friend = g1;g1 = null;g2 = null;}}

3.3 面向对象中的this关键字和static关键字

(一)this关键字

this关键字表示当前对象本身(当前对象的引用地址)。“普通方法”中的this总是指向调用该方法的对象,“构造方法”中的this总是指向正要初始化的对象(注意,构造函数中不写this,默认也是带有this的)。this()调用重载的构造方法,避免相同的初始化代码,但是只能在构造方法中用,并且必须位于构造方法的第一句。this方法不能用于static方法中。普通方法的this是一种隐式参数,由系统自动传递。

    /**   测试this方法*/public static class TestThis{int a, b, c;TestThis(){System.out.println("当前初始化对象: " + this);}TestThis(int a, int b){// 调用构造方法不能通过TestThis();的方法,而是要通过下面的this();的方法this();  // 调用无参的构造方法,并且必须位于第一行a = a; // 这里是局部变量而不是成员变量this.a = a;this.b = b; // 通过使用this区分成员变量和局部变量}TestThis(int a, int b, int c){this(a, b);  // 调用有参的构造方法,并且必须位于第一行a = a; // 这里是局部变量而不是成员变量this.c = c;}void sing(){System.out.println("当前 "+ this + " 正在唱歌~");}void eat(){System.out.println("当前对象: " + this);this.sing();System.out.println("快回家吃饭吧!");}}public static void testThis(){TestThis t1 = new TestThis(2, 3);t1.eat();}

在这里插入图片描述

(二)static关键字

static关键字,由static关键字定义的属性和方法都属于类位于方法区中,而普通对象的属性和方法都位于堆中,类只被加载一次,也只有一份。静态的变量/方法的生命周期和类相同,在整个程序执行期间都有效静态的变量/方法为该类的公用变量,属于类,被该类的所有实例共享,在类载入时被初始化static成员变量只有一份,但是可以有多个变量共同访问同一个static变量。一般用“类名.类的属性/方法”来进行调用。在static方法中不可以直接访问非static的成员。构造方法用于初始化普通属性,静态初始化块用来初始化静态属性,注意静态初始化块中不能直接访问非静态成员。

静态初始化块的执行顺序(结合继承进行理解):上述依次找父类,直到Object类,先执行Object的静态初始化块,再向下执行子类的静态初始化块,直到类的静态初始化块为止(构造方法的执行顺序同理)
变量的分类:局部变量(属于方法/语句块——位于栈)、成员变量(属于对象——位于堆)、静态变量(属于类——位于方法区)

  /**   测试static方法*/public static class TestStatic{int id;String name;static String company;// 定一个静态初始化块初始化静态属性static{company = "北京同仁堂";getCompany(); // 静态初始化块中也可以调用静态方法}TestStatic(){System.out.println(this + "欢迎使用");}TestStatic(int a, String b){this.id = a;this.name = b;}public void test01(){System.out.println("test01");}public static void getCompany(){//静态方法中无法使用非静态方法,因为,静态的方法属于类,非静态方法属于对象,直接使用无法知道是属于哪一个对象的方法// test01();// System.out.println(id);System.out.println(company);}}public static void testStatic(){TestStatic t1 = new TestStatic(1001, "小明");t1.company = "石家庄石药集团";t1.getCompany();}

在这里插入图片描述

(三)包的导入

import导入类,可以在本类中使用其他包的类。Java会默认导入java.lang包下的所有类,例如String,依次这些类我们可以直接使用。如果有两个同名的类,则只能用包名+类名来显示调用相关类。使用.*会导入该包下的所有类,会降低编译速度,但是不会降低运行速度import static静态导入作用是用于导入指定类下的静态属性和静态方法,这样我们可以直接使用静态的属性/方法。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com