【Java JVM】实例对象的创建
当我们涉及 Java 编程时, 对象的创建是一个基础而关键的概念。在 Java 中, 一切皆为对象, 而对象的创建方式直接影响代码的结构和性能。
本博客将探讨一下 Java 实例对象的创建过程。
1 创建对象的方法有哪些
在 Java 中如果要创建一个对象, 有哪些方式呢?
- 运用 new 关键字创建实例, 这是最常用的创建对象方法
- 通过反射, 调用 java.lang.Class 的 newInstance 方法, 相当于调用一个类的无参的构造函数创建对象
- 通过反射, 调用 java.lang.reflect.Constructor 类的 newInstance 方法, 支持无参/有参/私有的构造函数
- 通过对象的 clone 方法, 对象需要实现 java.lang.Cloneable 接口
- 通过反序列化, 对象需要实现 java.io.Serializable
- 通过 sun.misc.Unsafe 的 allocateInstance 方法
其中方法 1, 2, 3 本质都是通过类的构造函数创建对象, 就是 Java 的 new 机制。
而方法 4, 5, 6 不会调用构造函数。我们这里只讨论正常的构造函数创建对象的方式。
2 创建的过程
public class Demo {public static void main(String[] args) {Demo main = new Demo();}
}
上面是一个逻辑很简单, 就是通过 new 创建出了一个 Demo 的实例。
从 Java 层面这个对象的创建就完成了, 如何还需要进行深入分析的话, 我们需要进入到字节码的层面了。
对应如何将类文件转为字节码, 可以看一下后面的附录 1。
上面的 Demo 例子转为字节码后如下
Classfile /Users/lcn29/Projects/Demo/src/main/java/io/github/lcn29/Demo.classLast modified xxxx年xx月xx日; size 286 bytesSHA-256 checksum de9e200e3a5848520480df67e259986c46dca7342bbaf8f1b84b094815e04ee5Compiled from "Demo.java"
public class io.github.lcn29.Demominor version: 0major version: 65flags: (0x0021) ACC_PUBLIC, ACC_SUPERthis_class: #7 // io/github/lcn29/Demosuper_class: #2 // java/lang/Objectinterfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:#1 = Methodref #2.#3 // java/lang/Object."<init>":()V#2 = Class #4 // java/lang/Object#3 = NameAndType #5:#6 // "<init>":()V#4 = Utf8 java/lang/Object#5 = Utf8 <init>#6 = Utf8 ()V#7 = Class #8 // io/github/lcn29/Demo#8 = Utf8 io/github/lcn29/Demo#9 = Methodref #7.#3 // io/github/lcn29/Demo."<init>":()V#10 = Utf8 Code#11 = Utf8 LineNumberTable#12 = Utf8 main#13 = Utf8 ([Ljava/lang/String;)V#14 = Utf8 SourceFile#15 = Utf8 Demo.java
{public io.github.lcn29.Demo();descriptor: ()Vflags: (0x0001) ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 3: 0public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: (0x0009) ACC_PUBLIC, ACC_STATICCode:stack=2, locals=2, args_size=10: new #7 // class io/github/lcn29/Demo3: dup4: invokespecial #9 // Method "<init>":()V7: astore_18: returnLineNumberTable:line 6: 0line 7: 8
}
SourceFile: "Demo.java"
备注:
从上面的字节码内容中可以看到很多注释的内容 (// 后面的内容), 在实际的字节码中是不会有后面的注释内容的, 只有一个简单的 指令 #参数 (也可能没这个参数)。
后面注释的内容是 javap 为了方便我们阅读, 提前帮我们把 #参数 的内容转换了, 即后面注释的内容就是 #参数 的真正内容。
#参数 的真正内容如何查找的?
这里的 #参数 可以看作是一个坐标, 通过这个指标可以到字节码文件的常量池中获取对应的内容, 即字节码文件中的 Constant pool 项。
比如: #7 在我们的字节码文件的 Constant pool 从中找到的内容是 #8, 同理通过 #8 在 Constant pool 中最终获取到了内容 io/github/lcn29/Demo, 也就是 #7 的内容就是 io/github/lcn29/Demo
OK, 转为字节码后, 我们可以看到 JVM 创建对象的更多步骤。
下面我们就围绕这个字节码过程, 简单梳理一下 JVM 层面创建对象的过程。
2.1 检查类的加载
从 main 方法入手, 我们遇到的第一个字节码
new #7 // class io/github/lcn29/Demo
JVM 虚拟机遇到一条 new 指令时, 首先会去检查这个指令的后面参数是否能在运行时常量池中定位到一个类的符号引用, 并且检查这个符号引用代表的类是否已被加载, 解析和初始化过。
如果没有, 那必须先执行相应的类加载过程。
类加载 的过程就不在这里展开了。
所以 new 的是 io/github/lcn29/Demo 这个类, 所以首先需要确保在内存中有这个类存在。
2.2 分配内存
在类加载检查通过后, 接下来虚拟机将为新生对象分配内存。
一个对象需要分配内存的就 3 个部分
- 对象头 (Object Header) 的大小固定的
- 实例数据 (Instance Data) 的大小可以通过类的各个属性的大小计算出来
- 对齐填充 (Padding) 只需要在得到前 2 个的大小后, 保证整个对象为 8 个字节的倍数即可
所以一个对象所需内存的大小在类加载完成后便可完全确定, 这时就可以给这个对象分配内存空间。
这个过程实际就是把一块确定大小的内存从 Java 堆中划分出来。
2.2.1 内存分配方式
方式一
如果 Java 堆中内存是绝对规整的, 所有用过的内存都放在一边, 空闲的内存放在另一边, 中间放着一个指针作为分界点的指示器, 那所分配内存就仅仅是把那个指针向空闲空间那边挪动一段与对象大小相等的距离, 这种分配方式称为 “指针碰撞 (Bump the Pointer)”
方式二
如果 Java 堆中的内存并不是规整的, 已使用的内存和空闲的内存相互交错, 那就没有办法简单地进行指针碰撞了, 虚拟机就必须维护一个列表, 记录哪些内存块是可用的, 在分配的时候从列表中找到一块足够大的空间划分给对象实例, 并更新列表上的记录, 这种分配方式称为 “空闲列表 (Free List)”
至于选择哪种分配方式由 Java 堆是否规整决定。
而 Java 堆是否规整又由所采用的垃圾收集器是否带有空间压缩整理 (Compact) 功能决定。
Serial, ParNew 等带压缩整理过程的收集器就使用指针碰撞, 基于 CMS 这种清除算法就使用空闲列表
2.2.2 内存分配的安全问题
对象的创建需要申请内存, 这个过程不是线程安全的。
如果现在正在给对象 A 分配内存, 临界指针/空闲列表的值还未改变, 这时候又要一个对象 B 进行
内存的申请, 那么就导致线程不安全。
为了解决这个问题, 有 2 种方式
- 对分配内存空间的动作进行同步处理, 虚拟机是可以通过 CAS 加上失败重试的方式保证更新操作的原子性
- 把内存分配的动作按照线程划分在不同的空间之中进行, 每个线程在 Java 堆中预先分配一小块内存, 称为本地线程分配缓冲 (Thread Local Allocation Buffer, TLAB), 哪个线程要分配内存, 就在哪个线程的本地缓冲区中分配, 只有本地缓冲区用完了, 分配新的缓存区时才需要同步锁定。
2.3 空间初始化
内存分配完成后, 虚拟机需要将分配到的内存空间都初始化为默认值 (不包括对象头), 如果使用了 TLAB 的话, 这一项工作也可以提前至 TLAB 分配时顺便进行。
这步操作保证了对象的实例字段在 Java 代码中可以不赋自定义值就可以直接使用, 使程序能访问这些字段的数据类型所对应的初始值。
各种数据类型的初始值:
类型 | 默认值 |
---|---|
boolean | false(0) |
char | \u0000(unicode 编码, 转为十进制就是 0) |
byte | 0 |
short | 0 |
int | 0 |
float | 0.0f |
double | 0.0d |
long | 0L |
reference(引用类型) | null |
2.4 其他必要的设置
JVM 会对这个对象的对象头等相关的属性进行设置, 比如确定是哪个类的实例, 将 klass Pointer 指向对应的 Class, 设置对象的哈希码, 对象的 GC 分代年龄, 偏向锁标识等。
到了这一步, 字节码 new 引起的对象创建就完成。
但是这时创建出来的的对象所有的属性都是默认值, 还是一个未完整的对象的。
2.5 执行 <init> 方法
顺着字节码, 下一个 dup, 这个只是单纯的为了更方便地为后面的赋值操作而执行的,
本身不会改变到对象的任何属性, 所以跳过。
下一个 invokespecial #9 (Method “”😦)V) 字节码。
invokespecial 字节码, 可以先简单看作是调用后面参数指定的方法。
而 是 JVM 在编译时间, 根据我们的类生成的一个统一的属性初始化方法 (对应了上面的例子的public io.github.lcn29.Demo() 方法)。
举个例子:
public class A {private int num = 10;private int num2; private int num3;{this.num2 = 20;}public Demo() {this.num3 = 100;}
}
上面 A 有 3 个属性 num, num2, num3, 它们分别在 3 个地方被赋值了
- 声明赋值
- 代码块赋值
- 构造函数赋值
而编译为字节码后, 编译器会把所有的赋值操作都统一在自己生成的 方法中, 就像下面
public class A {private int num;private int num2; private int num3;public <init>() {// 先调用父类的 <init> 方法, 确保父类的属性设置完成super.<init>();// 自己的属性赋值this.num = 10;this.num2 = 20;this.num3 = 100;}public Demo() {}
}
了解完 方法, 我们可以了解到 invokespecial #9 这条字节码指令的效果: 对自己的父类和属性进行真正的赋值。
到了这里, 一个真正完整的实例对象就创建完成。
后面的 astore_1 和 return 都不涉及到对象的情况的处理, 跳过。
至此一个 实例对象的创建就完成。
3 <init> 方法和 <clinit> 方法
方法是编译器生成的, 生成的字节码中一般都会有, 但是不一定就会执行。
一般来说 方法是否执行, 由 new 指令后面是否跟随 invokespecial 指令决定。
Java 编译器会在遇到 new 关键字的地方同时生成这 2 条指令, 如果不是通过 new 方式创建的, 则不会有。
在 Java 类的定义中, 除了正常的属性外, 我们还可以再类中定义静态属性, 同理编译器会将静态属性和静态代码块中的属性赋值, 统一到一个 方法中。
方法在我们创建类实例时调用, 而 则是在类加载时执行。
3.1 举个例子加深理解
public class Parent {private static int pNum1 = 10;private int pNum2 = 10;static {pNum1 = 11;}{pNum2 = 12;}public Parent() {this.pNum2 = 13;}
}public class Son extends Parent {private static int sNum1 = 20;private int sNum2 = 20;static {sNum1 = 21;}{sNum2 = 22;}public Son() {this.sNum2 = 23;}
}
当我们创建 Son 的实例的时候, 上面的构造函数, 代码块, 静态代码块的执行顺序是怎么样的?
上面的执行顺序差不多是这样的
- Parent 的静态变量赋值
- Parent 的静态代码块执行
- Son 的静态变量赋值
- Son 的静态代码块执行
- Parent 的实例变量赋值
- Parent 的代码块执行
- Parent 的构造函数执行
- Son 的实例变量赋值
- Son 的代码块执行
- Son 的构造函数执行
出现上面的执行顺序, 主要是由 <init>
和 <clinit>
造成的。
<clinit>
主要针对我们当前类的初始化, 而<init>
主要针对我们当前类的实例的初始化, 而且他的初始会先调用父级的无参<init>
方法。- 这里的初始化指的是类中的属性直接赋值执行, 代码块执行, 构造函数执行, 这三个执行最终会整合到
<init>
(实例相关的), 或者<clinit>
(静态相关的), 并按照的执行顺序执行 - 类加载机制中, 会先加载父类, 再加载子类。
从 new Son() 时, 先加载 Parent 对应的类, 然后调用 Parent 的<clinit>
方法
- 在 Parent 的
<clinit>
方法
1.1 执行 Parent 的属性直接赋值, 给 pNum1 赋值为 10
1.2 执行 Parent 的静态代码块, 给 pNum2 赋值为 11
1.3 静态代码块和直接赋值没有层级关系, 谁在前谁先, 如果这时静态代码块在直接赋值前, 那么先给 pNum2 赋值 (代码块和实例属性也是遵循这个规则)
- 调用 Son 的
<clinit>
方法
2.1 执行 Son 的属性直接赋值, 给 sNum1 赋值为 20
2.2 执行 Son 的静态代码块, 给 sNum1 赋值为 21
- 执行 Son 的
<init>
方法
3.1
<init>
第一步会直接调用他的直接父级的<init>
方法, 也就是 Parent 的<init>
方法, 然后调用自身的代码块执行, 再构造函数执行 (Parent 的<init>
还会调用父类的, 这里省略)
3.2 Parent 的<init>
方法, 先执行属性直接赋值, pNum2 赋值为 10
3.3 Parent 的<init>
方法, 执行 Parent 的代码块, pNum2 赋值为 12
3.3 Parent 的<init>
方法, 执行 Parent 的构造函数, pNum2 赋值为 13
3.4 Parent 的<init>
执行完成, 执行 Son 自己的<init>
方法, 直接属性赋值, sNum2 赋值为 20
3.5 Son 的代码块, sNum2 赋值为 22
3.6 Son 的构造函数, sNum3 赋值为 23
从上面的例子, 应该可以区分出 <clinit>
和 <init>
的作用和区别了吧
2 个方法都是编译器, 对我们编写的初始的整合, static 属性赋值和静态代码块整合为 <clinit>
, 实例属性赋值, 代码块和构造方法整合为 <init>
, 而且 <init>
方法会先调用直接父级的 init 的方法。
到此, 所有的内容就整理完成了。
4 参考
Java对象的创建过程详解
相关文章:
【Java JVM】实例对象的创建
当我们涉及 Java 编程时, 对象的创建是一个基础而关键的概念。在 Java 中, 一切皆为对象, 而对象的创建方式直接影响代码的结构和性能。 本博客将探讨一下 Java 实例对象的创建过程。 1 创建对象的方法有哪些 在 Java 中如果要创建一个对象, 有哪些方式呢? 运用 new 关键字创…...
sectigo多域名通配符证书
多域名通配符SSL证书是一种特殊的SSL证书,它综合了多域名SSL证书和通配符SSL证书的特点,可以同时保护多个泛域名以及它的主域名,适合域名多,子域名也比较多的单个或多个站点使用。今天就随SSL盾小编了解Sectigo旗下的DV多域名通配…...
vue 流光边框矩形圆形容器
实现流光边框一般是用渐变背景加动画实现,然后使用内部盒子遮挡内部空间,达到边框流光的效果 思路:背景渐变旋转动画 功能: 自定义渐变(是否渐变<不渐变没有流光效果>,渐变颜色,渐变角…...
明理信息科技打造专属个人或企业知识付费平台,核心功能设计
在当今信息爆炸的时代,知识管理已经成为了每个人必须面对的问题。然而,市面上的知识付费平台大多数都是通用的,无法满足个性化需求。 因此,明理信息科技提供了一款专属定制的适合个人的知识付费平台。核心产品能力如下࿱…...
超结MOS/低压MOS在5G基站电源上的应用-REASUNOS瑞森半导体
一、前言 5G基站是5G网络的核心设备,实现有线通信网络与无线终端之间的无线信号传输,5G基站主要分为宏基站和小基站。5G基站由于通信设备功耗大,采用由电源插座、交直流配电、防雷器、整流模块和监控模块组成的电气柜。所以顾名思义…...
字节8年经验之谈 —— 如何从0开始做自动化测试?
自动化测试是使用软件工具在应用程序上自动运行测试的过程,无需任何人为干预。这可以通过减少手动测试的需要来保存时间并提高软件开发过程的效率。由于人为错误或不一致性,手动测试可能容易出错,这可能导致错误未被检测到。自动化测试通过提…...
深入探索Zookeeper的ZAB协议:分布式系统的核心解析
引言 自我进入软件开发领域以来,我一直对分布式系统充满着浓厚的兴趣。在这个领域中,Zookeeper无疑是一个备受关注的重要组件。作为一名资深的Java工程师,我有幸深入探索过Zookeeper的许多方面,其中最让我着迷的部分莫过于其核心机…...
安捷伦Agilent 34970A数据采集
易学易用 从34972A简化的配置到内置的图形Web界面,我们都投入了非常多的时间和精力,以帮助您节约宝贵的时间。一些非常简单的东西,例如模块上螺旋型端子连接器内置热电偶参考结、包括众多实例和提示的完整用户文档,以及使您能够在开机数分钟后…...
Apache Flume(5):多个agent模型
可以将多个Flume agent 程序连接在一起,其中一个agent的sink将数据发送到另一个agent的source。Avro文件格式是使用Flume通过网络发送数据的标准方法。 从多个Web服务器收集日志,发送到一个或多个集中处理的agent,之后再发往日志存储中心&…...
如何在Ubuntu系统中安装VNC并结合内网穿透实现远程访问桌面
文章目录 前言1. ubuntu安装VNC2. 设置vnc开机启动3. windows 安装VNC viewer连接工具4. 内网穿透4.1 安装cpolar【支持使用一键脚本命令安装】4.2 创建隧道映射4.3 测试公网远程访问 5. 配置固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址5.3 测试…...
JaCoCo 统计度量
1、JaCoCo: 一个判断算2个Branch,最后一个括号算一行 2、IDEA:一个判断算一个Branch,最后一个括号不算一行...
我们经常使用的AI技术
窄人工智能 Narrow AI 窄人工智能主要集中于处理相对单一的任务,可以理解,科学家在研究如何模拟人类智能时,一种思路就是我们是不是可以先分别模拟人的不同能力,例如我们的视觉能力,文字识别能力等等。所以就演化出针…...
静态路由及动态路由
文章目录 静态路由及动态路由一、静态路由基础1. 静态路由配置2. 负载分担3. 路由备份4. 缺省路由5. 静态路由实操 二、RIP 动态路由协议1. RIP 协议概述2. RIP 协议版本对比2.1 有类路由及无类路由 3. RIP 路由协议原理4. RIP 计时器5. 度量值6. 收敛7. 示例 静态路由及动态路…...
MySQL——表的增删查改
目录 一.Create(创建) 1.单行数据 全列插入 2.多行数据 指定列插入 3.插入否则更新 4. 替换 二.Retrieve(读取) 1. select 列 查询 2.where 条件 3.结果排序 4.筛选分页结果 三.Update (修改)…...
javascript_1
3) string ⭐️ js 字符串三种写法 let a "hello"; // 双引号 let b "world"; // 单引号 let c hello; // 反引号 html 代码如下,用 java 和 js 中的字符串如何表示? <a href"1.html">超链接</a> …...
【ranger】CDP环境 更新 ranger 权限策略会发生低概率丢失权限策略的解决方法
一、问题描述: 我们的 kafka 服务在更新(添加) ranger 权限时,会有极低的概率导致 MM2 同步服务报错,报错内容 Not Authorized。但是查看 ranger 权限是赋予的,并且很早配置的权限策略也会报错。 相关组件…...
Python安装及配置
一、前置说明 Python的安装有两种方式:1. 访问Python官方网站下载安装;2. 使用Python的开源发行版进行安装。 Anaconda 是一个用于科学计算、数据分析和机器学习的开源发行版,它包含了许多常用的科学计算和数据分析库。Anaconda 不仅仅是 P…...
Instagram 外贸产品推广技巧
在Instagram上,外贸业务有许多独特的机会来展示其产品并吸引国际买家。成功的外贸产品推广要求细致的策略、引人入胜的创意内容和有针对性的市场洞察。下面的小节将详细解析如何在Instagram上进行外贸产品的有效推广。 1.创意与视觉呈现 Instagram是一个基于图片和…...
5款实用的小工具,让你的日常生活多姿多彩
简单而小巧的工具,经常能在日常中悄然发挥极大的作用。这五款小工具可能成为你生活中不可或缺的一部分。 1.网络浏览器——Brave Brave是一款基于Chromium内核的开源网络浏览器,它可以阻止网站的广告和跟踪程序,保护您的隐私和安全。…...
【改进YOLOv8】磁瓦缺陷分类系统:改进LSKNet骨干网络的YOLOv8
1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 近年来,随着智能制造产业的不断发展,基于人工智能与机器视觉的自动化产品缺陷检测技术在各行各业中得到了广泛应用。磁瓦作为永磁电机的主…...
Linux-VRRP
这里写自定义目录标题 一、VRRP简介1.1 什么是VRRP?1.2 keepalived是什么? 二、配置过程2.1 试验模型2.2. Keepalived监控和维护VRRP集群的步骤 一、VRRP简介 1.1 什么是VRRP? VRRP(Virtual Router Redundancy Protocolÿ…...
使用Axure的中继器的交互动作解决增删改查h
🎬 艳艳耶✌️:个人主页 🔥 个人专栏 :《产品经理如何画泳道图&流程图》 ⛺️ 越努力 ,越幸运 目录 一、中继器的交互 1、什么是中继器的交互 2、Axure中继器的交互 3、如何使用中继器? 二…...
华为云Stack 8.X 流量模型分析(一)
一、基础知识 1.tap与tun tap与tun都是操作系统(Linux)内核中的虚拟网络设备,等同于一个以太网设备,可以收发数据报文包。 tap与tun的定义相同,两者仅仅是通过一个Flag来区分。但二者所承担的功能差别较大&am…...
SpringBoot已经禁掉了循环依赖!
还在问循环依赖嘛?SpringBoot已经禁掉了循环依赖! 首发2023-12-18 11:26yuan人生 如果现在面试时还有人问你循环依赖,你就这样怼他:循环依赖是一种代码质量低下的表现,springboot2.6之后的版本已经默认禁用了。 Spr…...
【.NET Core】反射(Reflection)详解(一)
【.NET Core】反射(Reflection)详解(一) 文章目录 【.NET Core】反射(Reflection)详解(一)一、什么是反射二、Assembly类2.1 LoadFile2.2 Load2.3 LoadFrom(String)2.4 GetName()2.5…...
jenkins入门
文章目录 前言一、 jenkins的安装二、新建简单任务总结 前言 本篇文章是 jenkins 的入门级别案例,包括安装、基础概念介绍、新建简单任务 一、 jenkins的安装 下载 jenkins https://www.jenkins.io/download/ 当前案例下载的是 2.426.2 LTS 版本 下载安装jdk11 …...
HarmonyOS --- 首页(新新新手版,高手误入)
一、前言 每一个App都应该有一个首页,在Android中一般由MainActivity Navigation Fragment * N (随便你怎么组合,用别的也一样),鸿蒙呢?瞅瞅吧。阿弥陀佛,苦逼Android学完Java学Dart、学完Da…...
springboot升级到3.2导致mybatis-plus启动报错
在springboot升级到3.2时,服务启动报错 java.lang.IllegalArgumentException: Invalid value type for attribute ‘factoryBeanObjectType’: java.lang.String: java.lang.IllegalArgumentException: Invalid value type for attribute factoryBeanOb…...
浏览器原理篇—渲染原理
目录导航 为什么要学习浏览器的渲染原理浏览器的渲染流程浏览器的渲染阻塞浏览器的渲染优化 为什么要学习浏览器的渲染原理? 知识深度挖掘: 帮助更好地理解前端性能优化。从而对实现效果进行针对性优化。如:**回流和重绘 **渲染机制。帮助…...
idea安装
mac安装路径 /Users/xxx/Library/Application Support/JetBrains/IntelliJIdeaxxx版本 将路径内文件直接复制到新版本即可, 注意如果为破解版idea.vmoptions配置中的内容是否添加或删除 maven配置如果使用idea, 需要在应用程序IntelliJ IDEA.app中显示包内容, /Applications/I…...
深圳贝尔利网站建设公司/爱站网ip反查域名
大家好,我是老赵!Java8的stream流,加上lambda表达式,可以让代码变短变美,已经得到了广泛的应用。我们在写一些复杂代码的时候,也有了更多的选择。代码首先是给人看的,其次才是给机器执行的。代码…...
聊城做企业网站/网站优化推广培训
ExecutorService fixedThreadPool Executors.newFixedThreadPool(5)创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待 package UnitTest;import java.util.ArrayList; import java.util.List; import java.util.concurrent.Execution…...
企业网站制作收费/免费seo关键词优化服务
持续更新 1.HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内…...
国外做蛋糕网站/广告推广怎么找客户
JS 创建自定义对象的方法 工厂模式 优点:接受参数,可以无数次的调用这个函数,创建Person对象,而每次他都可以返回一个包含三个属性一个方法的对象。 缺点:虽然解决了创建多个相似对象的问题,但是没有解决…...
做网站用的字体是什么/网站怎么做出来的
使用环境前一篇在介绍 JavaStruct 类时指定了使用库使用环境为 Java 5 及以上,也即开发我们使用的 JDK 版本为1.5及以上就可以了。以下讲解的用例可以直接将 code 直接粘贴到 java 的 main 函数中执行就可以了,后面会给出测试用例和结果。使用方法JavaSt…...
wordpress增加搜索框/邮件营销
★点开后电脑将在某一时间段后自动关机,输入如同“我是猪”一类的话语,即可结束,,,否则关机任务则会一直处于倒计时状态。。#include<stdio.h> //标准输入输出库函数 #include<stdlib.h> //可以输入…...