一:堆内存与栈内存
先创建一个Dog类,标注它的属性(特征即属性)和方法(行为即方法)
public class Dog {
/**
* 品种
*/
String breed;
/**
* 尺寸
*/
int size;
/**
* 颜色
*/
String color;
/**
* 年龄
*/
int age;
public void eat(){
}
public void run(){
}
public void sleep(){
}
}
然后在 Test包中 实例化出两个对象(dog01和dog02),输出并判断它们是否相等
结果肯定为false
import org.junit.jupiter.api.Test;
public class DogTest {
@Test
public void test01(){
Dog dog = new Dog();
}
@Test
public void test02(){
Dog dog01 = new Dog();
Dog dog02 = new Dog();
System.out.println(dog01 == dog02);
}
@Test
public void test03(){
Dog dog01 = new Dog();
Dog dog02 = new Dog();
System.out.println(dog01 == dog02);
}
}
原因:栈中的dog01会指向堆中的newDog(),栈中的dog02会指向堆中的一个新的
newDog(),dog01 和 dog02在堆中的存储空间地址不同,因为是一一对应
的关系,所以会出现两个newDog()存储空间,所以二者不会相等。
二:静态方法与非静态方法:
先创建一个Person类,标注它的属性(特征即属性)和方法(行为即方法)
然后给sleep方法加上static静态修饰符
public class Person {
/**
* 昵称
*/
String nickname;
/**
* 性别 1代表男 0代表女
*/
int gender;
/**
* 年龄
*/
int age;
public void eat(){
System.out.println("一顿不吃饿得慌");
}
public static void sleep(){
System.out.println("在哪里跌倒,就在那里睡一觉");
}
public void run(){
System.out.println("跑过博尔特");
}
}
然后再在 测试包(PersonTest) 里调用一下我们创建好的Person类里的方法
/**
*静态方法可以通过类名点方法名的方式调用
*但是不能通过类名点方法名的方式调用非静态方法
*可以通过类的实例化对象名点方法名的方式调用静态方法
*也可以通过类的实例化对象名点方法名的方式调用非静态方法
*静态方法可以调用静态方法但是无法直接调用非静态方法
*非静态方法可以调用非静态方法与可以调用静态方法
*/
public class Person01Test {
@Test
public void test01(){
// 静态方法可以通过类名点方法名的方式调用
// 但是不能通过类名点方法名的方式调用非静态方法
Person.sleep();
}
@Test
public void test02(){
// 静态方法可以通过类名点方法名的方式调用
// 但是不能通过类名点方法名的方式调用非静态方法
Person.sleep();
Person person01 = new Person();
// 可以通过类的实例化对象名点方法名的方式调用静态方法
// 也可以通过类的实例化对象名点方法名的方式调用非静态方法
person01.eat();
person01.run();
person01.sleep();
}
}
三:成员变量与局部变量以及二者之间的区别:
首先创建一个Variable类
在方法之中,类之内,声明啦三个数据类型为int的变量
count,x,未用静态修饰符修饰 而y用静态修饰符修饰,
用于测试包中体现调用成员变量时的区别
/**
* 成员变量 在类中定义,用来描述对象将要有什么<br>
* 局部变量 在类的方法中定义,在方法中临时保存数据<br>
* 同名变量不同
* -在同一个方法中,不允许有同名的局部变量
* -在不同的方法中,可以有同名的局部变量
* 成员变量和局部变量的区别<br>
* a)作用域不同
* -局部变量的作用域仅限于定义它的方法
* -成员变量的作用域在整个类内部都是可见的
* b)初始值不同
* -成员变量有默认的初始值
* -局部变量没有默认的初始值,必须自行设定初始值
* c)存储位置不同
* -成员变量是在对象创建以后存在于堆中,对象回收时,成员变量消失
* -局部变量是在方法被调用时存在于栈中,方法调执行结束,从栈中清除
* d)生命周期不同
* -对象的创建而创建,对象回收时,成员变量消失
* -随着方法的调用被创建,方法执行结束,从栈中清除
*/
public class Variable {
/**
* 成员变量
*/
public int count;
public int x;
public static int y;
public void fun01() {
int a = 10;
System.out.println("fun01()中a的值 >>> " + a);
}
public void fun02() {
int a = 20;
System.out.println("fun02()中a的值 >>> " + a);
}
public void fun03() {
int a = 30;
int b;
System.out.println("fun03()中a的值 >>> " + a);
// The local variable b may not have been initialized
// java: 可能尚未初始化变量b
// 局部变量 如果被调用初始化
// System.out.println("fun03()中b的值 >>> " + b);
}
public void fun04() {
System.out.println("成员变量count的值 >>> " + count);
}
public void fun05() {
System.out.println("成员变量count的值 >>> " + count++);
}
public void fun06() {
System.out.println("成员变量count的值 >>> " + ++count);
}
public void fun07(){
System.out.println("非静态成员变量x的值 >>> " + ++x);
System.out.println("静态成员变量y的值 >>> " + ++y);
}
}
然后再在 测试包(VariableTest) 里调用一下我们创建好的Variable类里的方法,
注意:调用成员变量和局部变量的区别,以及调用成员变量和成员变量之间的区别。
import org.junit.jupiter.api.Test;
public class VariableTest {
@Test
public void test01(){
Variable variable = new Variable();
// fun01()中a的值 >>> 10
variable.fun01();
// fun02()中a的值 >>> 20
variable.fun02();
// fun03()中a的值 >>> 30
variable.fun03();
// 成员变量count的值 >>> 0
variable.fun04();
// 成员变量count的值 >>> 0
variable.fun05();
// 成员变量count的值 >>> 2
variable.fun06();
}
@Test
public void test02(){
Variable variable = new Variable();
// 成员变量count的值 >>> 1
variable.fun06();
// 成员变量count的值 >>> 2
variable.fun06();
}
@Test
public void test03(){
Variable variable01 = new Variable();
Variable variable02 = new Variable();
// 成员变量count的值 >>> 1
variable01.fun06();
// 成员变量count的值 >>> 2
variable01.fun06();
// 成员变量count的值 >>> 1
variable02.fun06();
}
@Test
public void test04(){
Variable variable01 = new Variable();
Variable variable02 = new Variable();
// 非静态成员变量x的值 >>> 1
// 静态成员变量y的值 >>> 1
variable01.fun07();
// 非静态成员变量x的值 >>> 1
// 静态成员变量y的值 >>> 2
variable02.fun07();
// 非静态成员变量x的值 >>> 2
// 静态成员变量y的值 >>> 3
variable01.fun07();
// 非静态成员变量x的值 >>> 2
// 静态成员变量y的值 >>> 4
variable02.fun07();
}
}
注意:成员变量中y被static静态修饰符修饰后,它的存储地址就不在堆内存中啦
而y会存储在另一个新的存储区域内,此时Variable01() 和 Variable02()
会轮番调用在新区域内的y,第一次被Variable01()调用后++,y变为1,第二次
被Variable02()调用后++,变为2,以此类推,最终为4。
非静态成员变量仅仅能在对象内部共享数据
而静态成员变量可以在多个对象之间共享数据
四:匿名对象( 没有引用类型变量指向的对象)
先创建一个Temp类
public class Temp {
public void laugh(){
System.out.println("二十四笑头一笑,仰天长笑");
}
}
再在测试包中的TempTest类中调用Temp类
调用对象时不用实例化(如下面代码的比较)
import org.junit.jupiter.api.Test;
/**
* 普通变量 直接赋值
* 引用变量 引用了一个内存地址
* 匿名对象 没有引用类型变量指向的对象
* 适用场景:使用之后直接从内存中消失 不会长期占用内存 适用于仅仅偶尔使用的场景
* 不适用场景:因为使用之后直接从内存中消失 如果频繁使用该对象需要频繁在内存中创建和回收该对象 创建
和回收过程都要消耗系统资源 建议频繁使用对象尽量使用引用类型变量引用
*/
public class TempTest {
@Test
public void test01() {
Temp temp = new Temp();
temp.laugh();
temp.laugh();
temp.laugh();
}
@Test
public void test02() {
// Temp temp = new Temp();
// temp.laugh();
new Temp().laugh();
}
}