程序是静态的,存在于硬盘上,只有Load到内存中经过操作系统相关代码调用后分配内存开始运行,Java代码中又把内存分为4块儿,如下图:heap堆、stack栈、data segment、code segment。
八大基本类型与引用类型在内存中的区别:
八大基本类型在内存中只有一块儿内存
而引用类型占两块儿内存
类和对象在内存中的区别:
类是静态的概念,存在于代码区
对象是new出来的,位于堆内存,类的每个成员变量在不同的对象中都有不同的值(除了静态变量)而方法只有一份,执行的时候才占内存。
下面是一个小例子:

(Person p = new Person();其实是调用的Person内的构造器/构造方法)
图中c1和c2如果用==比较的话,两个是不同的,==比较的是对象的引用,可以重写equals()方法。
注意,Object类的equals()方法内部就是用==比较的!!!String类里的equals方法比较的是字符序列!
下面几个例子可以练练手!!!
例1.画出下面代码的内存图
package com.review02.memory;
public class Test {
public static void main(String[] args) {
Test test = new Test();
int date = 9;
BirthDate d1 = new BirthDate(7,7,1970);
BirthDate d2 = new BirthDate(21,11,1996);
test.change1(date);
test.change2(d1);
test.change3(d2);
System.out.println("date="+date);
d1.display();
d2.display();
}
public void change1(int i) { //此处是值传递,这里形参i变了,main中的实参date值不会改变
i = 1234;
}
public void change2(BirthDate b) { //下面重新new了一个对象,在堆里面又重新创建了一个对象
b = new BirthDate(15,4,2010);
}
public void change3(BirthDate b) {//这里和change1()不同,对象的引用里的值变了,对象的值随之发生改变。
b.setDay(22);
}
}
class BirthDate{
private int day;
private int month;
private int year;
public BirthDate(int d, int m, int y){
day = d;
month = m;
year = y;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public void display() {
System.out.println(day+"-"+month+"-"+year);
}
}

例2:画出如下代码最终的内存图:
package com.review02.memory;
public class Point {
private double x;
private double y;
private double z;
public Point() {
}
public Point(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public double getZ() {
return z;
}
public void setZ(double z) {
this.z = z;
}
public double calculateDistance(Point p) {
double distance,distanceSquare;
distanceSquare = Math.pow(x-p.getX(),2)+Math.pow(y-p.getY(),2)+Math.pow(z-p.getZ(),2);
distance = Math.sqrt(distanceSquare);
return distance;
}
public static void main(String[] args) {
// Point p = new Point(1,1,1);
// Point p1 = new Point(1.5,1,1);
// System.out.println(p.calculateDistance(p1));
Globe g1 = new Globe(new Point(1.0,2.0,3.0),3.0);
Globe g2 = new Globe(5.0);
//输出g1球心的坐标和半径
System.out.println("g1---球心坐标:("+g1.getPoint().getX()+", "+g1.getPoint().getY()
+", "+g1.getPoint().getZ()+"), 半径:"+g1.getRadius());
//输出g2球心的坐标和半径
System.out.println("g2---球心坐标:("+g2.getPoint().getX()+", "+g2.getPoint().getY()
+", "+g2.getPoint().getZ()+"), 半径:"+g2.getRadius());
//分别输出g1和g2的体积
System.out.println("g1的体积:"+g1.Volume()+",g2的体积:"+g2.Volume());
g1.setPoint(1.5, 2.0, 1.0);
g2.setRadius(2.0);
//分别打印g1、g2修改后的坐标和半径
System.out.println("修改后g1球心坐标后,g1---球心坐标:("+g1.getPoint().getX()+", "+g1.getPoint().getY()
+", "+g1.getPoint().getZ()+"), 半径:"+g1.getRadius()+", 体积:"+g1.Volume());
System.out.println("修改后g2半径后, g2---球心坐标:("+g2.getPoint().getX()+", "+g2.getPoint().getY()
+", "+g2.getPoint().getZ()+"), 半径:"+g2.getRadius()+", 体积:"+g2.Volume());
Point p1 = new Point(1.2, 2.5, 3.0);
System.out.println("点p1(1.2, 2.5, 3.0)在g1球内吗?--"+g1.contains(p1));
System.out.println("点(1.0, 5.5, 2.0)在g1球内吗?--"+g1.contains(new Point(1.0,5.5,2.0)));
}
}
class Globe {
private Point point;
private double radius;
public Globe() {
}
public Globe(Point point, double radius) {
this.point = point;
this.radius = radius;
}
public Globe(double radius) {
point = new Point(0.0,0.0,0.0);
this.radius = radius;
}
public Point getPoint() {
return point;
}
public void setPoint(double x, double y, double z) {
point.setX(x);
point.setY(y);
point.setZ(z);
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
//判断点是否在球体内
boolean contains(Point p) {
double x = p.getX() - point.getX();
double y = p.getY() - point.getY();
double z = p.getZ() - point.getY();
if(x*x+y*y+z*z>radius*radius) {
return false; //在球体外
}else {
return true;
}
}
//求球体的体积
public double Volume() {
return 3.14*Math.pow(radius,3)*3/4;
}
}

例3:分别画出含有和不含有静态属性sid·的内存图:
package com.review02.memory;
public class StaticCat {
//如果sid不是static类型,若不创建对象,sid就不存在
private static int sid = 0;
private String name;
int id;
public StaticCat(String name) {
this.name = name;
id = sid++;
}
public void info() {
System.out.println("My name is"
+name+"No."+id);
}
+
public static void main(String[] args) {
//StaticCat.sid = 100;
StaticCat mimi = new StaticCat("mimi");
StaticCat miao = new StaticCat("miao");
mimi.info();
miao.info();
}
}

本文深入探讨了Java内存管理的核心概念,包括基本类型与引用类型的内存分配差异、类与对象的区别等,并通过具体示例展示了不同操作对内存的影响。
729

被折叠的 条评论
为什么被折叠?



