面向对象基础

一.面向对象的介绍

1.1简介

面向对象(Object Oriented)是一种更加优秀的程序设计方法。它由面向对象分析(OOA),面向对象设计(OOD),面向对象编程(OOP)三部分组成。

它的基本思想是使用类,对象,继承,封装,多态等进行程序设计。它从现实世界中客观存在的事物出发来构造软件系统,在系统构造中尽可能的运用人类的自然思维方式,强调直接以现实世界中的事物为中心来思考问题,认识问题。并根据这些事物的本质特点,把他们抽象地表示为系统中的类,作为系统的基本构成单元,使得软件系统的组件可以直接映射现实世界,并保持客观世界事务及其相互关系的本来面貌。

我们主要学习的就是面向对象的编程,简称OOP

1.2面向对象的类

在面向对象编程中,最小的程序单元是类,类可以生成系统中的多个对象,这些对象能够映射出现实生活中的各个实例;

在类中我们可以定义很多成员变量(属性),比如设置一个person类,成员变量就会有身高,体重,姓名,性别,等等,我们只需要记录有关于业务的成员变量就可以了;

为了操作这些成员变量,我们使用方法来将成员变量实现:

类的定义 = 成员变量 + 方法

面向对象比面向过程的粒度要大;面向对象的单位是类,而面向过程的单位是函数,因此面向对象要比面向过程简单易用,举一个例子: 在组装电脑时,用主板,CPU,内存条硬盘这样的大件组装和使用一堆三极管,二极管,集成电路等组装,哪个更简单显而易见

1.3案例比较

①把大象放进冰箱

面向过程:

第一步:打开冰箱门

第二步:把大象放进去

第三步:关上冰箱门

这些都是人的行为,需要设计不同的函数来实现这些问题

面向对象:

第一步:冰箱开门           冰箱的行为

第二步:大象进入冰箱   大象的行为

第三步:冰箱关门          冰箱的行为

②猪八戒吃西瓜

面向过程:以函数为中心,所以需要表示为:吃这个函数,变量是猪八戒和西瓜

吃(猪八戒,西瓜)

面向过程,以对象为中心,所以可以表示为:猪八戒这个类调用吃这个方法

猪八戒.吃(西瓜)

说的大白话一点,开发者想直接模拟客观世界。定义一个类,对应客观世界的一种事物;业务需要关心这个事物的哪些状态数据,就定义为成员变量;业务需要关心这个事物的哪些行为,程序就可以定义为方法

面向对象是不脱离面向过程的思想,面向对象中的方法(Method)逻辑依然是面向过程的逻辑可以说面向过程是面向对象的基础思想;

面向对象和面向过程最终的目的都是解决问题,面向过程要求的是整个解决问题的步骤,而面向对象只需要关系问题中涉及到的类和方法就可以了。方法的内部还是会有面向过程的思想,只是思维方式不一样而已。

总结:

面向对象秉承着一切都是对象的思想,关心的是这个对象的行为,对象的成员变量(属性),

面向过程关心的是每一个步骤,需要有前因,有后果

二.类与对象

2.1类的设计

[访问权限修饰符]   class   类名{

成员变量

方法

}

在一个.java文件中,定义一个普通类,访问权限修饰词只能是public或者默认的

类名需要使用大驼峰命名法

成员变量需要声明

方法用来描述对象的共同行为,或者用来操作成员变量

public class Computer {
  public String model;
   public String color;
  public String brand;
   public String size;

我们定义了一个Computer类,属性有model,color,brand,size。

2.2 对象

类是对象的模板,对象是类的具体

我们可以使用new关键字来实例化对象;

使用     类名   对象名  =  new     类名 ();的格式就可以创建对象了;

Computer c1 = new Computer();

我们通过上述的方法就创建出了一个Computer类型的对象c1, 引用类型声明的变量,称之为引用变量,简称引用。 因为里面存储的不是对象,而是对象的内存地址 ;引用变量,说的其实就是可以通过自己存储的地址找到哪个对象。替代了c语言里的指针。

我们如果此时使用打印语句,并不能打印出对象的属性,只能打出对象的内存地址

会得到类全名+@+16进制储存地址

  2.3成员访问

①基本成员的访问

成员访问,指的就是如何使用类里的属性和方法;

通常使用点语法,对象名.成员变量 =    ;

访问方法 对象名.方法名( )

public class Person {
    //成员变量: 这类事物的共同特征,即状态数据,一堆不同类型的变量,也可以叫属性,全局变量
    String name;
    int age;
    char gender;

    //成员方法:    这类事物的共同行为,在这里可以直接操作成员变量
    public void eat(String food){
        System.out.println(name+"吃的食物是"+food);
    }
    public void play(String game){
        System.out.println(name+"喜欢玩"+game);
    }
    public void work(){
        System.out.println(name+"喜欢工作");
    }

在上述代码中,我们创建了一个Person的类,属性有name,age,gender

成员方法有eat,play,work,在方法中,设置了形参

public class PersonTest1 {
    public static void main(String[] args) {
        //创建Person类型的一个对象(引用变量)
        Person p1 = new Person();
        //注意:成员变量都是有默认值的,在没赋值之前。
        System.out.println(p1.name);  // 引用类型的默认值null
        System.out.println(p1.age);   // byte,short,int,long的默认值是0
        System.out.println(p1.gender); // char的默认值 \u0000

//        // 给对象的属性赋值。
        p1.name = "michael";
        p1.age = 18;
        p1.gender = '男';

在上述代码中,我们设置了一个测试类,提供了main方法,创建了Person类型的一个变量p1,p1内部有成员变量,初始值都是默认值,引用类型的默认值都是null,基本数据类型的默认值是0或0.0,false,\u0000

在执行打印语句打印其各个成员变量时,返回的就都是默认值;

但是我们可以利用对象名.成员变量的方式给各个成员变量赋值;

此时再打印p1的各个属性就有值了;

我们在访问成员方法时也可以使用对象名.成员方法的方式

p1.eat("蛋糕");
p1.play("王者荣耀");
p1.work();

//int...a  属于可变长参数,    变量类型...变量名  注意:该变量是数组  可变长参数只能放到最后面
    public long calculate(long b,int...a){
        int sum = 0;
        for (int i = 0; i < a.length; i++) {
            sum += a[i];
        }
        return sum;

    }

这是在Person类中设置的另一种方法,返回值类型是long,参数列表中由两部分组成,一部分是long类型的参数b,另一部分是可变长参数,需要放在最后面;初始化sum是0,然后把可变长参数中数组的每一项都相加;返回sum;在调用时,需要long类型的接受变量,还需要输入两部分参数,一部分时long类型的参数,另一部分是可变长参数

 long sum = p1.calculate(3,1,2,3,4,5);
 System.out.println(sum);

最后sum的结果就是可变长参数相加之和

2.4  this关键字

this.是隐藏在成员方法中成员变量前面的关键字

哪个对象调用这个方法,this就是谁;

public class Cat {
    String name;
    String brand;
    String color;

    public void setInfo(String a ,String b ,String c){
        //成员变量前隐藏了this.  可以写出来,也可以称略不写
        this.name = a;
        this.brand = b;
        this.color = c;
    }

根据上述代码,我们建立了一个Cat类,设置了三个属性分别是name,brand,color,并在下面定义了一个成员方法,setInfo,形参列表中分别是三个字符串类型的参数a,b,c.

this.name的作用就是确定把形参赋值给成员变量name,因为形参列表中的参数名和成员变量的名字不同,所以可以不加this.关键字,但是如果形参列表中的名字与成员变量相同,就需要添加this.关键字了

 public void setInformation(String name ,String brand,String color){
        //当形式参数的变量与成员变量的名字相同时,如果想要在这个作用于内
        //表示成员变量,那么this.不能省略
        this.name = name;
        this.brand = brand;
        this.color = color;
    }

此时this.关键字不能省略;

 public void showInfo(){
    System.out.println("name:"+name+"brand:"+brand+"color:"+color);
    }

再定义一个打印方法,来把对象中的成员变量能打印出来;

 public static void main(String[] args) {
        //创建cat类的对象c1;
        Cat c1 = new Cat();
        //调用setInfo给对象c1的各个属性赋值
        c1.setInfo("小白","中国田园","白色");
        //调用showInfo方法
        c1.showInfo();

使用main方法,创建一个Cat类型的对象c1,并使用setInfo方法给c1的属性赋值;分别是小白,中华田园,白色,然后调用showInfo方法打印出运行结果

 //调用setInformation修改属性信息
        c1.setInformation("小黑","吉林品牌","黑色");
        c1.showInfo();

我们还可以调用setInformation方法来修改c1对象的属性;然后打印出来

三.构造方法

3.1介绍

构造方法也是一种方法,只是和普通的方法有区别:

语法不同,构造方法没有返回值,这里说的没有返回值不是指返回值类型是void,而是返回值类型这个位置不存在;构造方法的名字,必须与类名保持一致;构造方法不能使用static修饰

执行时机不同,普通的方法,可以随时调用,但是构造方法是在实例化对象时才会调用,需要使用new 关键字来调用;

构造方法可以重载  参数列表不同即可, 如果程序员在定义某个类时,没有提供任何的构造器,系统会默认提供一个无参构造器,一旦程序员提供了某个构造器,无参构造器就不存在了,如果想使用无参构造器,需要程序员自己提供一个;

public class Person2 {
  String name;
  int age;
  char gender;
  //无参构造器
  public Person2(){
    System.out.println("---无参构造器---");
  }

  //全参构造器
    public Person2(String name, int age, char gender) {
      this.name = name;
      this.age = age;
      this.gender = gender;
      System.out.println("---全参构造器---");
    }

    public Person2(String name, char gender){
      this.name = name;
      this.gender = gender;
      this.age = 18;
      System.out.println("---两个参数构造器---");
    }

  public void showInfo(){
      System.out.println("Name: " + name);
      System.out.println("Age: " + age);
      System.out.println("Gender: " + gender);
  }
}

根据上述代码,我们先提供了一个无参构造器,然后提供了一个全参构造器,因形参列表中的形参名与成员变量一致,所以需要使用this.关键字,之后又提供了一个showInfo方法,来打印对象的三个属性,之后我们新建一个测试类,实例化一个对象;

public class Person2Test {
    public static void main(String[] args) {
        //调用Person2的无参构造器初始化和实例化一个对象
        Person2 p1 = new Person2();
        p1.showInfo(); //因为无参构造器中没有初始化操作,因此都是默认值

        //调用全参构造器实例化和初始化一个对象  ctrl+p用于查看重载的方法参数
        Person2 p2 = new Person2("小明",20,'男');
        p2.showInfo();

        //调用两个参数的构造器,实例化和初始化一个对象
        Person2 p3 = new Person2("小红",'女');
        p3.showInfo();
    }
}

可以看出,我们先使用无参构造器实例化了一个对象p1,他的成员变量值都是默认值

之后调用了全参构造器,需要输入三个实参,然后调用showInfo方法打印出来;

然后调用两个参数的构造器,成员变量age是设置好的18;

在调用构造器时,需要使用  类名  对象名 =  new 类名( )的方式调用。

3.2构造器的调用(续)

 

在我们使用构造器时可以使用this(有参传参)的方式调用本类中的其他构造器

需要注意的是,this(有参传参)必须写在构造器的首行首句;

public class Person3 {
    String name;
    int age;
    char gender;
    //无参
    public Person3() {
        this.name = "";
        this.age = -1;
        this.gender = 'f';
    }
    //单参
    public Person3(String name) {
        this.name = name;
    }

    public Person3(String name,int age ) {
       //调用本类中的一个参数构造器
        this(name);
        this.age = age;
    }

    public Person3(String name,int age, char gender) {
        //调用本类中的两个参数构造器
        this(name,age);
        this.gender = gender;
    }


     public void showInfo(){
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
        System.out.println("Gender: " + gender);
     }

首先我们定义了一个Person3的类,然后设置了其属性分别是name,age,gender

先定义一个无参构造器,初始化每个属性的值为空,-1,f  ;

然后定义了一个单参构造器,形参列表时name

定义双参构造器时,可以调用单参构造器,在构造器内部的首行首句写this(name);

定义全参构造器时可以调用双参构造器,在首行首句写this(name,age);

最后在定义一个showInfo方法用于打印

public static void main(String[] args) {
        //调用无参构造器
        Person3 p0 = new Person3();
        p0.showInfo();
        //调用两个参数构造器
        Person3 p1 = new Person3("小黑",18);
        p1.showInfo();

        //调用全参构造器
        Person3 p2 = new Person3("张三",29,'男');
        p2.showInfo();
    }
}

我们可以在main方法里利用无参构造器,双参构造器,全参构造器分别实例化一个对象并打印结果:

3.3代码块的学习

构造代码块:

也叫动态代码块,位置:与构造器并列都是在类体中;

特点:构造器执行一次,动态代码块就会执行一次,并且先于构造器执行,

用法:一般用于统计一个类创建了多少个对象,或者提前给成员变量赋值;

静态代码块:

需要前缀修饰词static,位置:与构造器并列,都是在类体中,

特点:只执行一次,在类加载期间就将该类的信息加载到内存

作用:一般用于加载静态资源图片,音频,视频到内存中

int a;
int b;
    static {
        System.out.println("---静态块执行了---");
    }
    {
        System.out.println("---动态块执行了---");
        a = 100;
        b = 200;
    }
    public BlockDemo() {
        System.out.println("---无参---");
    }
    public BlockDemo(int a, int b) {
        this.a = a;
        this.b = b;
        System.out.println("---有参---");
    }
    /**
     * String toString() :将对象的成员信息变成一串字符并返回
     * 该方法,在将引用变量放在输出语句中时,会默认调用
     */
    public String toString() {
        return "a: " + a + ", b: " + b;
    }
}

我们首先定义两个成员变量,构造一个静态块打印出,静态块执行了,再构造一个动态块打印动态块执行了,并将100赋值给a,200赋值给b,然后定义一个无参构造器,再定义一个全参构造器,之后定义一个toString( )方法,返回的结果时a和b的值

public class BlockDemo {
    public static void main(String[] args) {
        //调用无参构造器实例化对象
        BlockDemo bd = new BlockDemo();
        System.out.println(bd.toString());
        //调用有参构造器实例化对象
        BlockDemo bd2 = new BlockDemo(10,20);
        System.out.println(bd2); //默认调用了toString()方法
    }

在上述代码中,我们使用main方法,调用无参构造器实例化对象,然后通过对象调用toString方法

之后使用有参构造器实例化一个对象bd2,打印时会默认调用toString方法;

通过运行结果我们可以发现,静态块是在类加载期间运行的,所以静态块执行的最早,其次是我们在调用无参构造器时,动态块会先于构造器执行,每次在实例化一个对象时,动态块都会执行一次

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值