2015.09.01 Java 学习笔记—内存分析精华

掌握以下内容足以够以后学习所用,很好,很详细,一定吃透

内存分析基础知识

  1. 栈内存和堆内存
    栈内存:保存堆内存对应的地址数据,如果想要简单的理解,就将说明为对象的名称.
    堆内存:保存真正有用的数据:指的是对象的属性内容,每一块堆内存都是一块内存地址的信息.
    这里写图片描述
    关键字new相当于计算机在内存之中自动开辟一块新的堆内存空间, 开辟完之后分配的是类里属性的默认值
    对象只有实例化之后才可以使用,如果使用了未实例化的对象,一定会出现NullPointerExceptiong,而此异常只要是你从事开发工作,一定会一直陪伴这你, 特别需要提醒的是,每当使用了关键字new操作的时候都会分配新的堆内存空间,所以如果现在实例化了两个对象呢?
    这里写图片描述
    在日后的开发中,需要开辟新的堆内存空间,那么就是用关键字new
    对象的真实数据都保存在堆内存之中,所以所谓的引用关系,指的就是同一块堆内存空间被不同的栈所指向
    这里写图片描述
    这里写图片描述
    所以在实际的开发当中尽量不要产生无用的对内存空间,所有无用的堆内存空间最终都会被gc定期回收
    2.成员变量和局部变量
    成员变量包含:实例变量和类变量.(系统会为成员变量执行默认初始化)
    实例变量:从有实例开始,实例变量就存在了,实例被销毁,实例变量销毁.
    类变量:从有类开始,类变量就存在,一个jvm 里类信息只有一个,每个jvm 最多值加载一个类一次,系统就为该实例分配一块内存
    Java程序不允许直接访问堆内存中的对象,只能通过该对象的引用操作该对象
    只要你用这个类声明变量,或者创建实例或者调用这个类的静态方法或静态field都是用到了这个类
    局部变量必须由程序员来初始化,系统不会对局部变量初始化,局部变量存放在相应方法栈中

先掌握一段简单程序内存分析

package com.buaa.day3;
/*执行详解:
 * Test test = new Test();
 * 首先在main方法栈内定义了一个局部变量test,
 * 接着在堆内存里产生Test对象,局部变量test指向此对象
 * 接着int date = 9;
 * 在main方法栈中创建局部变量 date 值为9
 * 
 ************************************************
 *
 * BirthDate d1= new BirthDate(7,7,1970);
 * 首先BirthDate d1,在stack中创建局部变量d1 ,
 * 接着public BirthDate(int d, int m, int y) {day = d;   month = m;  year = y;  },
 * 在stack里临时产生局部变量 d, m, y
 * 接着new BirthDate(7,7,1970),将参数传给在堆内存创建BirthDate对象,局部变量 d, m, y消失                                                          
 * 接着d1指向BirthDate对象(即d1存了可以找到BirthDate对象在堆内存的地址)
 * 
 ************************************************
 *
 * test.change1(date);
 * i 的值的变化是先变成9,然后继续执行变成1234,但是由于i是局部变量,当方法执行结束以后i的值自动消失,
 * 所以date的值依然是9没有改变
 *
 ************************************************
 *test.change2(d1);
 *目的是为了改变d1指向堆内存里的值
 *首先test.change2(d1);把d1传进来,d1的值传给处在stack里的局部变量b,b指向了d1指向的堆内存对象值。
 *接着
 *public void change2(BirthDate b) {//b此时是局部变量,规定传入的参数必须是BirthDate的一个引用
 *b = new BirthDate(22,2,2004);//创建对象后b不指向d1对象的内存堆,指向对象b 的内存堆
 *方法调用完毕时,b这个局部变量消失,指向对象的引用就消失了,堆内存里22,2,2004内容无栈指针,所以会被垃圾回收机制回收
 *故不能达到目的}
 *************************************************
 *
 *test.change3(d2);
 *public void change3(BirthDate b) {b.setDay(22);} 局部变量b指向了d2指向的堆内存
 *接着调用public void setDay(int d) {day = d;}此时在方法栈里产生d局部变量,将d2堆内存里的day的值传参为22,此时实现改变堆内存的对象的值
 *
 *
 *
 * */
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(1,1,2000);    
        test.change1(date);
        test.change2(d1);
        test.change3(d2);
        System.out.println("date=" + date);
        d1.display();
        d2.display();
    }

    public void change1(int i){i = 1234;}

    public void change2(BirthDate b) {b = new BirthDate(22,2,2004);}

    public void change3(BirthDate b) {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 void setDay(int d) {day = d;}

    public void setMonth(int m) {month = m;}

    public void setYear(int y) {year = y;}

    public int getDay() {return day;}

    public int getMonth() {return month; }

    public int getYear() {return year; }

    public void display() {System.out.println(day + " - " + month + " - " + year);}
}
/*执行结果:
date=9
7 - 7 - 1970
22 - 1 - 2000
*/

接着掌握这段相对复杂的程序内存分析

package com.buaa.day3;
import static java.lang.System.*;
/*程序解读:
 * Circle c1 = new Circle(new Point(1.0,2.0), 2.0);
 * 首先执行Circle c1 ,c1是一个引用类型的变量,所以给它分配一块栈内存存放一个Circle对象的引用(也就是地址),
 * 接着new Point(1.0,2.0)在堆内存里分配Point对象,
 * 接着  Circle(Point p, double r) {//把圆心定到原点上。局部变量P指向Point对象,
        o = p; //让Circle对象的成员变量o指向指向Point对象的堆内存
        radius = r;

 * 接着new Circle(new Point(1.0,2.0), 2.0);在堆内存分配Circle对象,并且让Circle对象的成员变量O指向point对象,
 * 这行代码的顺序之所以是这样是因为“=”的优先级比“new”的优先级低。
 * 
 * 执行结果:c1指向Circle对象的堆内存,Circle对象的成员变量O指向了point对象的堆内存
 * 
 * *****************************************************************
 * 
 * Circle c2 = new Circle(5.0);
 * 内存里又分配一块Circle对象,c2指向此对象
 *     Circle(double r) {
        o = new Point(0.0, 0.0);c2指向的Circle对象的成员变量O指向了point对象的堆内存,内容为0.0, 0.0
        radius = r;
    } 
 *  
 * *****************************************************************
 * 
 * c1.getO().getX()
 * c1.getO() 
 * public Point getO() { return o;//分配一块临时内存区域,此区域的值和O里的值一样,指向了Point对象的堆内存,内容为1.0,2.0

    }
 *  c1.getO().getX()返回1.0
 *  
 *  
 *  
 *  
 * */
public class TestCircle {
    public static void main(String args[]) {

        Circle c1 = new Circle(new Point(1.0,2.0), 2.0);
        Circle c2 = new Circle(5.0); 
        out.println("c1:("+c1.getO().getX()+","+c1.getO().getY()+"),"+c1.getRadius());//执行完之后main方法栈内存只剩下c1,c2
        out.println("c2:("+c2.getO().getX()+","+c2.getO().getY()+"),"+c2.getRadius());     
        out.println("c1 area = "+c1.area());
        out.println("c1 area = "+c2.area());
        c1.setO(5,6);
        c2.setRadius(9.0);
        out.println("c1:("+c1.getO().getX()+"," +c1.getO().getY()+"),"+c1.getRadius());
        out.println("c2:("+c2.getO().getX()+","+c2.getO().getY()+"),"+c2.getRadius());
        out.println("c1 area = "+c1.area());
        out.println("c1 area = "+c2.area());
        //验证一个点是否在一个圆之内
        Point p1 = new Point(5.2, 6.3);
        out.println(c1.contains(p1));
        out.println(c1.contains(new Point(10.0,9.0)));

    }
}

class Point {
    private double x;
    private double y;
    Point(double x1, double y1) { 
        x = x1; 
        y = y1;
    }
    public double getX() { return x; }
    public double getY() { return y; }
    public void setX(double i) { x = i; }
    public void setY(double i) { y = i; }
}

class Circle {
    private Point o;
    private double radius;
    Circle(Point p, double r) {//把圆心定到原点上
        o = p; 
        radius = r;
    }
    Circle(double r) {
        o = new Point(0.0, 0.0);
        radius = r;
    }

    boolean contains(Point p) {//计算一个点是否在一个圆中
        double x = p.getX() - o.getX();
        double y = p.getY() - o.getY();
        if(x*x + y*y > radius * radius) return false;
        else return true;
    }


    public void setO(double x, double y) {
        o.setX(x); 
        o.setY(y);
    }
    public Point getO() { return o;//分配一块临时内存区域,此区域的值和O里的值一样,指向了Point对象的堆内存

    }
    public double getRadius() { return radius;}
    public void setRadius(double r) { radius = r;}
    public double area() { 
        return 3.14 * radius * radius;
    }
}
/*执行结果:
c1:(1.0,2.0),2.0
c2:(0.0,0.0),5.0
c1 area = 12.56
c1 area = 78.5
c1:(5.0,6.0),2.0
c2:(0.0,0.0),9.0
c1 area = 12.56
c1 area = 254.34
true
false

*/

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值