Java面向对象简介、构造方法、this及static关键字、两种数据类型的参数传递

  • 1. PO与OO
  • 1.1 什么是PO
  • 1.2 什么是OO
  • 1.3 PO与OO的联系
  • 1.4PO与OO的区别
  • 2. 面向对象软件开发的一般流程
  • 2.1 OOA
  • 2.2 OOD
  • 2.3 OOP
  • 3. 类
  • 3.1 类的创建
  • 3.2 类的组成
  • 4. 对象
  • 4.1 对象的实现
  • 5. 成员变量与局部变量的区别
  • 6. 构造方法
  • 6.1 构造方法的作用
  • 6.2 构造方法的实现
  • 6.3 构造方法的类型
  • 6.4 构造方法的调用
  • 6.4.1 自身调用自身构造方法
  • 6.4.2 创建对象调用构造方法
  • 6.4.3 子类调用父类构造方法
  • 7. 对象数组的实现及赋值操作
  • 8. this关键字
  • 8.1 this关键字的作用
  • 8.2 this关键字的使用
  • 9. static变量(静态变量)
  • 9.1 static变量作用
  • 9.2 static变量的实现
  • 9.2 与非静态成员变量的区别
  • 10. 两种数据类型参数的传递


1. PO与OO

1.1 什么是PO

PO是Procedure Oriented的简写,中文叫面向过程。

1.2 什么是OO

OO是Object Oriented的简写,中文叫面向对象。

1.3 PO与OO的联系

OO是在PO之后提倡出来的一种解决问题的思路,而且一般而言,OO是需要PO的分析的。

1.4PO与OO的区别

PO主要适用于解决微观的、线性的问题,而OO主要适用于解决宏观的、非线性的问题。

2. 面向对象软件开发的一般流程

2.1 OOA

OOA是Object Oriented Analysis的简写,中文叫面向对象分析。OOA最主要的目的是提取系统需求,即确定解决问题所需要的类、对象、属性、方法等。

2.2 OOD

OOD是Object Oriented Design的简写,中文叫面向对象设计。OOD最主要的目的是规范化系统需求,即以模块化、低耦合、高内聚、信息隐藏、重用性等为目标,用可实现的方式描述系统需求(类、对象、属性、方法等)。

2.3 OOP

OOP是Object Oriented Programming的简写,中文叫面向对象编程。OOP最主要的目的是实现系统需求,即用具体的编程语言实现类、对象、属性、方法等逻辑。

3. 类

3.1 类的创建

(public) class className{ }

注:一个源文件中有且仅有一个被public修饰的类

3.2 类的组成

类一般由成员变量、成员方法以及构造方法三部分组成。

还可以包括代码块及内部类

4. 对象

4.1 对象的实现

className objectName = new className(arguments);
或者
className objectName;//对象的声明
objectName = new className(arguments);//对象的实例化及初始化

new关键字是对对象的实例化操作,即创建一个对象,并为其在堆中开辟存储空间,而new后面的构造方法是对该对象进行初始化操作。

5. 成员变量与局部变量的区别

差异

成员变量

局部变量

定义位置

类中

方法中

内存位置

堆中

栈中

生命周期

同该类的生命周期

同该方法的生命周期

作用域

该类

该方法

默认值


无(所以必须初始化)

6. 构造方法

6.1 构造方法的作用

对类进行初始化

6.2 构造方法的实现

请看代码

/**
 * 功能:构造方法的实现
 */

public class Test {
	//成员变量
	private String name;
	
    //main方法
    public static void main(String[] args) {
    	Test t=new Test();//创建Test类的一个对象并初始化
    	System.out.println(t.name);//输出t对象的成员变量name,结果为初始值null
    }
}

通过上面的代码发现,并没有写Test类的构造方法,但也完成了对类的初始化,这是怎么回事?magic?
实际上,在程序员不提供显式构造方法时,Java默认提供一个隐式的无参构造器,如下

/**
 * 功能:构造方法的实现
 */

public class Test {
	//成员变量
	private String name;

	//默认的隐式无参构造方法
	//隐式就是可以写可以不写,虽然你看不见,但实际上它存在
	//下面创建t对象就是调用的这个构造方法完成的初始化
	public Test(){

	}
	
    //main方法
    public static void main(String[] args) {
    	Test t=new Test();//创建Test类的一个对象并初始化
    	System.out.println(t.name);//输出t对象的成员变量name,结果为初始值null
    }
}

那如果程序员提供显式构造器呢?结果会怎么样?

/**
 * 功能:构造方法的实现
 */

public class Test {
	//成员变量
	private String name;

	//提供显式有参构造方法
	public Test(String name){
		this.name=name;
	}
	
    //main方法
    public static void main(String[] args) {
    	Test t=new Test();//报错:Error:(23, 16) java: 无法将类 cn.khue.csdn.Test中的构造器 Test应用到给定类型;需要: java.lang.String找到: 没有参数原因: 实际参数列表和形式参数列表长度不同
    	System.out.println(t.name);
    }
}

发现结果在创建t对象时会报错,因为只要提供了显式构造方法,默认的哪个隐式构造方法便不再被提供了,所以建议在提供显式有参构造方法时也将默认的隐式构造方法显式化

/**
 * 功能:构造方法的实现
 */

public class Test {
	//成员变量
	private String name;

	//将默认的隐式构造方法显式化
	public Test(){

	}

	//提供显式有参构造方法
	public Test(String name){
		this.name=name;
	}
	
    //main方法
    public static void main(String[] args) {
    	Test t=new Test();//创建t对象并初始化
    	System.out.println(t.name);//输出t对象的name变量,值为初始化值null

		Test t2=new Test("Khue");//调用Test类的有参构造方法创建t2对象并赋值
		System.out.println(t2.name);//输出t2对象的name变量值为khue
    }
}

6.3 构造方法的类型

按有无参数来说,构造方法可以分为无参构造方法与有参构造方法

有参构造方法是对无参构造方法的重载(overload)

6.4 构造方法的调用

6.4.1 自身调用自身构造方法

通过this关键字调用即可

//默认的无参构造器
    public Test(){

    }

    //提供的有参构造方法
    public Test(String name){
        this();//调用无参构造器
        this.name=name;//操作成员变量
    }

6.4.2 创建对象调用构造方法

/**
 * 功能:构造方法的调用
 */

public class Test {
	//成员变量
	private String name;

	//默认的隐式无参构造方法
	public Test(){

	}
	
    //main方法
    public static void main(String[] args) {
    	Test t=new Test();//调用构造方法完成对t对象的初始化
    	System.out.println(t.name);//输出t对象的成员变量name,结果为初始值null
    }
}

6.4.3 子类调用父类构造方法

通过super关键字调用父类构造方法

//父类
class Father{
    //默认隐式无参构造方法
    public Father(){
        super();//默认隐式调用父类构造方法(无继承,其父类为顶级类Object类),即这里调用的是Object类的构造方法
    }
}

//子类
class Child{
    //默认隐式无参构造器
    public Child(){
        super();//默认隐式调用父类构造方法
    }
}

隐式可以不写,所以上面的代码等同于下面的代码

//父类
class Father{
 
}

//子类
class Child{
   
}

所以,构造方法的第一条语句默认是隐式的super();即默认调用父类构造方法,但在实际开发中,我们可以将其修改为显式的父类有参构造方法或这显式有参本类构造方法。所以,在用一个构造方法中不能同时使用super和this调用构造方法(但可以同时使用super和this调用变量和方法)

7. 对象数组的实现及赋值操作

objectName[] arrName = new objectName(arguments);//声明并实例化、初始化对象数组arrName
arrName[i] = new objectName(arguments);//对对象数组arrName的i元素进行赋值操作
//对象数组的遍历,可以通过成员方法调用
for(objectName arr : arrName){
	arr.traverse()
	Sytem.out.println(arr);//输出为arrName每个元素的地址
}
System.out.println(Arrays.toString(arrName));//输出为arrName每个元素的地址

8. this关键字

8.1 this关键字的作用

this是一个隐含的引用类型的成员变量,其值指向创建好的对象的地址值。

8.2 this关键字的使用

调用成员变量(当成员变量与局部变量名一致时,必须使用this关键字加以区分(不重名时可以省略))

调用成员方法(可以省略)

调用构造器(必须出现在第一条语句,且不能使用new关键字(使用了new关键字便实例化了一个新对象))

9. static变量(静态变量)

9.1 static变量作用

增强变量的独立性,使其在该类中被共享,而不依赖于任一该类的对象

9.2 static变量的实现

在需要实现的变量前加static关键字即可

public class test{
	int a;//成员变量(非静态成员变量)
	
	static int b;//静态变量(静态成员变量)

	public void method(){
		int c=0;//局部变量、
	}
}

9.2 与非静态成员变量的区别

差异

静态成员变量

非静态变量

内存位置

堆中

方法区中(1.8之后方法区改名为元空间)

调用方式

既可以通过类名调用,也可以通过对象名调用(避免歧义,推荐使用类名调用)

只能通过对象名调用

分配数量

一个类1个(该类共用)

一个对象1个

内存分配时间

第一次类加载时

创建对象时

10. 两种数据类型参数的传递

数据类型

基本数据类型(byte short int long float double char boolean)

引用数据类型(class类 interface接口 array数组 enumeration枚举 lable标注)

内存位置

栈中

堆中

局部变量被改变



e.g.

/**
 * 测试基本数据类型参数与引用数据类型参数的传递
 */
public class CSDN {
    public static void main(String[] args) {
        //定义两个需要被交换的整型变量
        int num1=10, num2=20;
        Swap num = new Swap(num1, num2);

        //输出交换前两个变量的值
        //System.out.println("交换前:num1="+num1+", num2="+num2);
        System.out.println("交换前:num1="+num.num1+", num2="+num.num2);

        //通过调用外部方法交换两个变量的值
        //swap1(num1,num2);无法交换,因为改变的swap方法中的局部变量而非main方法中的局部变量
        swap2(num);

        //输出交换后两个变量的值
        System.out.println("交换后:num1="+num.num1+", num2="+num.num2);
    }

    //基本数据类型作为参数传递
    public static void swap1(int num1, int num2){
        int temp;
        temp=num1;
        num1=num2;
        num1=temp;
    }
    public static void swap2(Swap num){
        int temp;
        temp=num.num1;
        num.num1=num.num2;
        num.num2=temp;
    }
}
class Swap{
    //引用数据类型作为参数传递
    int num1,num2;
    public Swap(){};
    //构造方法重载
    public Swap(int num1, int num2) {
        this.num1 = num1;
        this.num2 = num2;
    }
}