变量分为成员变量和局部变量,根据数据类型的不同分为:
:
1:成员变量基本类型:
整型,浮点型,字符型,布尔型这些基本类型的成员变量有默认值,成员变量根据方法区中的成员变量信息创建在堆内存中;
2:成员变量引用类型:
任何类型都可以作为成员变量类型;
字符串,数组,类,接口这些引用类型的成员变量有默认值为null,直接打印就是null;
但是当你通过数组 类型的成员变量去访问类中的内容必须对它进行赋数组操作;否则会出现空指针异常。
当你通过类 类型的成员变量名去访问类中的成员必须先对它进行赋对象操作;否则会出现空指针异常。
当你通过接口 类型的成员变量去访问接口中的抽象方法先对它进行赋实现类对象操作;否则会出现空指针异常。
成员变量类型举例——数组/类/接口作为成员变量类型:
public class Class01 {
private int[] arr;//数组 类型成员变量
private Person person;//类Person类型成员变量
//Person类中有 private int age ;和private String name;
private InterfacePersonMethod interfacePersonMethod;
//InterfacePersonMethod接口中有抽象方法void eat();和void sleep();
//代码过多,省略GetterSetter方法,省略空参全参构造
测试代码
public class Test01 {
public static void main(String[] args) {
Class01 class01 = new Class01();
System.out.println(class01.getArr()); //输出结果是null
// System.out.println(class01.getArr().toString());//没赋值访问数组内容报空指针异常
// Exception in thread "main" java.lang.NullPointerException
class01.setArr(new int[5]);//数组类型成员变量使用需要赋值
System.out.println(class01.getArr()); //输出结果是[I@75412c2f
System.out.println(class01.getArr()[2]); //输出结果是0
System.out.println(class01.getPerson()); //输出结果是null
// System.out.println(class01.getPerson().getAge());//没赋值访问类内容报空指针异常
//Exception in thread "main"java.lang.NullPointerException
class01.setPerson(new Person("张嘉译", 22));//类类型成员变量使用需要赋值
System.out.println(class01.getPerson()); //输出结果是cn.itcast.day06.Person@13b6d03
System.out.println(class01.getPerson().getName()); //输出结果是张嘉译
System.out.println(class01.getInterfacePersonMethod());//输出结果是null
// class01.getInterfacePersonMethod().eat();//没赋值访问接口内容报空指针异常
// Exception in thread "main" java.lang.NullPointerException
class01.setInterfacePersonMethod(new InterfacePersonMethod() {
@Override
public void eat() {
System.out.println("人吃饭");
}
@Override
public void sleep() {
System.out.println("人睡觉");
}
});//接口类型成员变量使用需要赋值
System.out.println(class01.getInterfacePersonMethod());//输出结果是cn.itcast.day06.Test01$1@64c64813
class01.getInterfacePersonMethod().eat(); //输出结果是人吃饭
}
}
========================================================================================================================================================
3: 局部变量基本类型:
整型,浮点型,字符型,布尔型这些基本类型的局部变量作为方法的参数传入的是一个具体的值;
方法内部修改的具体值只在当前方法中有效,出了当前方法就消失了。
4:局部变量引用类型:
字符串,数组,类,接口这些引用类型的局部变量作为方法的参数传入的实际上是它在堆内存中的地址值;
方法内部修改的具体内容已经修改好存储到堆里了,出了当前方法再次访问该地址里的内容是修改过的信息。
局部变量类型举例——数组,int类型变量作方法参数类型:
public class Test01 {
public static void main(String[] args) {
int arr[]={1,3,5,};
int num=999;
System.out.println("=======");
show(arr,num);
System.out.println(num);//999
System.out.println(arr[2]);//50
System.out.println(Arrays.toString(arr)); //[1,3,50]
}
private static void show(int arr[],int num){
arr[2]=50;
num+=1;
int[] arr2={2,4,6};
arr=arr2;
System.out.println("局部变量是"+num);//局部变量是1
System.out.println(Arrays.toString(arr)); //[2, 4, 6]
}
}
输出结果:
局部变量是1000
[2, 4, 6]
======
999
50
[1,3,50]
解析:
局部变量是1000 , [2, 4, 6]的解析: 他们是方法中的局部变量,前者是基本类型,后者是引用类型,作用在当前所属的大括号;
999的解析: 定义的方法中更改局部变量为1000,但他有作用域(直接所属大括号),局部变量只在当前方法有效,一旦超出作用域(比如方法执行完弹栈后),局部变量立刻从栈内存里消失,所以仍是999;
50,[1,3,50]的解析: 数组(引用数据类型)作为参数传递时,传递的是地址值;因此,方法执行结束出栈以后,引用类型的地址值不会发生改变,就可以解释方法内部明明把arr2的地址赋给arr(修改它的地址值只在定义的方法中有效),出栈后arr存储的地址值却是原来的;同时引用类型的原有地址中的内容如果改变了是可以的,和出栈没有影响;
总结一下:当在方法中对原有地址值里的数据进行修改后,在回到main方法(方法调用处)之后,再去查看数据时,就是被更改后的最新的数据
局部变量类型举例——类,接口作方法参数类型:
public class Test02 {
public static void main(String[] args) {
//传递的是他的创建的对象的地址值
Person person = new Person("张嘉译", 20);
methodClass(person);
//传递的是他的实现类类对象的地址值
List<Integer> list = new ArrayList<>();//List是接口,Arraylist是List接口的实现类
methodInterface(list);
}
//Person类作为方法参数类型
public static void methodClass(Person person) {
System.out.println("我叫" + person.getName() + ",今年" + person.getAge() + "岁了");
}
//接口作为方法参数类型
public static void methodInterface(List<Integer> list) {
list.add(1);
list.add(2);
System.out.println(list);
}
}
解析:
方法里面可以写一个类作为方法参数类型,传递参数的时候给他传一个该类的子类对象即可;
这是多态的写法,父类类型作为方法形式参数,传递子类对象给方法。
方法里面可以写一个接口作为方法参数类型,传递参数的时候给他传一个该类的实现类对象即可;
这也运用了多态写法:接口类型作为方法形式参数,传递子类对象给方法。