建设网站公司联系方式,怎么做网站手机版,网站建设服务内容,重庆建设工程安全管理网查询目录
1.对象村的秘密#xff08;对象在内存的实现#xff09;
1.1 内存的好兄弟“堆”与“栈”
1.1.1方法喜欢玩泰山压顶
1.1.2 stack的实现
1.2栈上的对象引用
1.2.1有关对象局部变量
1.2.2 如果局部变量生存在栈上#xff0c;那么实例变量呢#xff1f;
1.2.3创建…目录
1.对象村的秘密对象在内存的实现
1.1 内存的好兄弟“堆”与“栈”
1.1.1方法喜欢玩泰山压顶
1.1.2 stack的实现
1.2栈上的对象引用
1.2.1有关对象局部变量
1.2.2 如果局部变量生存在栈上那么实例变量呢
1.2.3创建对象的奇迹
1.3对象的消亡
1.3.1life与“scope”的差别
1.3.2杀死对象的三位杀手
2.和事佬在对象村的处境static成员
2.1 和事佬的处事方式static的特性
2.2 static修饰成员变量
2.3 static修饰成员方法 2.4 static成员变量初始化
3.代码块
3.1代码块概念以及分类
3.2 普通代码块
3.3 构造代码块
3.4 静态代码块 导读上节我们拜访了对象村我们不禁产生很多疑问。怎么做到遍地都是对象的呢对象村又是如何出现的下面就由我来进行揭秘。 前言 对象有生有死。你必须为对象的生命循环周期负责。你决定着对象何时创建如何创建也决定着何时销毁对象。其实你不是真的自消灭对象只是声明要放弃它而巳。一旦它被放弃了冷血无情的垃圾收集器(GC)就会将它蒸发掉、回收对象所占用的内存空间。如果你要编写Java程序就必须创建对象。早晚你得将它们释放掉不然就会出现内存不足的问题。这一章会讨论对象如何创建、存在于何处以及如何让保存和抛弃更有效率。这代表我们会述及堆、栈、范围、构造器、超级构造器、空引用等。注意:内容含有死亡成份12岁以下儿童需由家长陪同观赏 1.对象村的秘密对象在内存的实现
1.1 内存的好兄弟“堆”与“栈”
在Java中堆heap和栈stack是两种不同的内存区域用于存储程序运行时的不同类型的数据和对象。
1. 栈Stack
栈是一种线性数据结构遵循先进后出Last-In-First-Out, LIFO的原则。栈中的数据主要包括基本数据类型的变量和对象的引用。 栈内存用于存储局部变量、方法参数、方法调用以及方法返回时的临时数据。当一个方法被调用时会在栈上创建一个称为栈帧的区域用于存储该方法的局部变量和方法调用信息。栈帧在方法执行完毕后被销毁。 栈的大小在程序运行时是固定的由Java虚拟机JVM进行分配和管理。如果栈的内存空间不足会抛出 StackOverflowError 错误。
2. 堆Heap 堆是用于存储动态分配的对象的一块内存区域。堆是Java中最大的一块内存区域也是最复杂的一块内存区域。所有的类实例对象和数组对象都存储在堆上。堆的大小在程序运行时是可变的。Java虚拟机根据堆的使用情况动态地分配和回收内存。堆的内存分配由垃圾回收器Garbage Collector负责它自动扫描并回收不再使用的对象使可用内存得到重复利用。 通常情况下栈的内存空间比较小用于存储局部变量等临时数据。而堆的内存空间比较大用于存储动态创建的对象。在Java中基本类型的变量如int、boolean等和对象的引用被存储在栈上而对象的实际数据包括成员变量则存储在堆上。 了解栈和堆的原理对于理解Java的内存管理和内存分配非常重要它们的不同特点也直接影响到程序的性能和内存使用情况。 如图所示 实例变量 实例变量是定义在类中方法外的变量。每个实例变量属于该类的每个实例对象每个对象都有自己的实例变量副本。实例变量在对象创建时被初始化并在对象的整个生命周期内都存在。实例变量可以被类中的任何方法、构造方法或块使用。访问实例变量时必须通过对象引用来访问。 示例代码如下
public class MyClass {// 实例变量private String name; // 字符串类型的实例变量public void setName(String name) {this.name name;}public void printName() {System.out.println(Name: name);}
}局部变量 局部变量是在方法、构造方法或块中定义的变量只在其所在的作用域内可见。局部变量仅在其所在的方法或块执行期间存在并且在方法或块的执行结束后被销毁。在方法中定义的局部变量在每次方法调用时都会重新创建每个方法调用都会为其分配内存空间。访问局部变量时只能在其声明的作用域内访问。 示例代码如下
public class MyClass {public void printNumber(int number) {// 局部变量String message The number is: ; // 字符串类型的局部变量System.out.println(message number);}
} 1.1.1方法喜欢玩泰山压顶
当你调用一个方法时该方法会放在调用栈的栈顶实际被堆上栈的是堆栈块。它带有方法的状态包括执行到哪一行程序以及所有的局部变量的值。
栈顶上的方法是目前正在执行的方法方法会一直待在这里直到执行完毕如果foo() 方法调用bar()方法则bar()方法会放在foo()方法的上面。 1.1.2 stack的实现
下边有三个方法第一个方法在执行过程中会调用第二个方法第二个会调用第三个。每个方法都在内容中声明一个局部变量而go()方法还有声明一个参数(这代表go方法有两个局部变量。
public void doStuff(){boolean b true;go(4);
}
public void go(int x){int z x 24;crazy();//假设还有很多代码
}
public void crazy(){char a;
}
如图 1.2栈上的对象引用
1.2.1有关对象局部变量
要记得非primitive的变量只是保存对象的引用而已而不是对象本身。你已经知道对象存在于何处——堆。不论对象是否声明或创建如果局部变量是个对该对象的引用只有变量本身会放在栈上 对象本身只会存在于堆上。 primitive在Java中primitive原始类型是指Java语言中的基本数据类型。Java的原始类型包括boolean、char、byte、short、int、long、float和double。这些原始类型是Java语言的基本构建块用于存储简单的数据值。 public class stackRef{
public void foof(){barf();}public void barf(){Duck d new Duck(24);}} 要点 我们关心栈 与堆这两种内存空间。 实例变量是声明在类中方法之外的地方。 局部变量声明在方法或方法的参数上。 所有局部变量都存在于栈上相对应的堆栈块中。 对象引用变量 与primitive主数据类型变量都是放在栈上。 不管是实例变量或局部变量 对象本身都会在堆上。 1.2.2 如果局部变量生存在栈上那么实例变量呢
当你要新建一个CellPhone()时Java必须在堆上帮CellPhone找一个位置。这会需要多少空间呢?足以存放该对象所有实例变量的空间。没错实例变量存在于对象所属的堆空间上。 记住对象的实例变量的值是存放于该对象中。如果实例变量全都是primitive主数据类型的则Java会依据primitive主数据类型的大小为该实例变量留下空间。int需要32位long需要64位依此类推。Java并不在乎私有变量的值不管是32或32,000,000的int 都会占用32位 1.2.3创建对象的奇迹
三个步骤的回顾声明、创建、赋值 1.3对象的消亡
1.局部变量只会存活在声明该变量的方法中 局部变量只会存活在声明该变量的方法中
public void read(){
int s 42;//s只能用在此方法中
//当方法结束时// s会完全消失 变量s只能用在read(方法中。换句话说此变量的范围只会在所属方法的范围内。其余的程序代码完全见不到s。2.实例变量的寿命与对象相同。 如果对象还活着则实例变量也会是活的。
public class Life {int size;public void setSize (int s) {size s;//s会在方法结束时//消失但size在类中//到处都可用 此时s变量(这次是方法的参数)的范国同样也只限制在所属的setSize()这方法中。
1.3.1life与“scope”的差别 Lite 只要变量的堆栈块还存在于堆栈上局部变量就算活着。也就是说活到方法执行完毕为止。 Scope 局部变量的范围只限于声明它的方法之内.当此方法调用别的方法时该变量还活着但不在目前的范围内。执行其他方法完毕返回时范围也就跟着回来。 public void doStuff(){
boolean btrue;
go(4) ;
}
public void go(int x){
int z x 24;
crazy();
//这里有更多的代码
}
public void crazy(){
char c a;
}当局部变量活着的时候它的状态会被保存。只要doStuff()还在堆栈上b变量就会保持它的值。但b变量只能在doStuffO待在栈顶时才能使用。也就是说局部变量只能在声明它的方法在执行中才能被使用 1.3.2杀死对象的三位杀手 有3种方法可以释放杀死对象的引用: 当最后一个引用消失时对象就会变成可回收的。1 引用永久性的离开它的范围。 void go() { Life znew Life() ; } 2 引用被赋值到其他的对象上. Life z new Life() ; z new Life(); 3 直接将引用设定为null。 Life z new Life(); z null; 对象杀手1号
引用永久性的离开他的范围
public class StackRef{
public void foof(){barf();}public void barf(){Duck d new Duck;}} 对象杀手三号
引用被赋值到其他对象
public class ReRef{Duck d new Duck();public void go(){d new Duck;}
}
如下图 对象杀手三号
直接将引用设定为null
public class ReRef {Duck d new Duck();public void go() {d null;}
} 那null又是什么呢 null的真相 当你把引用设为null时你就等于是抹除遥控器的功能。换句话说你会拿到一个没有电视的遥控器。null是代表“空” 的字节组合(实际上是什么只有Java虚拟机才会知道)。 如果你真地按下这种逼控器上的按钮什么事情也不会发生。但在Java.上你是不能对null引用按钮的。因为Java虚拟机会知道(这是运行期不是编译时的错误)你期待喵喵叫但是却没有Cat可以执行! 对null引用使用圆点运算符会在执行期遇到NullPointerException这样的错误。后而会有讨论异常的章节。 2.和事佬在对象村的处境static成员
2.1 和事佬的处事方式static的特性
通过以下三个代码对学生进行描述如下所示
public class Student{
// ...
public static void main(String[] args) {
Student s1 new Student(Li leilei, 男, 18, 3.8);
Student s2 new Student(Han MeiMei, 女, 19, 4.0);
Student s3 new Student(Jim, 男, 18, 2.6);
}
}
得到以下三个对象的特征 每个对象中都会包含一份 ( 称之为实例变量 )因为需要使用这些信息来描述 具体的学生。而现在要表示学生上课的教室这个教室的属性并不需要每个学生对象中都存储一份而是需要让所 有的学生来共享。 在 Java 中被 static 修饰的成员称之为静态成员也可以称为类成员其不属于某个具体的对 象是所有对象所共享的。 2.2 static修饰成员变量
static修饰的成员变量称为静态成员变量静态成员变量最大的特性不属于某个具体的对象是所有对象所共享的。 【静态成员变量特性】 1. 不属于某个具体的对象是类的属性所有对象共享的不存储在某个对象的空间中 2. 既可以通过对象访问也可以通过类名访问但一般更推荐使用类名访问 3. 类变量存储在方法区当中 4. 生命周期伴随类的一生(即随类的加载而创建随类的卸载而销毁) public class Student{
public String name;
public String gender;
public int age;
public double score;
public static String classRoom Bit306;
// ...
public static void main(String[] args) {
// 静态成员变量可以直接通过类名访问
System.out.println(Student.classRoom);
Student s1 new Student(Li leilei, 男, 18, 3.8);
Student s2 new Student(Han MeiMei, 女, 19, 4.0);
Student s3 new Student(Jim, 男, 18, 2.6);
// 也可以通过对象访问但是classRoom是三个对象共享的
System.out.println(s1.classRoom);
System.out.println(s2.classRoom);
System.out.println(s3.classRoom);}
}
静态成员变量可以直接通过类名访问 同学以调试方式运行上述代码然后在监视窗口中可以看到静态成员变量并没有存储到某个具体的对象中。 2.3 static修饰成员方法
被private修饰的只有自己知道其他人都不知道封装会进行详细讲解 一般类中的数据成员都设置为private而成员方法设置为public那设置之后Student类中classRoom属性如何在类外访问呢
public class Student{
private String name;
private String gender;
private int age;
private double score;
private static String classRoom Bit306;
// ...
}
public class TestStudent {
public static void main(String[] args) {
System.out.println(Student.classRoom);
}
}
编译失败
Error:(10, 35) java: classRoom 在 extend01.Student 中是 private 访问控制 那static属性应该如何访问呢
Java中被static修饰的成员方法称为静态成员方法是类的方法不是某个对象所特有的。静态成员一般是通过静态方法来访问的。
public class Student{
// ...
private static String classRoom Bit306;
// ...
public static String getClassRoom(){
return classRoom;
}
}
public class TestStudent {
public static void main(String[] args) {
System.out.println(Student.getClassRoom());
}
} 输出Bit306 【 静态方法特性】 1. 不属于某个具体的对象是类方法 2. 可以通过对象调用也可以通过类名.静态方法名(...)方式调用更推荐使用后者 3. 不能在静态方法中(直接)访问任何非静态成员变量 无法从静态上下文引用非静态变量name 4. 静态方法中不能调用任何非静态方法因为非静态方法有this参数在静态方法中调用时候无法传递this引用 5. 静态方法无法重写不能用来实现多态(此处大家暂时不用管后序多态位置详细讲解) 2.4 static成员变量初始化
注意静态成员变量一般不会放在构造方法中来初始化构造方法中初始化的是与对象相关的实例属性
静态成员变量的初始化分为两种就地初始化 和 静态代码块初始化。 1. 就地初始化
就地初始化指的是在定义时直接给出初始值
public class Student{
private String name;
private String gender;
private int age;
private double score;
private static String classRoom Bit306;
// ...
} 2. 静态代码块初始化
那什么是代码块呢继续往后看 :) ~~~
3.代码块
3.1代码块概念以及分类
使用 {} 定义的一段代码称为代码块。根据代码块定义的位置以及关键字又可分为以下四种 普通代码块 构造块 静态块 同步代码块后续讲解多线程部分再谈 3.2 普通代码块 普通代码块定义在方法中的代码块 public class Main{
public static void main(String[] args) {
{ //直接使用{}定义普通方法块
int x 10 ;
System.out.println(x1 x);
}
int x 100 ;
System.out.println(x2 x);//外面用不了内部的x
}
}
// 执行结果
x1 10
x2 100 这种用法较少见 3.3 构造代码块 构造块定义在类中的代码块(不加修饰符)。也叫实例代码块。构造代码块一般用于初始化实例成员变量。 public class Student{
//实例成员变量
private String name;
private String gender;
private int age;
private double score;
public Student() {
System.out.println(I am Student init()!);
}
//实例代码块
{
this.name bit;
this.age 12;
this.sex man;
System.out.println(I am instance init()!);
}
public void show(){
System.out.println(name: name age: age sex: sex);
}
}
public class Main {
public static void main(String[] args) {
Student stu new Student();
stu.show();
}
}
// 运行结果
I am instance init()!
I am Student init()!
name: bit age: 12 sex: man构造代码块在方法的外面类的里面 实例代码块比构造方法先执行和放在哪里没有关系 3.4 静态代码块
使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量。
public class Student{
private String name;
private String gender;
private int age;
private double score;
private static String classRoom;
//实例代码块
{
this.name bit;
this.age 12;
this.gender man;
System.out.println(实例代码块);
}
// 静态代码块
static {
classRoom bit306;
System.out.println(静态代码块);
}
public Student(){
System.out.println(构造代码块);
}
public static void main(String[] args) {
Student s1 new Student();
Student s2 new Student();
}
} 注意事项 静态代码块不管生成多少个对象其只会执行一次 静态成员变量是类的属性因此是在JVM加载类时开辟空间并初始化的 如果一个类中包含多个静态代码块在编译代码时编译器会按照定义的先后次序依次执行(合并) 实例代码块只有在创建对象时才会执行 实例化两个对象 当没有实例化对象时 结尾:
以上就是全部内容送一句话该大家
让我们如大自然般悠然自在地生活一天吧 别因为有坚果外壳或者蚊子翅膀落在铁轨上而翻了车。
让我们该起床时就赶紧起床 该休息时就安心休息 保持安宁而没有烦扰的心态;
身边的人要来就让他来要去就让他去 让钟声回荡让孩子哭喊— 下定决心好好地过一天。