Java入门2.1---面向对象的主线1---类及类的构成成分:属性、方法、构造器、代码块、内部类

面向对象编程的三条主线:

  1. 类及类的构成成分:属性 方法 构造器 代码块 内部类
  2. 面向对象编程的特征:封装性 继承性 多态性(抽象性)
  3. 其他的关键字:this super package import static final abstract interface

一、类

基本元素:类和对象
成员:

  1. 属性:Field=属性=成员变量:
  2. 方法:Method=(成员)方法=函数

面向对象思想的落地法则:

  1. 设计类,并设计类的成员(成员变量&成员方法)
  2. 通过类,来创建类的对象(也称作类的实例化)
  3. 通过“对象.属性”或“对象.方法”来调用,完成相应的功能

对象之间独立:创建的多个对象,彼此各自拥有一套类的属性,当对其中一个对象的属性进行修改时,不会影响搭配其他对象的属性值。

二、类的构成成分

1.属性(成员变量)

1.1 属性的声明的格式

修饰符 数据类型 变量名 = 初始化值 // java是强数据类型的语言

1.2 成员变量 VS 局部变量

相同点:

  1. 遵循变量声明的格式:修饰符 数据类型 变量名 = 初始化值 // java是强数据类型的语言
  2. 都有作用域

不同点:

  成员变量 局部变量
声明的位置 在类体内里,方法体外声明的变量 方法体内部声明的变量
修饰符 public private protected 缺省 局部变量没有修饰符,与所在的方法修饰符相同
初始化值

如果在声明时候,不显示的赋值,那么不同数据类型会有不同的默认初始化值。

  1. byte short int long默认值为0;
  2. float double默认值为0.0;
  3. char默认值为空格;
  4. boolean默认值为false;
  5. 引用类型变量默认值为null
一定要显示的赋值(局部变量没有默认初始化值)
内存中的存放位置 堆空间

栈空间

例:局部变量n被设置为"付昊",结束调用之后n就会从栈中清除。

总结:关于变量的分类

1.3 内存划分的结构

  1. 栈(stack):局部变量、对象的引用名、数组的引用名
  2. 堆(heap):new出来的“东西”(如:对象的实体,数组的实体),含成员变量
  3. 方法区:含字符串常量(字符串常量池)、类名
  4. 静态域:存放类中静态的的变量

2.方法(提供某种功能的实现)

2.1 格式

权限修饰符 (其他的关键字:static/final/abstract) 返回值类型(void:无返回值/具体的返回值) 方法名(形参列表){}

举例:

public void eat(){}
public String getName(){}
public void setName(String n){}

2.2 关于返回值类型

  1. void:表明方法不需要返回值
  2. 有返回值的方法,在方法的最后一定有return+返回值类型对应的变量

记忆:void与return不可以同时出现在一个方法内,像一对“冤家”
方法内可以调用本类的其他方法或属性,但是不能在方法内再定义其他方法。

2.3 方法的重载

要求:

  1. 同一个类中;
  2. 方法名必须相同;
  3. 方法的参数列表不同(参数的个数不同/参数类型不同)

方法的重载与方法的返回值类型没有关系:

class OverLoad{
    //定义两个int型变量的和
    public int getSum(int i,int j){
        return i + j;
    }
    //定义三个int型变量的和
    public int getSum(int i,int j,int k){
        return i + j + k;
}

    //不能与其他几个方法构成重载
    //public void getSum(int i,int j,int k){
        // return i + j + k;
    //}

    //定义两个double型数据的和
    public double getSum(double d1,double d2){
        return d1 + d2;
    }
    //定义三个double型数组的和
    public double getSum(double d1,double d2,double d3){
        return d1 + d2 + d3;
    }
}
//参数类型相同,但顺序不同是允许的
public void method1(int i,String str){
}
public void method1(String str,int j){
}

//参数类型相同,但参数名字不同是不允许的
//public void method1(int i,String str){
//}
//public void method1(int j,String str){
//}
//判断与void show(int a,char b,double c){}构成重载的有:
void show(int x,char y,double z){}//no
int show(int a,double c,char b){}//yes
void show(int a,double c,char b){}//yes
boolean show(int c,char b){}//yes
void show(double c){}//yes
double show(int x,char y,double z){}//no
void shows(){double c;}//no

2.4 匿名类对象

创建的类的对象是匿名的。

  • 当我们只需要一次调用类的对象时,我们就可以考虑使用匿名的方式创建类的对象。(栈中没有名字,堆中有类的对象)
  • 特点:创建的匿名类的对象只能够调用一次。

2.5 可变个数的形参的方法

  1. 格式:对于方法的形参:数据类型 ... 形参名
  2. 可变个数的形参的方法与同名的方法之间形成重载
  3. 可变个数的形参在调用时,个数从0开始,到无穷多个
  4. 使用可变多个形参的方法与方法的形参使用数组是一致的
  5. 若方法中存在可变个数的形参,那么一定要**声明在方法形参的最后**
  6. 在一个方法中,**最多**声明一个可变个数的形参
public void sayHello(){
    System.out.println("hello world");
}
public void sayHello(String str1){
    System.out.println("hello " + str1);
} 
//可变个数的形参的方法,包含前两个方法,实际写的时候,可以省略前两个方法
public void sayHello(String ... args){
    for(int i=0;i<args.length;i++){
        System.out.println(args[i]);
    }
}

public void sayHello1(String[] args){
    for (int i=0;i<args.length;i++){
    System.out.println(args[i]);
    }
}

/*
public int getSum(int i,int j){
    return i + j;
}
public int getSum(int i,int j,int k){
    return i + j + k;
}
*/
public int getSum(int ... args){
    int sum = 0;
    for(int i = 0;i < args.length;i++){
        sum += args[i];
}
return sum;

2.6 方法的参数(值)传递(重点、难点)

2.6.1 形参 VS 实参

  1. 形参:方法声明时,方法小括号内的参数
  2. 实参:调用方法时,实际传入的参数的值

2.6.2 参数传递机制规则

java中的参数传递机制,值传递机制

(1)形参是基本数据类型

将实参的传递给形参的基本数据类型的变量

/*
public class TestArgsTransfer{
    public static void main(String[] args){
        TestArgsTransfer tt = new TestArgsTransfer();
        DataSwap ds = new DataSwap();

        System.out.println("ds.i "+ds.i+" ds.j "+ds.j);

        tt.swap(ds);
        System.out.println("ds.i "+ds.i+" ds.j "+ds.j);
    }

    public void swap(DataSwap d){
        int tmp = d.i;
        d.i = d.j;
        d.j = tmp;
    }
}

class DataSwap{
    int i = 10;
    int j = 5;
}*/

public class TestArgsTransfer{
    public static void main(String[] args){
        int i = 3;
        int j = 6;
        TestArgsTransfer tt = new TestArgsTransfer();
            System.out.println("i "+i+" j "+j);

        tt.swap(i,j);
        System.out.println("i "+i+" j "+j);//没有交换
    }

    public void swap(int i,int j){
        int tmp = i;
        i = j;
        j = tmp;
    }
}    

(2)形参是引用数据类型的

将实参的引用类型变量的值(对应的堆空间的对象实体的首地址)传递给形参的引用类型变量

public class TestArgsTransfer{
    public static void main(String[] args){
        TestArgsTransfer tt = new TestArgsTransfer();
        DataSwap ds = new DataSwap();

        System.out.println("ds.i "+ds.i+" ds.j "+ds.j);

        tt.swap(ds);
        System.out.println("ds.i "+ds.i+" ds.j "+ds.j);
    }

    public void swap(DataSwap d){
        int tmp = d.i;
        d.i = d.j;
        d.j = tmp;
    }
}

class DataSwap{
    int i = 10;
    int j = 5;
}


举例:
class Value{
    int i = 15;
}
class Test{
    public static void main(String argv[]){
        Test t = new Test();
        t.first();
}

public void first(){
    int i = 5;
    Value v = new Value();
    v.i = 25;
    second(v,i);
    System.out.println(v.i);
}

public void second(Value v,int i){
    i = 0;
    v.i = 20;
    Value val = new Value();
    v = val;
    System.out.println(v.i + " " + i);
    }
}

最终结果为: 
15 0
20

3.构造器(构造方法)

类的第三个成员:构造器(constructor 构造方法)

3.1 构造器的作用

  1. 创建对象;
  2. 给创建的对象的属性赋值

注意:

  1. 设计类时,若不显示声明类的构造器的话,程序会默认提供一个空参的构造器
  2. 一旦显示的定义类的构造器,那么默认的构造器就不再提供
  3. 如何声明类的构造器,格式:权限修饰符 类名(形参){}
  4. 类的多个构造器之间构成重载
public class TestPerson{
    public static void main(String[] args) {
        Person p1 = new Person();
        String str = new String("bunny");
        Person p2 = new Person("aa");
    }
}

class Person{
    //属性
    private String name;
    private int age;

    //构造器
    public Person(String n){
    name = n;
    }

    public Person(){

    }

    public Person(int a){
    age = a;
    }

    public Person(String n,int a){
        name = n;
        age = a;
    }
}    

3.2 类对象的属性赋值的先后顺序

  1. 属性的默认初始化(new数据类型的默认值);
  2. 属性的显示初始化(定义数据类型时候的赋值);
  3. 初始化块
  4. 通过构造器给属性初始化;(对象.setName());
  5. 通过”对象.方法“的方式给属性赋值

4. 初始化块(代码块)

4.1 主要作用

用来初始化类的成员变量

代码块如果有修饰的话,只能使用static;

4.2 属性赋值执行顺序

  1. 默认的初始化;
  2. 显示的初始化或代码块初始化(此处两个结构按照顺序执行);
  3. 构造器中;
  4. 通过方法对对象的相应属性进行修改。

4.3 分类:非静态代码块 VS 静态代码块

非静态代码块:没有static修饰的代码块 静态代码块:用static修饰的代码块
  1. 可以对类的属性(静态的、非静态的)进行初始化操作,同时也可以调用本类声明的方法(静态的、非静态的)
  2. 里面可以有输出语句
  3. 一个类中可以有多个非静态的代码块,多个代码块之间安装顺序结构执行
  4. 每创建一个类的对象, 非静态代码块就加载一次
  5. 非静态代码块的执行要早于构造器
  1. 里面可以有输出语句
  2. 随着类的加载而加载,而且只能被加载一次
  3. 多个静态代码块之间按照顺序结构执行
  4. 静态代码块执行要早于非静态代码块执行
  5. 静态代码块中执行执行静态的结构(类属性、类方法)
  6. 不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法
   

5.内部类

5.1 定义

在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类

  1. Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。
  2. Inner class的名字不能与包含它的类名相同;
  3. Inner class可以使用外部类的私有数据,因为它是外部类的成员,同一个类的成员之间可相互访问。而外部类要访问内部类中的成员需要:内部类.成员或者内部类对象.成员。

5.2 内部类的分类

5.2.1 成员内部类

  1. 声明在类内部且方法外,是外部类的一个成员
  2. 可以有修饰符(4个)
  3. 可以用static/final修饰(static成员内部类和非static成员内部类)
  4. 可以调用外部类的属性、方法

5.2.2 局部内部类

  1. 声明在类的方法里、匿名内部类
  2. 可以用abstract修饰
  3. 还可以在其内部定义属性、方法、构造器

5.2.3 重点掌握

(1)如何创建成员内部类的对象(如:创建Bird类和Dog类的对象)

  1. 创建静态内部类的对象,可以直接通过外部类调用静态内部类的构造器;
  2. 创建非静态的内部类的对象,必须先创建外部类的对象,通过外部类的对象调用内部类的构造器。

(2)如何区分调用外部类、内部类的变量(尤其是变量重名时)

(3)局部内部类的使用

常常使用一个方法,使其返回值为某个类或接口的对象。而这个类或接口在方法内部创建。

6.类初始化顺序

普通类:

  • 静态变量
  • 静态代码块
  • 普通变量
  • 普通代码块
  • 构造函数

继承的子类:

  • 父类静态变量
  • 父类静态代码块
  • 子类静态变量
  • 子类静态代码块
  • 父类普通变量
  • 父类普通代码块
  • 父类构造函数
  • 子类普通变量
  • 子类普通代码块
  • 子类构造函数

抽象的实现子类: 接口 - 抽线类 - 实现类

  • 接口静态变量
  • 抽象类静态变量
  • 抽象类静态代码块
  • 实现类静态变量
  • 实习类静态代码块
  • 抽象类普通变量
  • 抽象类普通代码块
  • 抽象类构造函数
  • 实现类普通变量
  • 实现类普通代码块
  • 实现类构造函数

接口注意:

  • 声明的变量都是静态变量并且是final的,所以子类无法修改,并且是固定值不会因为实例而变化
  • 接口中能有静态方法,不能有普通方法,普通方法需要用defalut添加默认实现
  • 接口中的变量必须实例化
  • 接口中没有静态代码块、普通变量、普通代码块、构造函数

 

 

 

 

 

参考链接:

【1】【知识总结】Java类初始化顺序说明 - 努力编程的小猪 - 博客园

posted @ 2020-05-09 15:43  nxf_rabbit75  阅读(351)  评论(0编辑  收藏  举报