面向对象

面向对象思想

面向对象相比于面向过程是一种更优秀的程序设计方法,它的基本思想是使用类、对象、继承、封装、消息等基本概念进行程序设计。它从现实世界中的客观存在的事物为中心来思考,认识问题。并根据这些事物的本质特点。把它们抽象地表示为系统的类作为系统的基本构成单元。

面向对象与面向过程理解

针对“猪八戒吃西瓜”这件事;

在面向过程中,一切以函数为中心,函数最大;可以描述为:

吃(猪八戒,西瓜)

在面相对象中,一切以对象为中心,对象最大;可以描述为:

猪八戒.吃(西瓜)

对于面象类和对象的理解

定义一个dog类来说;

定义一个类相当于定义了dog这个物种,这个物种有名字,有年龄,有体重等特征,这相当于类中的成员变量(属性);dog这个物种可以吃饭、睡觉、跑步等动作,相当于类中的成员方法。

但具体是哪一条dog,就要把它实例化成一个对象,给它名字,它有自己的年龄,有自己的体重,它会吃饭,睡觉。而且每个dog的名字年龄都不一样,所以可以将这个类实例化成很多对象。(在测试类中实例化 也就是有主函数的类里面进行实例化)

类和对象的具体概念:

  • 一组相关的属性和行为的集合
  • 对象是该类事物的具体表现

类的定义

在一个java文件(包)中写两个类:一个基本类,一个测试类
建议文件名称和测试类名称一致。

格式:

[修饰符] class 类名{
	零到多个构造器定义;
	零到多个成员变量;
	零到多个方法
}
  • 修饰符:public、final、abstract,或者完全省略;
  • 类名:从可读性方面,必须是一个或多个有意义的单词连缀而成,每个单词首字母大写,其他字母全部小写,单词和单词之间不能有空格。
  • 成员变量用于定义该类或该类的实例所包含的数据状态;
  • 方法则用于定义该类或该类实例的行为特征或者功能实现;
  • 构造器用于构造该类的实例。
package miianxiangduixiang;

//定义类
public class Dog {
    
    //成员变量
    String name="bobby"; //给出默认值
    int    age;
    String sex;

    //成员方法
    public void eat(String name){//吃的方法
        System.out.println("the "+name+" dog is eating");
    }

    public void sleep(String name) {//睡觉的方法
        System.out.println("the "+name+" dog is sleeping");
    }
}

成员变量:

  • 语法格式:[修饰符] 类型 成员变量名 [=默认值];
  • 修饰符:可以省略,也可以是public、protected、private、static、final。
  • 类型:可以是Java语言中允许的任何数据类型。
  • 成员变量:合法标识符即可,但从语法角度:可以由一个或者多个单词组成,第一个单词首字母小写,以后每个单词首字母大写,其余全部小写,单词和单词之间不要有分隔符;
  • 默认值:定义成员变量还可以指定一个可选默认值。

实例:

//成员变量
    String name="bobby"; //给出默认值
    int    age;
    String sex;

成员方法:

  • 语法格式:[修饰符] 方法返回值类型  方法名(形式参数){
                      由零条到多条之可执行语句组成的方法体
                      }
  • 修饰符:可以省略,也可以是public、protected、private、static、final。
  • 方法返回值类型:返回值可以是Java语言循序的任何数据类型,如果没有返回值,则用void来声明;
  • 方法名:合法标识符即可,但从语法角度:可以由一个或者多个单词组成,第一个单词首字母小写,以后每个单词首字母大写,其余全部小写,单词和单词之间不要有分隔符;
  • 形参列表:用于定义该方法可以接受的参数。

方法体中的语句之间有严格的执行顺序,排在方法体前面的先执行,排在后面的后执行。

实例:

//成员方法
    public void eat(String name){//吃的方法
        System.out.println("the "+name+" dog is eating");
    }

    public void sleep(String name) {//睡觉的方法
        System.out.println("the "+name+" dog is sleeping");
    }

构造器

构造器是一个类创建对象的根本途径,如果没有构造器这个类将无法创建对象实例。Java类中提供了一个默认的构造器,如果程序员在提供一个自定义的构造器,前者将被覆盖。(默认构造器为无参构造器)

无参构造器(默认构造器):

public Dog() {
		super();
	}

有参构造器:

[修饰符] 构造器名称(形参列表){
		//由零条到多条可执行语句组成的执行体
}
  • 修饰符:可以是public、protected、private.
  • 构造器名:必须与类名相同;
  • 形参列表:和定义方法形参列表的格式相同;

构造器既不能定义返回值类型,也不能使用void声明构造器没有返回值。如果为构造器定义了返回值类型,或使用void来定义,编译时不会出错,但Java会把这个所谓的构造器当做方法来处理。

实际上类的构造器是有返回值类型的,当使用new关键字来调用构造器时,构造器返回该类的实例,可以把这个实例当做构造起的返回值,注意:不要在构造器里显式使用return来返回当前类的对象,因为构造器的返回值是隐式的。

实例化

//通过new关键字来调用Dog类的构造器即可创建这个类的实例
        //将返回的实例赋给dog变量
        Dog bobby=new Dog();//bobby代表实例化狗的名字。

调用该类的方法和属性:

//        初始化类的成员变量
        String name=dog.name;
        int age=dog.age;
        String sex=dog.sex;
        dog.Dog();
        name="bobby";
        age=4;
        sex="boy";

//        调用成员变量
        System.out.println("the "+sex+" named "+name+" is "+age);

//        调用成员方法
        dog.eat(name);
        dog.sleep(name);
    }
}
/*the boy named bobby is 4
the bobby dog is eating
the bobby dog is sleeping
*/

实例化两个对象的内存图示:

        Dog dog1=new Dog();
//        初始化类的成员变量
        dog1.name="bobby";
        dog1.age=4;
        dog1.sex="gril";

        System.out.println(dog1);
//        mianxiangduixiang.Dog@1540e19d
        
        Dog dog2=new Dog();
        dog2.name="Harry";
        dog2.age=2;
        dog2.sex="boy";

        System.out.println(dog2);
//        mianxiangduixiang.Dog@677327b6

内部机制:

可以看出Dog对象由多块内存组成,不同内存块分别存储了Dog对象的不同成员变量。当把这个Dog对象赋值给一个引用变量时(例如dog1,dog2),Java队让这个引用变量指向这个对象即可。
和数组类型相类似,类也是一种引用数据类型,因此变量只是一个引用,它被放在栈内存内,而实际的对象在堆内存内。实际上java中的引用就是C里面的指针,只是引用是被封装起来的,不需要那么繁琐的操作
Java程序不允许直接访问堆内存中的对象,只能通过引用来访问(实例化)。
可以有多个引用变量来指向同一个对象进行操作,但还是如果没有引用变量来指向该对象,那么程序将无法访问该对象,这个对象就变成了垃圾,Java的垃圾回收机制将会把它回收掉,释放所占内存区。

对象this的引用

Java提供了一个关键字this,this关键字总是指向调用该方法的对象。根据this出现的位置不同,this作为对象的默认引用有两种情形。

  1. 构造器中引用该构造器正在初始化的对象。
  2. 在方法中引用定义该方法的对象。

this关键字最大的作用就是让类的一个方法,访问该类的另一个方法或实例变量。

this可以代表任何对象,当this出现在某个方法体中时,它所代表的对象是不确定的,但他的类型是确定的:它所代表的只能是当前类的实例,只有当这个方法被调用时,它所代表的队形才能被确定下来,谁在调用这个方法,this就代表谁。大部分时候,一个方法访问该类中定义的其他方法、成员变量时加不加this前缀的效果是一样的。

public class Cat {

    public void run(){
        System.out.println("正在执行run方法");
    }

    public void jump(){
        this.run();
        System.out.println("正在执行jump方法");
    }
}

对于static修饰的方法,则可以使用该类来直接调用该方法,如果在static修饰的方法中使用this关键字,则这个关键字就无法指向合适的对象,所以在static修饰的方法中不能使用this引用。

关键字static

被static修饰的方法或者变量属于类自身的方法或变量,不属于这个类的实例。
使用static修饰的方法或变量既可以使用类来调用,又可以使用实例来调用。因为static修饰的方法和变量被被放在内存中方法区的静态区,和类一起创建。而不像那些没有用static修饰的方法或变量,在实例化调用时才被创建。

实例:

定义一个Cat类,其中变量name和方法run被static所修饰,称为静态变量和静态方法,而age和方法jump没有被修饰,所以是普通变量和方法。

package mainxiangduixiang;

public class Cat {

    static String name="MiMi";
    double age=3.0;

    public static void run(){
        System.out.println("正在执行run方法");
    }

    public void jump(){
        System.out.println("正在执行jump方法");
    }
}

调用:可以看到报错信息,因这时候并没有实例化对象,但是被static修饰的变量和方法已经被放在静态区域;而此时变量和age和方法jump还没有被创建,所以无法引用。

package mianxiangduixiang;

public class CatTest {
    public static void main(String[] args) {

        System.out.println(Cat.name);
//        MiMi
//        System.out.println(Cat.age);
//Error:(8, 31) java: 无法从静态上下文中引用非静态 变量 age

        Cat.run();
//        正在执行run方法

        Cat.jump();
//        Error:(14, 12) java: 无法从静态上下文中引用非静态 方法 jump()
    }

}

实例化以后再来试试:可以看到运行没有报错;

package mianxiangduixaing;

public class CatTest {
    public static void main(String[] args) {

        //为了验证效果,让对象名和类名一样
        Cat Cat=new Cat();

        System.out.println(Cat.name);
        System.out.println(Cat.age);

        Cat.run();

        Cat.jump();
    }

}
/*MiMi
3.0
正在执行run方法
正在执行jump方法*/

内存图示:

实际上通过实例来访问类变量和类方法是一个错误,因为它们不属于实例。应该通过类本身来访问,这样会增加程序的可读性和明确性。

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值