一. 方法
在Java语言当中应该有这样一个机制:
- 某个功能代码只需要写一遍
- 要使用这个功能,只需要给这个功能传递具体的数据
- 这个功能完成之后返回一个最终的结果。
这样代码就可以重复使用了,提高代码的复用性。【这就是 “方法” 】
使用这个方法我们称为 “调用/invoke”
1. 方法的本质
方法就是一段代码片段,并且这段代码片段可以完成某个特定的功能,并且可以被重复使用。 方法,对应的英语单词:Method,在 C 语言中叫做函数:Function、
方法定义在类体中,在一个类当中可以定义多个方法,方法编写的位置没有先后顺序,可以随意。
方法体中不能再定义方法!!!!!!
2. 方法的基础语法
2.1. 语法结构
[修饰符列表] 返回值类型 方法名(形式参数列表){
方法体;
}
2.2 对以上语法结构进行解释说明:
2.2.1. 关于修饰符列表
- 可选项,不是必须的
- 目前统一写成public static
- 方法的修饰符列表当中”有static关键字”的话,怎么调用这个方法?
类名.方法名(实际参数列表);
2.2.2. 返回值类型
1、什么是返回值?
一个方法是可以完成某个特定功能的,这个功能结束之后大多数都是需要返回最终执行结果的,执行结果可能是一个具体存在的数据。而这个具体存在的数据就是返回值。
2、返回值类型?
返回值就是一个具体存在的数据,数据都是有类型的,此处需要指定的是返回值的具体类型。
3、返回值类型都可以指定哪些类型呢?
java任意一种类型都可以,包括基本数据类型和所有的引用数据类型。
4、也可能这个方法执行结束之后不返回任何数据,java中规定,当一个方法执行结束之后不返回任何数据的话,返回值类型位置必须编写:void 关键字。
5、返回值类型可以是: byte,short,int,long,float,double,boolean,char,string,void…
6、返回值类型若不是 void,表示这个方法执行结束之后必须返回一个具体的数值。当方法执行结束的时候,没有返回任何数据的话,编译器报错。怎么返回值呢?代码怎么写呢?“return 值;”并且要求“值”的数据类型必须和“方法的返回值类型”一致,不然编译器报错。
7、返回类型是void的时候,在方法体当中不能编写“return 值;”这样的语句。但是要注意可以编写“return;”这样的语句。
8、只要带有关键字的语句执行,return语句所在的方法结束。【不是JVM结束,是return所在的方法结束】
2.2.3. 方法名
- 只要是合法的标识符就行
- 方法名最好见名知意
- 方法名最好是动词
- 方法名首字母要求是小写,后面每个单词首字母大写
2.2.4 形式参数列表:简称形参
- 形参是局部变量:int a;double b;…
- 形参的个数可以是 0~N 个
- 多个形参之间用“逗号”隔开
- 形参中起决定性作用的是形参的数据类型,形参的名字就是局部变量的名字。
- 方法在调用的时候,实际给这个方法传递的真实数据被称为:实际参数,简称实参
- 实参列表和形参列表必须满足:
- 数量相同
- 类型对应相同
2.2.5. 方法体必须由大括号括起来,方法体中的代码有顺序
实例:
//public表示公开的
//class表示定义类
//MethodTest是一个类名
public class MethodTest{ //表示定义一个公开的类,起名MethodTest,由于是公开的类,所以源文件名必须为:MethodTest
//类体
//类体中不能出现直接编写java语句,除声明变量之外
//方法出现在类体当中
//方法
//public表示公开的
//static表示静态的
//void表示方法执行结束后不返回任何数据
//main是方法名:主方法
//(String[] args):形式参数列表,其中String[]是一种引用数据类型,args是一个局部变量的变量名
//所以以下只有args这个局部变量的变量名是随意的
//主方法就需要这样固定编写,这是程序的入口。【SUN公司规定的,必须这样写】
public static void main(String[] args){
//这里的程序是一定会执行的
//main方法是JVM负责调用的,是一个入口的位置
//从这里作为起点开始执行程序
//既然是这样,我们就可以在这里编写java语句来调用其他方法
//调用MethodTest的sum方法,传递两个实参
MethodTest.sum(10,20);//(10,20)实参列表
//注意:方法体当中的代码是有顺序的,遵循自上而下的顺序以此执行
//上一行代码的程序执行不结束,无法执行下一行代码。
//一个方法可以被重复使用,重复调用
int a=100;
MethodTest.sum(a,500);// (a,500)实参列表
//再次调用方法
int k=90;
int f=10;
MethodTest.sum(k,f);//(k,f)实参列表
}
//自定义方法,不是程序的入口
//方法的作用:计算两个int类型数据的和,不要求返回结果,但是要求将结果直接输出到控制台
//修饰符列表:public static
//返回值类型:void
//方法名:sum
//形式参数列表:(int x,int y)
//方法体:主要任务是求和之后输出计算结果
public static void sum(int x, int y){
System.out.println(x+'+'+ y +'='+ (x+y))
}
}
3. 方法怎么调用?
方法只定义不去调用是不会执行的,只有在调用的时候才会执行。
语法规则:《方法的修饰符列表当中有static》
类名.方法名(实参列表);<这是一条java语句,表示调用某个类的某个方法,传递这样的实参。>
二. Java语言的方法
实例
public class MethodTest01(){
public static void sum(int a,int b){
System.out.println(a+"+"+b+"="+(a+b));
//调用doSome方法
MethodTest.doSome();
}
//主方法
public static void main(String[] args){
//调用sum方法
MethodTest.sum(1,2);
}
public static void doSome(){
System.out.println("do some!");
}
}
以上代码了看出:方法的调用不一定在main方法当中。只要是程序可以执行到的位置,都可以调用其他的方法。
1. 方法调用的时候实参和形参要求个数对应相同,数据类型对应相同。
类型不同的时候要求能够进行相应的自动类型转换
public class MethodTest02(){
//主方法
public static void main(String[] args){
MethodTest02.sum();//编译错误:参数数量不同
MethodTest02.sum(true,false);//编译错误:实参和形参的类型不是对应相同的
MethodTest02.sum(10L,20L);//编译通过
MethodTest02.sum(10,20);//编译通过:存在自动类型转换:int-->long
MethodTest02.sum(3.0,20);//编译错误:参数类型不是对应相同的
MethodTest02.sum((long)3.0,20);//编译通过
}
public static void sum(long a,long b){
System.out.println(a+"+"+b+"="+(a+b));
}
}
2. 方法调用
1、方法的修饰符列表当中有static字,完整的调用方法是:类名 . 方法名(实参列表)
2、但是,有时候 “ 类名.” 可以省略,什么情况下可以省略呢?
- 对于方法的修饰符列表当中有static关键字的:“类名.” 可以省略不写。
- 调用同个类中的方法可省略不写
public class MethodTest03(){
public static void main(String[] args){
System.out.println("main begin");
m1();
System.out.println("main over");
}
public static void m1(){
System.out.println("m1 begin");
m2();
System.out.println("m2 over");
}
public static void m2(){
System.out.println("m2 begin");
m3();
System.out.println("m2 over");
}
public static void m3(){
System.out.println("m3 begin");
System.out.println("m3 over");
}
}
输出结果:

方法中的代码是自上而下的顺序依次执行的
2.1. 方法的返回值类型不是void的时候
- 返回值类型不是void的时候:要求方法必须保证百分百的执行“return 值;”这样的语句来完成值的返回。没有这个语句编译器会报错。
- 一个方法有返回值的时候,当我们调用这个方法的时候,方法返回了一个值,对于调用者来说,这个返回值可以选择接收,也可以选择不接收。
public class MethodTest04(){
public static void main(String[] args){
//调用方法
divide(10,3);//这里没有接收这个方法的返回数据
//这里接收返回值
//采用变量接收
//变量的数据类型需要和返回值的数据类型相同,或者可以自动类型转换
int i = divide(10,3);
}
` /*
需求:
请定义并实现一个方法,该方法可以计算两个int类型数据的商,
要求将最终计算结果返回给调用者。
*/
//编译错误:缺少返回值
/*public static int divide(int a, int b){
return;
}
//编译错误:方法定义的时候要求返回一个int类型,此时返回布尔类型,类型不兼容
public static int divide(int a, int b){
return true;
}
//可以:但是具体方法体中编写的代码无法满足当前的需求
public static int divide(int a, int b){
return 1;
}
public static int divide(int a, int b){
int c=a/b;
return c;
}*/
public static int divide(int a, int b){
return a/b;
}
}
2.2. 深入return语句
- 带有return关键字的java语句只要执行,所在的方法执行结束。
- 在“同一个作用域”当中,return语句下面不能编写任何代码,因为这些代码永远都执行不到,所以编译报错。
public class MethodTest05(){
public static void main(String[] args){
int reValue=m();
System.out,println(reValue);
}
//编译报错:缺少返回语句,以下程序编译器认为无法百分百保证“return 1;”会执行
/*public static int m(){
int a=10;
if(a>3){
return 1;
}
}
*/
public static int m(){
int a=10;
if(a>3){
return 1;
//这里不能编写代码,编译错误,因为无法执行访问的语句
//System.out.println("Hello");
}
//这里的代码可以执行
System.out.println("Hello");
return 0;
}
}
在返回值类型是void的方法当中使用“return;”语句。“return;”语句当中出现在返回值为void的方法当中主要是为了终止方法的执行。
return;直接终止方法;break只是终止循环。
return更强
三. 方法执行过程中内存分析
1. 方法在执行过程当中,在JVM中的内存是如何分配的呢,内存是如何变化的?
方法只定义,不调用,是不会执行的,并且在JVM中也不会给该方法分配“运行所属”的内存空间。只有在调用这个方法的时候,才会动态的给这个方法分配所属的空间。
在JVM内存划分上有这样三块主要的内存空间:
- 方法区内存
- 堆内存
- 栈内存
关于栈数据结构:
- 栈:stack,是一种数据结2、数据结构反应的是数据的存储形态。
- 数据结构是独立的学科,不属于任何编程语言的范畴,只不过在大多数编程语言当中要使用数据结构。
- 作为程序员需要提前精通:数据结构+算法【计算机专业必修的一门语言】
- 常见的数据结构:数组、队列、栈、链表、二叉树、哈希表…
方法代码片段存在哪里?方法执行的时候执行过程的内存在哪里分配?
- 方法片段属于.class字节码文件的一部分,字节码文件在类加载的时候,将其放到了方法区当中。所以JVM中的三块主要的内存空间中的方法区内存最先有数据,存放了代码片段。
- 代码片段虽然在方法区内存当中只有一份,但是可以被重复调用。每一次调用这个方法的时候,需要给该方法分配独立的活动场所,在栈内存中分配。【栈内存中分配方法运行的所属空间】
方法在调用的时候,会给该方法分配独立的内存空间,在栈中分配,此时发生压栈动作,方法执行结束之后,给该方法分配的内存空间全部释放,此时发生弹栈动作。
- 压栈:给方法分配内存。
- 弹栈:释放该方法的内存空间。
局部变量在栈中存储。局部变量在运行阶段内存在栈中分配。

栈内存:
- 是为 java 方法提供运行空间的
- 方法一旦被调用就会在栈中创建对应的栈帧,而方法的整个执行过程就是方法对应的栈帧从入栈到出栈的过程。换言之,就是方法被调用进栈(压栈入栈),方法执行结束出栈(弹栈)。
- 栈是先进后出后进先出(先被调用的方法最后结束,后被调用的方法最先结束)
- 栈中的变量都是属于方法的,所以都是局部变量,且局部变量必须初始化值。
- 栈生命周期与其所属线程的生命周期一致,可以认为栈具有自动销毁机制。
堆内存:
- 是为实体对象来开辟空间的,换言之就是实体对象的空间都在堆中开辟。凡是被 new 出来的都是对象。
- 堆中的变量是对象变量,因为是属于对象的,且是随着对象的创建而产生随着对象的销毁而销毁。
- 堆中的变量(对象变量)都有默认值:
- 整数:0
- 浮点型:0.0
- 布尔型:false
- char型:”
- 对象:null
- 堆没有自动销毁机制,它里面的垃圾由垃圾回收器负责收集(通过收集算法判断哪个对象属于垃圾然后再清理)
- 堆中的空间都有一个16进制的首地址作为地址进行区分。
方法区:
方法区中存放已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
常量是存放在方法区中的运行时常量池中的。
重点:方法调用的时候,在参数传递的时候,实际上传递得是变量中保存的那个“值”传过去了。
四. 方法重载(overload)
- 功能虽然不同,但是“功能相似”的时候,方法重载机制可以让相似的方法就像在用一个方法一样。【Java支持这种机制而有些语言则不支持,例如JavaScript】
- 功能相似的时候,方法名可以相同。
1. 什么时候考虑使用方法重载?
- 功能相似的时候,尽可能让方法名相同【但是功能不同/不相似的时候,尽可能让方法名不同】
2. 什么条件满足之后构成了方法重载
- 在同一个类当中
- 方法名相同
- 参数列表不同:
- 数量不同:
public static void m1(){} 与 public static void m1(int a){} - 顺序不同:
public static void m2(int a,double b){} 与 public static void m2(double a, int b){} - 类型不同:
public static void m3 (int x){} 与 public static void m3(double x){}
- 数量不同:
方法重复,编译错误。
public static void m4(int a,int b){}
public static void m4(int b,int a){}
3. 方法重载和什么有关系,和什么没有关系
- 方法重载和方法名+参数列表有关系
- 方法重载和返回值类型无关
- 方法重载和修饰符列表无关
五. 方法递归
- 什么是递归?
即:方法自身调用自身。
a(){
a();
}
- 递归是很耗栈内存的,递归算法可以不用的时候尽量别用。
- 以下程序运行的时候发生这样的一个错误【不是异常,是错误 error】:
Java. Lang. StackOverflowError
栈内存溢出错误
错误发生无法晚挽回,只有一个结果。就是 JVM 停止工作。 - 递归必须有结束条件,没有结束条件一定会发生栈内存溢出错误。
- 递归即使有了结束条件,即便结束条件是正确的,也可能会发生栈内存溢出错误,因为递归太深了。
注意:
- 递归可以不使用尽量别用。
- 但是有些情况下该功能的实现必须依靠递归方式。
例子
递归计算前n个数的和:
public class RecursionTest01{
publci static void main(String[] args){
int n=4;
int reValue=sum(n);
System.out.println(reValue);
}
public static int sum(int n){
if(n==1){
return 1;
}
return n+sum(n-1);
}
}
递归计算n的阶乘:
public class RecursionTest02{
publci static void main(String[] args){
int n=5;
int reValue=method(n);
System.out.println(reValue);
}
public static int method(int n){
if(n==1){
return 1;
}
return n*method(n-1);
}
}
六. 面向对象和面向过程的区别
面向过程:
主要关注点是:实现的具体过程,因果关系【集成显卡的开发思路】
优点: 对于业务逻辑比较简单的程序,可以达到快速开发,前期投入成本较低。
缺点: 采用面向过程的方式开发很难解决非常复杂的业务逻辑,另外面向过程的方式导致软件元素之间“耦合度”非常高,只要其中一环出现了问题,整个系统受到影响,导致最终的软件扩展力差。另外,由于没有独立体的概念,所以无法达到组件复用。面向对象:
主要关注点是:主要关注对象【独立体】能完成哪些功能。【独立显卡的开发思路】
优点: 耦合度低,扩展能力强。更容易解决现实世界当中更复杂的业务逻辑,组件复用性强。
缺点: 前期投入成本高,需要进行独立体的抽取,大量的系统分析与设计。
C 语言是纯面向过程的,C++半面向对象、Java 纯面向对象
七. 面向对象的三大特征
- 封装
- 继承
- 多态
注:所有面向对象的编程语言都有这三大特征。
采用面向对象的方式开发一个软件,生命周期当中:【整个生命周期中贯穿使用OO面向对象方式】
- 面向对象的分析:OOA
- 面向对象的设计:OOD
- 面向对象的编程:OOP
八. 类的对象的概念
什么是类?
- 类在现实世界当中是不存在的,是一个模板,是一个概念。是人类大脑思考抽象的结果。
- 类代表了一种事物。
- 在现实世界中,对象 A 与对象 B 之间具有共同特征,进行抽象总结出一个模板,这个模板被称为类。
什么是对象?
- 对象是实际存在的个体。现实世界当中实际存在。
软件开发的过程:
- 程序员先观察现实世界,从现实世界当中寻找对象
- 寻找了 N 个对象之后,发现所有的对象都有共同特征
- 程序员在大脑中形成一个模板【类】
- Java 程序员可以通过 java 代码来表述这个类
- Java 程序中有了类的定义
- 然后通过类就可以创建对象
- 有了对象之后,可以让对象直接协作起来形成一个系统。
类–【实例化】->对象
对象又被称为实例/instance
对象–【抽象】–>类
重点:
- 类描述的是对象的共同特征。
- 共同特征例如:身高特征
这个身高特征在访问的时候,必须先创建对象,通过对象去访问这个特征。因为这个特征具体的某个对象上之后,值不同。有的对象身高 1.80,有的对象身高 2.80.
一个类主要描述什么信息呢?
一个类主要描述的是:状态+动作。 状态信息:名字、身高、性别、年龄 动作信息:吃、喝、玩、乐
- 状态–>一个类的属性
- 动作–>一个类的方法
类{
属性; //描述对象的状态信息
方法; //描述对象的动作信息
}
注意:状态和动作当具体到某个对象上之后,发现最终的结果可能不一样。
九. 类的定义
语法结构:
[修饰符列表] class 类名{
属性;
方法;
}
重点:属性通常是采用一个变量的形式来完成定义的。
定义一个类,类名Student
Student是一个类。代表了所有的学生对象,是一个学生模板
public class Student{//定义一个公开的类
//属性【描述的是对象的状态信息】
//属性通常采用变量的方式来定义
//在类体当中,方法体之外定义的变量被称为“成员变量”
//成员变量没有赋值,系统赋默认值:一切向0看齐。
int no;//学号
String name;//姓名
boolean sex;//性别
int age;//年龄
String address;//住址
//方法
//方法描述的是对象的动作信息
//当前例子就只描述属性,不描述方法。
}
Java语言中所有的class都属于引用数据类型。
十. 对象的创建和使用
public class OOTest01{
publci static void main(String[] args){
int i=10;
Student s = new Student();
int StuNo=s.no;
System.out.println("学号 =" + StuNo);//0【默认值】
System.out.println("学号 =" + s.no);//0【默认值】
s.no=10;
System.out.println("学号 =" + s.no);//10
//再通过类实例化一个全新的对象
//stu是一个引用
//stu同时也是一个局部变量
//Student是变量的数据类型
Student stu = new Student();
System.out.println("学号 =" + stu.no);// 0
System.out.println("学号 =" + Student.no);//编译错误,不能直接采用“类名”的方式访问
//因为no是实例变量,对象级别的变量,变量存储在java对象的内部,必须先有对象,通过对象才能访问no这个实例变量,不能直接通过“类名”访问
}
}
//学生类
//学生类是一个模板
//描述了所有学生的共同特征【状态+行为】
//当前类只描述学生的状态信息【属性】
public class Student{
//类体=属性+方法
//属性【存储数据采用变量的形式】
//由于变量定义在类体当中,方法体之外,这种变量称为成员变量
//所有学生都有学号信息
//但是每一一个学生的学号都是不同的
//所以要访问这个学号必须先创建对象,通过对象去访问学号信息
//学号信息不能直接通过"类"去访问,所以这种成员变量又被叫做:实例变量
//对象又被称为实例,实例变量又被称为对象变量。【对象级别的变量】
//不创建对象,这no变量的内存空间是不存在的,只有创建了对象,这个no变量内存空间才会创建。
int no;
String name;//姓名
boolean sex;//性别
int age;//年龄
String address;//住址
- 通过一个类可以实例化 N 个对象,
- 实例化对象的语法:new 类名 ()
- New 是 java 语言当中的一个运算符
- New 运算符的作用是创建对象,在 JVM 堆内存当中开辟新的内存空间
- 方法区内存:在类加载的时候,class 字节码代码片段被加载到该内存空间当中。
- 栈内存(局部变量):方法代码片段执行的时候,会给该方法分配内存空间,在栈内存中压栈。
- 堆内存:new 的对象在堆内存中存储
对于 Student s = new Student ();
- Student 是一个引用数据类型
- S 是一个变量名
- New Student () 是一个学生对象
- S 是一个局部变量【在栈内存中存储】:引用
- 什么是对象? New 运算符在堆内存中开辟的内存空间称为对象。
- 什么是引用? 引用是一个变量,只不过这个变量中保存了另一个 java 对象的内存地址。
- Java 语言当中,程序员不能直接操作堆内存,java 中没有指针,不像 C 语言
- Java 语言当中,程序员只能通过“引用”去访问堆内存当中对象内部的实例变量。
1. 访问实例变量的语法格式:
读取数据:引用.变量名
修改数据:引用.变量名 = 值int StuNo=s.no;
局部变量在栈内存中存储
成员变量中的实例变量在堆内存的java对象内部存储
实例变量是一个对象一份,100个对象有100份
public class Customer
{
int id;
}
public class OOTest02
{
public static void main(String[] args){
Customer c= new Customer();
System.out.println(c.id); //0
c=null;
//以下程序编译可以通过,因为符合语法
//运行出现空指针异常
//空引用访问“实例”相关的数据一定会出现空指针异常
//java.lang.NullPointerException
System.out.println(c.id);
}
}
“实例”相关的数据表示:这个访问的时候必须有对象的参与。这种数据就是实例相关的数据。
重点: 实例变量必须先创建对象,通过引用的方式访问,不能直接使用 类名. 的方式访问
十一. 内存分析
JVM ( Java 虚拟机) 主要包括三块内存空间. 分别是: 栈内存、堆内存、方法区内存。
堆内存和方法区内存各有 1 个。一个线程一个栈内存。
方法调用的时候, 该方法所需要的内存空间在栈内存中分配, 称为压栈。方法执行结束之后, 该方法所属的内存空间释放, 称为弹栈。
栈中主要存储的是方法体当中的局部变量。
方法的代码片段以及整个类的代码片段都被存储到方法区内存当中, 在类加载的时候这些代码片段会载入。
在程序执行过程中使用 new 运算符创建的 java 对象. 存储在堆内存当中。对象内部有实例变量, 所以实例变量存储在堆内存当中。
变量分类:
- 局部变量[方法体中声明]
- 成员变量[方法体外声明]
- 实例变量[前边修饰符没有 static]
- 静态变量[前边修饰符中有 static]
静态变量存储在方法区内存当中。[先背会]
三块内存当中变化最频繁的是栈内存, 最先有数据的是方法区内存, 垃圾回收器主要针对的是堆内存。
垃圾回收器[自动垃圾回收机制、GC 机制]什么时候会考虑将某个 java 对象的内存回收呢?
- 当堆内存当中的 java 对象成为垃圾数据的时候. 会被垃圾回收器回收。
什么时候堆内存中的 java 对象会变成垃圾呢?
- 没有更多的引用指向它的时候。这个对象无法被访问, 因为访问对象只能通过引用的方式访问。
十二. 构造方法
1. 关于java类中中的构造方法:
1、构造方法又被称为构造函数/构造器/Constructor
2、构造方法语法结构: [修饰符列表] 构造方法名 (形式参数列表){ 构造方法体; }
3、回顾普通方法的语法结构: [修饰符列表] 返回值类型方法名 (形式参数列表){ 方法体; }
4、对于构造方法来说,“返回值类型”不需要指定,并且也不能写 void。只要写上 void,那么这个方法就成为普通方法了。
5、对于构造方法来说,构造方法的方法名必须与类名保持一致。
6、构造方法的作用?
- 构造方法存在的意义是,通过构造方法的调用,可以创建对象。
7、构造方法应该怎么调用?
- 普通方法是这样调用的:方法修饰符中有 static 的时候:类名. 方法名(实参列表)、方法修饰符列表中没有 static 的时候:引用. 方法名(实参列表)
- New 构造方法名(实参列表)
8、构造方法调用执行之后,有返回值吗?
- 每一个构造方法实际上执行结束之后都有返回值,但是这个“return 值;”这样的语句不需要写。构造方法结束的时候 java 程序自动返回值。
- 并且返回值类型是构造方法所在类的类型。由于构造方法的返回值类型就是类本身,所以返回值类型不需要编写。
9、注释和取消注释:Ctrl + /、多行注释:ctrl + shift +/\
10、当一个类中没有定义任何构造方法的话,系统默认给该类提供一个无参数的构造方法,这个构造方法被称为缺省构造器。
11、当一个类显示的将构造方法定义出来了,那么系统则不再默认为这个类提供缺省构造器。建议开发中手动的为当前类提供无参数的构造方法。因为无参数的构造方法太常用了。
2. 构造方法的作用
- 1、创建对象
- 2、创建对象的同时,初始化实例变量的内存空间。
成员变量之实例变量,属于队象级别的变量,这种变量必须先有对象才能有实例变量。
实例变量没有手动赋值的时候,系统默认赋值,那么这个系统默认赋值是在什么时候完成的呢?是在类加载的时候么?
- 不是的,因为类加载的时候只加载了代码片段,还没来得及创建对象。所以此时实例变量并没有初始化。
- 实际上,实例变量的内存空间是在构造方法执行过程当中完成开辟的,完成初始化的。
- 系统在默认赋值的时候,也是在构造方法执行过程当中完成的赋值。
十三. 对象与引用
1. 对象与引用的概念
- 对象:目前在使用 new 运算符在堆内存中开辟的内存空间称为对象。
- 引用:是一个变量,不一定是局部变量,还可能是成员变量。引用保存了内存地址,指向了堆内存当中的对象。
- 所有访问实例相关的数据,都需要通过“引用.”的方式访问,因为只有通过引用才能找到对象。
- 只有一个空的引用,访问对象的实例相关的数据会出现空指针异常。
参数传递
主要研究和学习的是方法在调用的时候,涉及到参数传递的问题,到底是怎样传递数据的呢?
- 值传递
Int i = 10;
Int j = i ; i 传递给 j,实际上只是将 i 变量中保存的 10 传递给了 j,j 实际上是一个全新的内存空间
User u = 0 x 1234;
User u 2 = u;
U 传递给 u 2,实际上是将 0 x 1234 这个值赋给 u 2 了,u 和 u 2 实际上是两个不同的局部变量,但是他们这两个变量指向堆内存中的同一个 java 对象。
Java 语言当中方法调用的时候涉及到的参数传递的问题
参数传递实际上传递的是变量中保存的具体值
例一:
public class Test01()
{
public static void main(String[] args){
//int i = 10;
//add(i)等同于:add(10)
int i = 10;
add(i);//add方法调用的时候,给add方法传递了一个变量i,实际上传递的是变量中保存的具体值
System.out.println("main-->"+ i );
}
public static void add(int i){
i++;
System.out.println("add-->"+ i);
}
}
编译结果:

例二:
public class Test02(){
public static void main(String[] args){
User u = new User(20);
//User u =0x1234;
//add(u)等同于:add(0x1234)
add(u);//传递u给add方法的时候,实际上传递的是U变量中保存的值,只不过这个值是一个java对象的内存地址
System.out.println("main-->"+ u.age);
}
public static void add(User u ){
u.age++;
System.out.println("add-->"+ u.age);
}
}
class User
{
int age;
public User(int i){
age = i;
}
}
编译结果:

最终结论:
方法调用的时候,涉及到参数问题,传递的时候,java只遵循一种语法机制,就是将变量中保存的“值”传递过去了,只不过有时候这个值是一个字面值10,有的时候是另一个java对象的内存地址0x1234。






