Java学习记录day6

文章介绍了Java编程中的static关键字的用途,包括修饰属性和方法,以及静态类的使用。它强调了静态方法只能调用静态变量和方法,并解释了值传递和引用传递的区别。此外,还讨论了内存结构,如类加载器、方法区、栈内存和堆内存,并提到了不同类型的代码块(构造块、静态块等)的执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

书接上回

类与对象

static关键字

static的作用:

  1. 修饰一个属性:声明为static的变量实质上就是一个全局变量,其生命周期为从类被加载开始一直到程序结束;
  2. 修饰方法:无须本类的对象也可以调用该方法;
  3. 修饰一个类:该类必须是内部类(后说);
    静态类与变量通过类名直接调用:类名.静态变量/静态方法。注意,非静态方法中可以调用静态的变量和方法,而静态方法中只能调用静态的变量和方法,不能调用非静态的变量和方法。
public class Test{
	public static void main(String[] args) {
		House h;//声明一个类的变量
		h = new House();//创建实例对象
		h.kind = "别墅";
		h.Print();//非静态方法的调用需要有h这个对象
		House.Smile();//静态类直接调用
		System.out.println(House.Count);//变量的调用也一样
	}
}
public class House{
	String kind = "未知";
	static int Count = 3;
	public void Ptint(){
		System.out.println(kind + Count +"栋");
		}
	public static void Smile(){
		System.out.println("哈哈,被骗了");
		}
}

静态方法限制:

  1. 仅能调用其他static方法;
  2. 只能访问static数据;
  3. 不能以任何方式引用this和super;
    因为static的限制,所以我们再定义他的时候最好确定之后他是否是所有对象共同的属性或方法在将其定义为静态。

值传递与引用传递

有一道非常经典的面试题目:


public class Test {
    public static void main(String[] args) {
    	Integer a = 1;
    	Integer b = 2;
    	System.out.println("a 和 b 的原始的值:"+a+" "+b);
    	swap(a,b);
    	System.out.println("a 和 b 的现在的值:"+a+" "+b);
    }
 	private static void swap(Integer a, Integer b) {
		// 交换a与b的值
	}

实现变量的交换非常简单,前面已经学习过了三种交换方法,直接带入最简单的:

 	private static void swap(Integer a, Integer b) {
		// 交换a与b的值
		int c;
		c = a;
		a = b;
		b = c;
	}

完成后最后的结果却是错的,这是因为程序中只交换了形参的值,而实参却没有丝毫变化。
形参 :就是形式参数,用于定义方法的时候使用的参数,是用来接收调用者传递的参数的。 形参只有在方法被调用的时候,虚拟机才会分配内存单元,在方法调用结束之后便会释放所分配的内存单元。 因此,形参只在方法内部有效,所以针对引用对象的改动也无法影响到方法外。
实参 :就是实际参数,用于调用时传递给方法的参数。实参在传递给别的方法之前是要被预先赋值的。 在本例中 swap 方法中的a, b 就是形参,传递给 swap 方法的 a,b 就是实参。
值传递:只能把实参传递给形参,而不能把形参的值反向作用到实参上。在函数调用过程中,形参的值发生改变,而实参的值不会发生改变。
在上题中,实际内存情况:
在这里插入图片描述
引用传递:是将实参引用的地址传递给了形参,所以任何发生在形参上的改变也会发生在实参变量上。
在第一个程序中h.kind = "别墅";这就是引用传递:
在这里插入图片描述
补充:附上正确解法,该解法涉及到引用类型和拆箱装箱,就不再说明(其实我也看太懂。。。。。。)

private static void swap(Integer numa, Integer numb){ 
        int tmp = numa.intValue();
        try{         
	        Field field = Integer.class.getDeclaredField("value");
            field.setAccessible(true);
           	field.set(numa, numb);
            field.set(numb, new Integer(tmp));
        }catch(Exception e){
            e.printStackTrace();
         }
}

内存结构

在这里插入图片描述
.class:java程序编译后产生的编译文件;
类加载器:加载.class文件 ;
方法区:各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;
栈内存: 在栈内存中保存的是堆内存空间的访问地址,或者说栈中的变量指向堆内存中的变量(Java中的指针);
堆内存:堆内存用来存放由new创建的对象实例和数组;
本地方法栈:存储本地方法,比如c语言栈。
程序计数器:可以看做是当前线程所执行的字节码的行号指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都要依赖这个计数器来完成。

代码块

用大括号裹起来的代码:

  1. 普通代码块:在方法中的写的代码块;
  2. 构造块:在类中定义的代码块,在创造对象时被调用,优于构造方法;
  3. 静态代码块:在类中是使用static声明的代码块,在第一次被调用(创建对象)时被调用,只会执行一次,优于构造块;
  4. 同步代码块:多线行程中介绍;
public class Test{
	public static void main(String[] args) {
		House h1 = new House();
		House h2 = new House();
		House h = null;
	}
}
public class House{
	public House(){
		System.out.println("构造方法/n--------------");
	}
	{
		System.out.println("构造块House/n---------");
	}
	public static void Smile(){
		{
		String info = "普通代码块smile/n-----------";
		System.out.println(info);			
		}
	}
	static {
		String info = "静态代码块smile/n-----------";
	}
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值