Java学习笔记(3)—— 面对对象(构造)

这篇博客深入探讨了Java的面向对象特性,包括类和对象的概念及其区别,详细阐述了属性和方法的定义、权限修饰符、构造器的作用,以及重载、递归等概念。还介绍了JavaBean标准和内部类的定义及分类,展示了静态和非静态代码块在初始化中的应用。此外,文章通过实例解析了对象创建和初始化的流程,以及类加载时静态和非静态代码块的执行顺序。
摘要由CSDN通过智能技术生成

Java学习笔记(3)—— 面对对象(构造)

1 面对对象的思想

1.1 面向对象与面向过程

  1. 面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做。
  2. 面向对象:强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。

1.2 面向对象中两个重要的概念:

  • 类:对一类事物的描述,是抽象的、概念上的定义
  • 对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)

    面向对象程序设计的重点是类的设计
    设计类,就是设计类的成员。

  • 二者的关系:对象,是由类new出来的,派生出来的。
package FaceObject;

/**
 * @author Chris
 * @create 2021-07-12-17:17
 */

public class Person {   // 构建对象
    //属性
    String name;
    int age = 1;

    // 构造器
    public Person(){

    }

    //方法
    public void eat(){
        System.out.println("人可以吃饭");
    }

    // 块
    {
        System.out.println("人可以睡觉");
    }

    // 内部类
    class Brain{

    }
}

class PersonText{
    public static void main(String[] args) {
        Person p =new Person();               // 构建对象
        p.name = "chris";                     // 通过对象.属性,对象.方法调用对象结构
        System.out.println(p.name);
        System.out.println(p.age);
        p.eat();
    }

}

2 类的构造之一属性(成员变量)

2.1 属性和局部变量

  • 变量的分类: 按照在类中声明的位置:

在这里插入图片描述

  • 变量的分类:按照数据类型
    在这里插入图片描述

2.1.1 相同点:

  1. 定义变量的格式:数据类型 变量名 = 变量值

  2. 先声明,后使用

  3. 变量都其对应的作用域

2.1.2 不同点:

  1. 在类中声明的位置的不同
  • 属性:直接定义在类的一对{}内
  • 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
  1. 关于权限修饰符的不同
  • 属性:可以在声明属性时,指明其权限,使用权限修饰符。常用的权限修饰符:private、public、缺省、protected —>封装性
  • 局部变量:不可以使用权限修饰符。
  1. 默认初始化值的情况:
  • 属性:类的属性,根据其类型,都默认初始化值。
    整型(byte、short、int、long:0)
    浮点型(float、double:0.0)
    字符型(char:0 (或’\u0000’))
    布尔型(boolean:false)
    引用数据类型(类、数组、接口:null)
  • 局部变量:没默认初始化值。意味着,我们在调用局部变量之前,一定要显式赋值。特别地:形参在调用时,我们赋值即可。
  1. 在内存中加载的位置:
  • 属性:加载到堆空间中 (非static)
  • 局部变量:加载到栈空间

2.2 属性赋值的顺序

  1. 默认初始化
  2. 显式初始化
  3. 在代码块中赋值
  4. 构造器中初始化
  5. 有了对象以后,可以通过"对象.属性"或"对象.方法"的方式,进行赋值

3 类的构造之二方法

在这里插入图片描述

  • 方法的声明:
权限修饰符  返回值类型  方法名(形参列表){
 				方法体
		  }
例如:
public void eat(){}
public void sleep(int hour){}
public String getName(){}
public String getNation(String nation){}

3.1 权限修饰符

  • 默认方法的权限修饰符先都使用public

  • Java规定的4种权限修饰符:private、public、缺省、protected

3.2 返回值类型: 返回值 vs 没返回值

  • 如果方法返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,需要使用 return关键字来返回指定类型的变量或常量:“return 数据”。
return关键字的使用:
1. 使用范围:使用在方法体中
2. 作用:1.结束方法;2. 针对于有返回值类型的方法,使用"return 数据"方法返回所要的数据。
3. 注意点:return关键字后面不可以声明执行语句。
  • 如果方法没返回值,则方法声明时,使用void来表示。通常,没返回值的方法中,就不需要使用return.但是,如果使用的话,只能“return;”表示结束此方法的意思。

3.3 方法名

属于标识符,遵循标识符的规则和规范(xxxYyyDddd),“见名知意”

3.4 形参列表

方法可以声明0个,1个,或多个形参。
格式: 数据类型1 形参1,数据类型2 形参2,…

3.4.1 可变个数形参的方法

1.jdk 5.0新增的内容
2. 具体使用:

  • 可变个数形参的格式:数据类型 … 变量名
  • 当调用可变个数形参的方法时,传入的参数个数可以是:0个,1个,2个,。。。
  • 可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载
public void show(String s){
	System.out.println("show(String)");
}

public void show(String ... strs){
	System.out.println("show(String ... strs)");
	
	for(int i = 0;i < strs.length;i++){
		System.out.println(strs[i]);
	}
}
  • 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载。换句话说,二者不能共存。
	public void show(String ... strs){
		System.out.println("show(String ... strs)");
		
		for(int i = 0;i < strs.length;i++){
			System.out.println(strs[i]);
		}
	}
	//不能与上一个方法同时存在
//	public void show(String[] strs){
//		
//	}
  • 可变个数形参在方法的形参中,必须声明在末尾
  • 可变个数形参在方法的形参中,最多只能声明一个可变形参。

3.4.2 java的值传递机制

3.4.2.1 方法内变量的赋值

规则:

  • 如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
  • 如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值
 class ValueTransferTest {

    public static void main(String[] args) {

        System.out.println("***********基本数据类型:****************");
        int m = 10;
        int n = m;

        System.out.println("m = " + m + ", n = " + n);

        n = 20;

        System.out.println("m = " + m + ", n = " + n);

        System.out.println("***********引用数据类型:****************");

        Order1 o1 = new Order1();
        o1.orderId = 1001;

        Order1 o2 = o1;//赋值以后,o1和o2的地址值相同,都指向了堆空间中同一个对象实体。

        System.out.println("o1.orderId = " + o1.orderId + ",o2.orderId = " +o2.orderId);

        o2.orderId = 1002;

        System.out.println("o1.orderId = " + o1.orderId + ",o2.orderId = " +o2.orderId);

    }

}

class Order1 {

    int orderId;

}

在这里插入图片描述

3.4.2.2

针对于方法的参数概念

  • 形参:方法定义时,声明的小括号内的参数
  • 实参:方法调用时,实际传递给形参的数据

java中参数传递机制:值传递

  • 如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
  • 如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。
class ValueTransferTest1 {
    public static void main(String[] args) {

        int m = 10;
        int n = 20;

        System.out.println("m = " + m + ", n = " + n);
        //交换两个变量的值的操作
//        int temp = m ;
//        m = n;
//        n = temp;

        ValueTransferTest1 test = new ValueTransferTest1();
        test.swap(m, n);

        System.out.println("m = " + m + ", n = " + n);


    }

    public void swap(int m,int n){
        int temp = m ;
        m = n;
        n = temp;
    }
}

/*运行结果
m = 10, n = 20
m = 10, n = 20
*/
class ValueTransferTest2 {

    public static void main(String[] args) {

        Data data = new Data();

        data.m = 10;
        data.n = 20;

        System.out.println("m = " + data.m + ", n = " + data.n);

        //交换m和n的值
//		int temp = data.m;
//		data.m = data.n;
//		data.n = temp;

        ValueTransferTest2 test = new ValueTransferTest2();
        test.swap(data);


        System.out.println("m = " + data.m + ", n = " + data.n);

    }

    public void swap(Data data){
        int temp = data.m;
        data.m = data.n;
        data.n = temp;
    }

}

class Data{

    int m;
    int n;

}

/*运行结果
m = 10, n = 20
m = 20, n = 10
*/

3.5 重载

定义: 在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。

总结 :“两同一不同”:同一个类、相同方法名 ;参数列表不同:参数个数不同,参数类型不同

判断是否是重载:跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系!

    //如下的4个方法构成了重载
    public void getSum(int i,int j){
        System.out.println("1");
    }

    public void getSum(double d1,double d2){
        System.out.println("2");
    }

    public void getSum(String s ,int i){
        System.out.println("3");
    }

    public void getSum(int i,String s){
        System.out.println("4");
    }

    //如下的3个方法不能与上述4个方法构成重载
//	public int getSum(int i,int j){
//		return 0;
//	}

//	public void getSum(int m,int n){
//
//	}

//	private void getSum(int i,int j){
//
//	}

在通过对象调用方法时,如何确定某一个指定的方法: 方法名 —> 参数列表

3.6 递归方法

  1. 递归方法:一个方法体内调用它自身。
  2. 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
class RecursionTest {

    public static void main(String[] args) {

        // 例1:计算1-100之间所有自然数的和
        // 方式一:
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            sum += i;
        }
        System.out.println(sum);
        // 方式二:
        RecursionTest test = new RecursionTest();
        int sum1 = test.getSum(100);
        System.out.println(sum1);

        System.out.println("*****************");
        int value = test.f(10);
        System.out.println(value);

    }

    // 例1:计算1-n之间所有自然数的和
    public int getSum(int n) {// 3

        if (n == 1) {
            return 1;
        } else {
            return n + getSum(n - 1);
        }

    }

    // 例2:计算1-n之间所有自然数的乘积:n!
    public int getSum1(int n) {

        if (n == 1) {
            return 1;
        } else {
            return n * getSum1(n - 1);
        }

    }

    //例3:已知有一个数列:f(0) = 1,f(1) = 4,f(n+2)=2*f(n+1) + f(n),
    //其中n是大于0的整数,求f(10)的值。
    public int f(int n){
        if(n == 0){
            return 1;
        }else if(n == 1){
            return 4;
        }else{
//			return f(n + 2) - 2 * f(n + 1);
            return 2*f(n - 1) + f(n - 2);
        }
    }

    //例4:斐波那契数列

    //例5:汉诺塔问题

    //例6:快排
}

4 类的构造之三构造器

4.1 作用

  • 创建对象
  • 初始化对象的信息

4.2 使用说明

  1. 如果没显式的定义类的构造器的话,则系统默认提供一个空参的构造器
  2. 定义构造器的格式:权限修饰符 类名(形参列表){}
  3. 一个类中定义的多个构造器,彼此构成重载
  4. 一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器
  5. 一个类中,至少会有一个构造器。
public class PersonTest {
	public static void main(String[] args) {
		//创建类的对象:new + 构造器
		Person p = new Person();
		
		p.eat();
		
		Person p1 = new Person("Tom");
		
		System.out.println(p1.name);
		
		
	}
}

class Person{
	//属性
	String name;
	int age;
	
	//构造器
	public Person(){
		System.out.println("Person().....");
	}
	
	public Person(String n){
		name = n;
		
	}
//	
	public Person(String n,int a){
		name = n;
		age = a;
	}

	
	//方法
	public void eat(){
		System.out.println("人吃饭");
	}
	
	public void study(){
		System.out.println("人可以学习");
	}
	
}

4.3 JavaBean

定义:

所谓JavaBean,是指符合如下标准的Java类:
	>类是公共的
	>有一个无参的公共的构造器
	>有属性,且有对应的get、set方法
class Customer1 {

    private int id;
    private String name;

    public Customer1(){

    }

    public void setId(int i){
        id = i;
    }
    public int getId(){
        return id;
    }
    public void setName(String n){
        name = n;
    }
    public String getName(){
        return name;
    }

}

5 类的构造之四块

5.1 作用

用来初始化类、对象

5.2 分类

静态代码块 vs 非静态代码块

  • 静态代码块:

内部可以输出语句
随着类的加载而执行,而且只执行一次
作用:初始化类的信息
如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
静态代码块的执行要优先于非静态代码块的执行
静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构

  • 非静态代码块:

内部可以输出语句
随着对象的创建而执行
每创建一个对象,就执行一次非静态代码块
作用:可以在创建对象时,对对象的属性等进行初始化
如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法

5.3 实例化子类对象

涉及到父类、子类中静态代码块、非静态代码块、构造器的加载顺序?
由父及子,静态先行

class Root{
    static{
        System.out.println("Root的静态初始化块");
    }
    {
        System.out.println("Root的普通初始化块");
    }
    public Root(){
        super();
        System.out.println("Root的无参数的构造器");
    }
}
class Mid extends Root{
    static{
        System.out.println("Mid的静态初始化块");
    }
    {
        System.out.println("Mid的普通初始化块");
    }
    public Mid(){
        super();
        System.out.println("Mid的无参数的构造器");
    }
    public Mid(String msg){
        //通过this调用同一类中重载的构造器
        this();
        System.out.println("Mid的带参数构造器,其参数值:"
                + msg);
    }
}
class Leaf extends Mid{
    static{
        System.out.println("Leaf的静态初始化块");
    }
    {
        System.out.println("Leaf的普通初始化块");
    }
    public Leaf(){
        //通过super调用父类中有一个字符串参数的构造器
        super("尚硅谷");
        System.out.println("Leaf的构造器");
    }
}
class LeafTest{
    public static void main(String[] args){
        new Leaf();
        System.out.println();
        new Leaf();
    }
}

/**运行结果
 * Root的静态初始化块
 * Mid的静态初始化块
 * Leaf的静态初始化块
 * Root的普通初始化块
 * Root的无参数的构造器
 * Mid的普通初始化块
 * Mid的无参数的构造器
 * Mid的带参数构造器,其参数值:尚硅谷
 * Leaf的普通初始化块
 * Leaf的构造器
 *
 * Root的普通初始化块
 * Root的无参数的构造器
 * Mid的普通初始化块
 * Mid的无参数的构造器
 * Mid的带参数构造器,其参数值:尚硅谷
 * Leaf的普通初始化块
 * Leaf的构造器
 */

6 类的构造之五内部类

6.1 定义:

Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类.

6.2 分类

成员内部类(静态、非静态 ) vs 局部内部类(方法内、代码块内、构造器内)

6.3 成员内部类

一方面,作为外部类的成员:

  • 调用外部类的结构
  • 可以被static修饰
  • 可以被4种不同的权限修饰

另一方面,作为一个类:

  • 类内可以定义属性、方法、构造器等
  • 可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承
  • 可以被abstract修饰

如何创建成员内部类的对象?(静态的,非静态的)

//创建静态的Dog内部类的实例(静态的成员内部类):
Person.Dog dog = new Person.Dog();

//创建非静态的Bird内部类的实例(非静态的成员内部类):
//Person.Bird bird = new Person.Bird();//错误的
Person p = new Person();
Person.Bird bird = p.new Bird();

如何在成员内部类中调用外部类的结构?

class Person{
	String name = "小明";
public void eat(){
}
//非静态成员内部类
	class Bird{
		String name = "杜鹃";
		public void display(String name){
			System.out.println(name);//方法的形参
			System.out.println(this.name);//内部类的属性
			System.out.println(Person.this.name);//外部类的属性
		//Person.this.eat();
		}
	}
}

备注:本文来自观看尚硅谷视频做的笔记。强烈推荐!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值