美文网首页
第3章:面向对象编程

第3章:面向对象编程

作者: 秋的懵懂 | 来源:发表于2018-07-20 09:36 被阅读0次

时间:2018-07-19 作者:魏文应


一、成员变量和局部变量

成员变量,也叫做 类的属性。下面代码中, agename 是声明在 类里,但在方法外 的变量,那它就叫做 类的成员变量。相对的,变量 ijn 依次是声明在 方法内、方法的形参、代码块内 的三个变量,这三种情况的变量,叫做 局部变量

class Animal{
    // 这就是属性(成员变量)
    int age;
    String name;
    
    public void setAge(int n){
        // 这就是局部变量
        int i = 0;
        
        for(int j = 0; j < 10; j++)
            i++;
        age = n;
        age += i;
    }
}

成员变量 存储在堆 中,局部变量 存储在栈 中。比如,下面代码中,Animal 对象 test 的成员变量,有age和name,分别存储在堆中,test 存储了一个地址引用,指向堆中Anima类的实体。而 i、n、j 存储在堆中:

public class TestAnimal{
    public static void main(String[] args){
        
        Animal test = new Animal();
        test.setAge(1);
    }
}
  • 成员变量和局部变量存储

局部变量 必须显式初始化,成员变量可以 不显式初始化,编译器可以给 成员变量 一下默认赋值:

数据类型 默认赋值
byte、short、int、long 0
float、double 0.0
char 空格
引用类型变量(比如String) null

成员变量可以使用 public、private、protected、缺省 修饰变量,比如:

public int age;

局部变量却不可以使用这些关键字来修饰(修饰了没有意义)。

二、类的方法

方法格式:权限修饰符 返回值类型 方法名 参数

class Animal{
    public void testPrintln(){
        System.out.println("Hello World!");
    }
}

可以在方法内 调用其它方法,但不能在方法内 定义其它方法

三、方法的重载

构成方法的重载,需要下面的条件:

  • 在同一个类中。
  • 方法名必须相同。
  • 方法的参数列表不同。
class OverLoad{
    public int getSum(int i, int j){
        return i + j;
    }
    
    public int getSum(int i, int j, int k){
        return i + j + k;
    }
    
    public double getSum(double d1, double d2){
        return d1 + d2;
    }
    
    public void getSum(double d1, double d2, double d3){
        System.out.println(d1 + d2 + d3);
    }
}

从上面可以看出,方法重载 和返回值没有关系。比如下面会 报错

class OverLoad{
    public int getSum(int i, int j){
        return i + j;
    }
    public void getSum(int i, int j){
        return i + j;
    }
}

四、匿名类对象

匿名,就是没有名字。下面代码中,TestNoName c = new TestNoName();,这个是 有名称 的类对象,名称为 cnew TestNoName().show(); 这个是 没有名称 的类对象,这就是匿名类对象。

public class PassObject {
    public static void main(String[] args) {
        TestNoName c = new TestNoName();
        new TestNoName().show();
    }
}

class TestNoName {
    public void show(){
        System.out.println("Test No Name Class");
    }
}

当我们只需 调用类对象一次,那我们就可以考虑使用匿名类对象。

五、可变形式形参的方法

方法的参数个数是可变的,可以是任意多个:0个到无穷多个。格式如下:

修饰  返回值  函数名  (参数类型 ... 参数名)

或者 使用下面格式

修饰  返回值  函数名  (参数类型[] 参数名)

比如,下面两种格式是一样的,表示一模一样的一个方法:

public void sayHello(String ... args)
public void sayHello(String[] args)

下面是一个应用示例(其实常见的 main(String[] args) 就是可变参数):

public class TestArgs {
    public static void main(String[] args) {
        new TestHello().sayHello("Hello", "World", "!");
    }
}

class TestHello{
    public void sayHello(String ... strings ){
        for(int i = 0; i < strings.length; i++){
            System.out.println(strings[i]);
        }   
    }
}

当我们有一个固定参数的时候,我们需要先把固定参数写前面,可变参数写后面。比如下面的代码,参数 i 写前面,可变参数写后面:

public void sayHello(int i, String ... strings)

六、函数参数值传递

方法参数传递中,我们可以看下面代码:

public class TestSwap {
    public static void main(String[] args) {    
        int i = 1, j = 2;
        
        TestSwap tmp = new TestSwap();
        tmp.swap(i, j);
        System.out.println("i = " + i + "; " + "j = " + j + ";");
    }
    
    public void swap(int m, int n){
        m = m ^ n;
        n = m ^ n;
        m = m ^ n;
        
        System.out.println("m = " + m + "; " + "n = " + n + ";");
    }
}

运行打印的结果显示,m 和 n 的值发生了互换,但 i 和 j 的值没有发生互换。原因是,当我们传参时 swap(i, j),栈中就会开辟新的两个内存空间,并赋值 m = i; n = j; 。从图中可以看出,i 和 j 的值 从始至终没有改变过,变化的只是 m 和 n。

  • 类方法参数传递情况

如果想要上面的 i 和 j 的值发生交换,类方法的参数应该使用 引用数据类型

public class TestArgsSwap {

    public static void main(String[] args) {
        
        DataSwap tmp = new DataSwap();
        tmp.i = 1;
        tmp.j = 2;
        
        TestArgsSwap tmp2 = new TestArgsSwap();
        
        tmp2.swap(tmp);
        System.out.println("tmp.i = " + tmp.i + "; " + "tmp.j = " + tmp.j + ";");
    }
    
    public void swap(DataSwap ds){
        ds.i = ds.i ^ ds.j;
        ds.j = ds.i ^ ds.j;
        ds.i = ds.i ^ ds.j;
        
        System.out.println("ds.i = " + ds.i + "; " + "ds.j = " + ds.j + ";");
    }
}

class DataSwap{
    int i;
    int j;
}

由于类方法参数 ds ,同样指向 tmp 类的堆内存地址,两个 引用变量指向的内存相同,所以导致最终 tmp.i 和 tmp.j 的值被修改了。

  • 使用引用数据类型的情况

七、面向对象的封装性

我们是可以 直接给成员变量赋值 的,比如,下面的代码,给类成员变量 legs 赋值:

public class TestAnimal {

    public static void main(String[] args) {
        Animal tmp = new Animal();
        
        tmp.legs = 4;
    }

}

class Animal{   
    String name;
    int legs;
}

但是,我们希望对legs的值的范围做一定的限制,那么使用类方法可以对属性进行操作:

public class TestAnimal {

    public static void main(String[] args) {
        Animal tmp = new Animal();
        
        tmp.legs = 4;
        tmp.setLegs(3);
    }

}

class Animal{   
    String name;
    int legs;
    
    public void setLegs(int n){
        if(n > 0 && n % 2 == 0){
            legs = n;
        }else{
            System.out.println("你输入的数据有误");
        }
    }
}

这时我们还是可以 在外面对 legs 成员变量 进行赋值操作,如果我们 不希望外面能够直接 对legs进行赋值操作,那么,可以在成员变量前,加上 private 私有化修饰:

public class TestAnimal {

    public static void main(String[] args) {
        Animal tmp = new Animal();
        
        // tmp.legs = 4; // 这就不可以用了。否则报错
        tmp.setLegs(3);
    }

}

class Animal{   
    String name;
    private int legs;
    
    public void setLegs(int n){
        if(n > 0 && n % 2 == 0){
            legs = n;
        }else{
            System.out.println("你输入的数据有误");
        }
    }
}

八、权限修饰符

Java权限修饰符 public、protected、private、缺省,置于类的成员定义前,用来 限定 对象对该类成员的 访问权限 。权限范围如下(yes表示可以访问):

修饰符 类内部 同一个包 子类 任何地方
private yes
(缺省) yes yes
protected yes yes yes
public yes yes yes yes

上面的四个中修饰符情况,可以修饰 类的方法类的成员。对于 class的权限修饰 只可以用 public(缺省)

  • public类可以在任意地方被访问。
  • default类只可以被同一个包内部的类访问。

九、类的成员之三:构造器

类除了属性、方法,还有 构造器(constructor 构造方法) 。它的形式如下:

class Person{
    public Person(){    
    }
}

也就是,它和 它所在的类重名 。如果没有没有在类中 显示地定义构造器,编译器会默认给一构造器。默认的构造器也就是上面 空参形式的构造器 。我们可以 自定义构造器,构造器也可以 重载

class Person{
    private String name;
    
    public Person(){
        
    }
    
    public Person(String n){
        name = n;
    }
}

十、this 关键字

this 关键字,表示 当前类。比如下面的示例,方法中的 参数变量名为name,而当前 类成员变量 也有一个变量名为name 。这个时候,同时名为name的这两个变量,就 不能区分哪个是哪个。所以就加上this修饰,用 this.name 表示成员变量 private String name 的name。

class Person{
    
    private String name;
    
    public void setName(String name){
        this.name = name;
    }
}

this 可以像上面一样修饰 成员变量,同样也可以修饰 类方法、构造器。

相关文章

  • “老奶奶”的python学习笔记(12)

    知识体系 第12关:面向对象编程 知识点 面向对象编程(Object Oriented Programming) ...

  • JS设计模式 -- 面向对象 -- 1 封装

    以下内容来自张荣铭《JavaScript设计模式》第2章。 两种编程风格 -- 面向过程与面向对象。 面向对象编程...

  • 面向对象_初识

    目录 面向对象编程介绍 类与对象介绍 私有属性与私有方法 面向对象编程 1. 面向对象编程介绍 面向对象编程:Ob...

  • 谈谈面向对象编程

    何为面向对象编程 面向对象编程简介 面向对象编程(Object-oriented Programming,缩写:O...

  • 面向对象基础

    面向对象编程包括: 面向对象的分析(OOA) 面向对象的设计(OOD) 面向对象的编程实现(OOP) 面向对象思想...

  • python-day14

    一、面向对象编程 编程思想:1.面向对象编程 --> 算法,逻辑2.函数式编程 --> 函数3.面向对象编程 ...

  • PHP全栈学习笔记8

    面向对象的基本概念,面向对象编程,oop,面向对象,面向对象的分析,面向对象的设计,面向对象的编程,什么是类。 类...

  • PHP全栈学习笔记8

    面向对象的基本概念,面向对象编程,oop,面向对象,面向对象的分析,面向对象的设计,面向对象的编程,什么是类。 类...

  • JavaScript继承和封装

    Javascript继承 第2章 写的都是看到的---面向对象编程 2.1 两种编程风格 ----面向过程与面向...

  • 面向对象浅析

    ### 面向对象编程和面向对象编程语言 面向对象编程的英文缩写是 OOP,全称是 Object Oriented ...

网友评论

      本文标题:第3章:面向对象编程

      本文链接:https://www.haomeiwen.com/subject/bwbzpftx.html