前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >对象与内存控制

对象与内存控制

作者头像
迹_Jason
发布2019-05-28 12:30:09
4100
发布2019-05-28 12:30:09
举报
文章被收录于专栏:迹_Jason的AppZone

JVM的垃圾回收机制是由一条后台线程执行的,其本身也是非常消耗内存的,因此,滥用创建对象,会导致性能大大下降,对内存的分配的了解就显得尤为重要

变量分类

局部变量
  • 形参:存在于方法签名中定义的局部变量,有方法调用者为其赋值,随着方法的结束而消亡
  • 方法内部变量:在方法内部定义的局部变量,必须在方法内对其进行显示初始化,随着方法的结束而消亡
  • 代码块内部的局部变量:在代码块内定义的局部变量,必须在代码块内对其显式初始化,随着代码块结束而消亡

成员变量

  • 实例变量:非静态的成员变量,随着对象的产生,进行初始化等操作,对象结束变量也就消亡
  • 类变量:静态的成员变量,带有static修饰符,随着类初始化产生,随着类消失而消失

在创建变量的时候,一定要合法的前向引用。其含义就是先定义的变量不能引用后定义的变量,反之则可以

变量的内存分配

在同一个JVM中每一个类只会存在一个Class对象,因此JVM只要分配一块内存空间给类变量就可以了,而实例变量则每次创建对象都要为其分配一块内存,几个实例就要创建几块内存空间

实例变量的初始化时机

  1. 定义变量的时候
  2. 代码块中
  3. 构造器中

定义实例变量时指定的初始值、初始化块中为实例变量指定初始值的语句的地位是平等的,当经过编译器处理后,他们都将被提取到构造器中,也就是说在编译后,初始化都会被放在构造器中按先后顺序进行初始化赋值

类变量初始化时机

同一个JVM中,类变量只能初始化一次

  1. 定义变量的时候
  2. 静态代码块

父类构造器

在创建Java对象的时候,都会先去执行该类的父类对象的非静态代码块和构造器,最后才是该类的非静态代码块和构造器

  • 所谓的隐式调用和显式调用,其实就是有没有用super去调用父类的构造器的区别。
  • 如果父类还没被初始化过,则会最先对类变量进行初始化

访问子类对象的实例变量

子类的方法可以访问父类的实例变量,这是因为子类继承父类就会获得父类的成员变量和方法,但父类的方法不能访问子类的实例变量,因为父类无法知道哪个子类继承他

而且子父类中的成员变量(类变量和实例变量)是相互独立的,父类中的成员变量不会被子类中同名的变量覆盖

代码语言:javascript
复制
class Base {
	static int count = 2;
}

class Mid extends Base {
	static int count = 20;
	
}

public class Sub extends Mid {
	static int count = 200;

	public static void main(String[] args) {
		// 创建一个Sub对象
		Sub s = new Sub();
		// 将Sub对象向上转型后赋为Mid、Base类型的变量
		Mid s2m = s;
		Base s2b = s;
		// 分别通过3个变量来访问count实例变量
		System.out.println(s.count);
		System.out.println(s2m.count);
		System.out.println(s2b.count);
	}
}

结果

200 20 2

当创建Sub的时候,会初始化Base、Mid和Sub三个对象,同时也就存在三个count变量了,也就是说有三块内存保存着这三个对象和count变量,以s2m变量为例,s2m拥有的地址是Sub对象的堆地址,但s2m变量类是是Mid,则会去寻找Mid下的变量值 也就说成员变量的值取决于声明该变量声明时是所用的类型

http://img.blog.csdn.net/20160526151712404
http://img.blog.csdn.net/20160526151712404

访问子类对象的方法

子类可以重写父类的方法,子类也可以通过super的方式调用父类的方法,在多态的情况下,子类重写的方法会覆盖掉父类的方法

代码语言:javascript
复制
class Base{
	int count =2;
	public void display(){
		System.out.println(this.count);
	}
}
class Derived extends Base{
	int count =20;
	@Override
	public void display() {
		System.out.println(this.count);
	}
}
public class FieldAndMethod {
	public static void main(String[] args) {
		Base b=new Base();
		System.out.println(b.count);
		b.display();
		Derived d=new Derived();
		System.out.println(d.count);
		d.display();
		Base db=new Derived();
		System.out.println(db.count);
		db.display();
		Base b2d=d;
		System.out.println(b2d.count);
	}
}

结果

2 2 20 20 2 20 2

一切在你执行这段代码之后,你就会明白一切了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-05-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 变量分类
    • 局部变量
    • 成员变量
    • 变量的内存分配
    • 实例变量的初始化时机
    • 类变量初始化时机
    • 父类构造器
    • 访问子类对象的实例变量
    • 访问子类对象的方法
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档