Loading

java.面向对象设计的核心——类和对象

面向对象的三条学习主线

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

面向过程(POP)与面向对象(OOP)

    二者都是一种思想,面向对象是相对于面向过程而言。面向过程,强调的是功能行为,以函数为最小单位,考虑怎么做。面向对象,将功能封装进对象,强调具备功能的对象,以类/对象为最小单位,考虑谁来做。
    面向对象更加强调运用人类在日常的思维逻辑中采用的思想方法与原则,如抽象、分类、继承、聚合多态等。

面向对象程序设计的三大基本特征

封装性(Encapsulation)

封装是一种信息隐蔽技术,它体现于类的说明,是对象的重要特征。封装把数据和加工该数据的方法(函数)打包为一个整体,以实现独立性很强的模块,使得用户只能见到对象的外特性(对象能接受哪些信息,具有哪些处理能力),而对象的内特性(保存内部状态的私有数据和实现加工能力的算法)对用户是隐蔽的。封装的目的在于把对象的设计者和对象的使用者分开,使用者不必知晓其行为实现的细节,只需要用设计者提供消息来访问该对象

继承性(Inheritance)

继承性是子类共享其父类数据和方法的机制他由类的派生功能体现。一个类直接继承其他类的全部描述,同时可以修改和扩充。继承具有传递性。类的对象是各自封闭的,如果没有继承性机制,则类中的属性(数据成员)、方法(对数据的操作)就会出现大量重复。继承不仅支持系统的可重用性,而且还促进系统的可扩展性。

多态性(Polymorphism)

对象通常根据接受到的消息做出动作。当同一消息被不同的对象接受并产生不同的行动,这种现象称为多态性。例如:同样是run方法,鸟调用时是飞,野兽调用时是奔跑。
利用多态性,用户可以发送一个通用信息,而将所有的实现细节都留给接受消息的对象自行决定。

类和对象的基本概念

类和对象是面向对象的核心概念
类是对一类事物的描述,是抽象的、概念上的定义
对象是实际存在的该类事物的每个个体,也称为实例

    类是一个抽象的概念,要利用类的方式解决问题,必须用类创建一个实例化的对象,然后通过对象去访问类的成员变量,去调用类的成员方法来实现程序的功能。比如“汽车”是一个抽象的概念,只有使用一辆具体的汽车才能感受汽车的功能。
    一个类可以创建多个类的对象,它们具有相同的属性模式,但可以具有不同的属性值。java程序为每个对象都开辟了内存空间,已保存各自的属性值。

对象

    对象(object)是类的实例化后的产物。对象的特征分为静态特征和动态特征。
    静态特征是指对象的外观、特质、属性等。动态特征是指对象具有的功能、行为等。
    人们将对象的静态特征抽象为属性,用数据来描述,在JAVA语言中称之为成员变量。而将动态特征抽象为行为,用一组代码来表示,完成对数据的操作,在JAVA语言中称之为方法(Method)。
    一个对象是由一组属性和一类属性进行的操作(即方法)构成的。

类的声明与定义

限修饰符

在java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限
  1. public:公共的
  2. protected:受保护的
  3. default:默认的
  4. private:私有的
public protected default(空的) private
同一类中
同一包中(子类与无关类)
不同包的子类
不同包中的无关类
**public具有最大权限。private则最小权限
编写代码时,如果没有特殊考虑,建议这样使用权限:**
  1. 成员变量使用private,隐藏细节
  2. 构造方法使用public,方便创建对象
  3. 成员方法使用public,方便调用方法

类的声明

[标识符] class 类名称
{
    //类的成员变量
    //类的方法
}
声明类使用的class关键字。声明一个类时,在class关键字后面加上类的名称,
标识符可以是public、private、protected或者完全省略,类名称只要是一个合法的表示符即可,但从程序的可读性方面来看,类名称建议是由一个或多个有意义的单词连缀而成,形成自我注释(SelfDocumenting),每个单词首字母大写,单词间不要使用其他分隔符。

类的组成

class Person {
    String name;    
    int age;    
    void talk(){        
        System.out.println("我是"+naem+",今年"+age+"岁");    
        }
}
首先用class声明了一个名为Person的类,在这里Perosn是类的名称
第02和03行声明了两个属性(即描述数据的变量)name和age,name为String(字符串类型)
型,age为int(整型)型。
第04~06行声明了一个talk()方法----操作数据(如name和age)的方法,此方法用于向屏幕打印信息。

类的定义

    对于一个类而言。构造方法、属性和方法,是常见的3种成员。可以定义零个或者多个。如果3中成员都只定义零个,实际上这是一个空类。
    各个成员之间定义的先后顺序没有任何影响。各个成员可以互相调用,但是static修饰的成员不能被非static修饰的成员访问。

类的定义使用

public class ColorDefine {
    String color = "黑色";    
    void getMes(){        
        System.out.println("定义类");    
    }    
    
    public static void main(String[] args) {        
        ColorDefine b = new ColorDefine();
        System.out.println(b.color); //黑色
        b.getMes();  //定义类    
        }
    }

类的属性

属性的定义
[修饰符] 属性类型 属性名 [=默认值]

  1. 修饰符:修饰符可以省略,使用默认的访问权想default,也可以是显示的访问控制符public、protected、private及static、final,其中3个访问控制符public、protected和private只能使用其中之一,static和final则可组合起来修饰属性。
  2. 属性类型:属性类型可以是JAVA允许的任何数据类型,包括基本类型(int、float等)和引用类型(接口、数组、类等)
  3. 属性名:从语法的角度来说,属性名则只要是一个合法的标识符即可。但如果从程序可读性的角度来看,属性名应该由一个或多个有意义的单词连缀而成,推荐第一个单词小写开头第二个大写开头,其余全部小写单词间不使用分隔符。如 String studentNumber
  4. 默认值:定义属性还可以定义一个可选的默认值
属性是一种比较符合汉语习惯的说法,在JAVA官方文献中,属性被称为Field,因此有些书籍也把“属性”翻译为“字段”或“域”,它们在本质上是一样的

属性的使用

public class usingAttribute {
    //定义两个String类型的属性str1和str2,它们是静态的,所以它们是属于类的,也就是属于这个类定义的所有对象共有,对象看到的静态属性值都是相同的
    static String str1 = "string-1";
    static String str2;

    //定义了两个String类型的属性str3和str4,因为它们是非静态的,所以它们是属于这个类所定义的对象私有的,每个对象都有这个属性,且各自的属性值可不同
    String str3 = "string-3";
    String str4;

    //定义了静态方法块,它没有名称。使用static关键字加以修饰并用大括号“{}”括起来称之为静态代码块用来初始化静态成员变量。如静态变量str2被初始化为“string-2"
    static{
        printStatic("before static");
        str2 = "String-2";
        printStatic("after static");
    }

    //定义一个方法用来打印静态成员变量
    public static void printStatic(String title){
        System.out.println("--------"+title+"---------");
        System.out.println("str1=\""+str1+"\"");
        System.out.println("str2=\""+str2+"\"");
    }

    //定义一个构造方法usingAttribute(),在这个方法中,使用了类中各个属性。构造方法与类同名,且无返回值(包括void),它主要的目的是创建对象。
    //打印一次属性,然后改变str4属性,最后再打印一次
    public usingAttribute(){
        print("before constructor");
        str4 = "string-4";
        print("after constructor");
    }

    //定义公有方法用来打印所有属性,包括静态成员
    public void print(String title){
        System.out.println("--------"+title+"--------");
        System.out.println("str1=\""+str1+"\"");
        System.out.println("str2=\""+str2+"\"");
        System.out.println("str4=\""+str4+"\"");
        System.out.println("str3=\""+str3+"\"");
    }

    public static void main(String[] args) {
        System.out.println();
        System.out.println("--------创建usingAttribute对象---------");
        System.out.println();
        //匿名对象
        new usingAttribute();
    }
}

运行结果

--------before static---------
str1="string-1"
str2="null"
--------after static---------
str1="string-1"
str2="String-2"

--------创建usingAttribute对象---------

--------before constructor--------
str1="string-1"
str2="String-2"
str3="string-3"
str4="null"
--------after constructor--------
str1="string-1"
str2="String-2"
str3="string-3"
str4="string-4"

对象的声明与使用

对象的声明

类名 对象名 = new 类名();
创建属于某类的对象,需要通过下面两个步骤来实现
1、声明指向“由类所创建的对象”的变量
2、利用new创建新的对象,并指派给先前所创建的变量

举例说明:如果要创建Person类的对象,可用下列语句实现

//1、声明一个Person对象,再用new关键字实例化Personp1
Person p1;
p1 = new Person;

//2、声明Person对象p1并直接实例化此对象
Person p1 = new Person();

对象只有在实例化之后才能被使用,而实例化对象的关键字就是new

对象的使用

如果向访问对象里的某个成员变量或方法,可以通过下面的语法来实现

对象名称.属性名     //访问属性
对象名称.方法名()   //访问方法

使用Person类的对象调用类中的属性与方法的过程

public class ObjectDemo {
    public static void main(String[] args) {
        //实例对象,调用构造方法
        Person p1 = new Person();
        //对p1的name和age进行赋值
        p1.name = "leesin";
        p1.age = 30;
        //调用talk方法
        p1.talk();
    }

    //Person类的定义
    static class Person{
        String name;
        int age;
        void talk(){
            System.out.println("我是:"+name+",今年:"+age+"岁");
        }
    }
}

匿名对象

匿名对象是指没有名字的对象。实际上,根据前面的分析,对于对象实例化的操作来讲,对象真正有用的部分在堆内存里面,而栈内存只是保存一个对象引用名称(严格来说是对象在堆内存的地址),所以所谓的匿名对象就是指,只开辟了堆内存空间,而没有栈内存指向的对象。

创建匿名对象

public class NoNameObject {
    public void say(){
        System.out.println("面向大海,春暖花开!");
    }
    public static void main(String [] args){
        //匿名对象,没有被其他对象所引用
        new NoNameObject().say();  //面向大海,春暖花开!
    }
}

匿名对象有两个特点:

1、匿名对象没有被其他对象所引用,即没有栈内存指向
2、因为没有栈内存指向,所以只能使用一次,之后就无法找寻的垃圾对象,会被垃圾回收器收回

对象的比较

    有两种方式可用于对象间的比较:
        1、利用“==”运算符
            “==”运算符用于比较两个对象的内存地址值是否相等
        2、利用equals()方法
            equals()方法用于比较两个对象的内容是否相等

对象比较的范例

public class CompareObject {
    public static void main(String[] args) {
        String s1 = new String("java");
        String s2 = new String("java");
        String s3 = s2;

        if(s1 == s2){
            System.out.println("s1 == s2");
        }else {
            System.out.println("s1 != s2"); //s1 != s2
        }

        if (s2 == s3){
            System.out.println("s2 == s3"); //s2 == s3
        }else {
            System.out.println("s2 != s3");
        }

        System.out.println(s3.equals(s2)); //true
        System.out.println(s3.equals(s1)); //true
    }
}

对象数组的使用

把类理解为用户自定义的数据类型,它和基本数据类型(int、float等)具有等同的地位。。
通过两个步骤可以用数组来存放对象
    1、声明以类为数据类型的数组变量,并用new分配内存空间给数组
    2、用new产生新的对象,并分配内存空间给它

要创建3个Person类型的数组元素,语法如下

Person p[]; //声明Person类类型的数组变量
p = new Person[3]; //用new分配内存空间

创建好数组元素之后,便可把数组元素指向Person类所定义的对象

p[0] = new Person();
p[1] = new Person();
p[2] = new Person();

例:创建一个Person类

public class Person {
    String name;
    int age;

    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }

    public String talk(){
        return "我是" + this.name + ",今年:" + this.age + "岁";
    }
}

例:声明对象数组

public class ObjectArray {
    public static void main(String[] args) {****
        Person p[] = {
                new Person("leesin",30),
                new Person("zed",35),
                new Person("king",25)
        };

        for (int i = 0; i < p.length; i++) {
            System.out.println(p[i].talk());
        }
        /*
        我是leesin,今年:30岁
        我是zed,今年:35岁
        我是king,今年:25岁
         */
    }
}

关键字

this关键字

1、this调用本类中的属性,也就是类中的成员变量;
2、this调用本类中的其他方法;
3、this调用本类中的其他构造方法,调用时要放在构造方法的首行

解析上面Person类中this关键字的使用

static关键字

程序中如果用static定义属性的话,则此属性成为静态属性

没有使用静态属性的不便

class Person{
    String name;
    int age;
    String nation;

    public Person(String name,int age,String nation){
        this.name = name;
        this.age = age;
        this.nation = nation;

    }

    public String talk(){
        return "我是:"+this.name+",今年:"+this.age+",来自:"+this.nation;
    }
}
public class noStaticDemo {
    public static void main(String[] args) {
        Person p1 = new Person("李青",30,"艾欧尼亚");
        Person p2 = new Person("艾瑞利亚",35,"艾欧尼亚");
        System.out.println(p1.talk());
        System.out.println(p2.talk());
    }

    /*output
        我是:李青,今年:30,来自:艾欧尼亚
        我是:艾瑞利亚,今年:35,来自:艾欧尼亚
     */
}
在程序中可以看到,两个Person对象都有一个nation属性,而且都相同。
如果要生产500个对象,每个对象的nation属性都相同,浪费空间不说,如果想修改所有人的nation属性,就要实施500次nation属性修改,这显然太麻烦。所以java提供了static关键字,用它来修饰类的属性后,此属性就是公共属性了。

用static修饰nation

class Person{
    String name;
    int age;
    static String nation;

    public Person(String name,int age,String nation){
        this.name = name;
        this.age = age;
        this.nation = nation;

    }

    public String talk(){
        return "我是:"+this.name+",今年:"+this.age+",来自:"+this.nation;
    }
}
public class noStaticDemo {
    public static void main(String[] args) {
        Person p1 = new Person("李青",30,"艾欧尼亚");
        Person p2 = new Person("艾瑞利亚",35,"艾欧尼亚");
        System.out.println("修改之前的信息:"+p1.talk());
        System.out.println("修改之前的信息:"+p2.talk());
        System.out.println("---------修改之后的信息----------");
        p1.nation = "均衡教派";
        System.out.println("修改之后的信息:"+p1.talk());
        System.out.println("修改之后的信息:"+p2.talk());
    }

    /*output
        修改之前的信息:我是:李青,今年:30,来自:艾欧尼亚
        修改之前的信息:我是:艾瑞利亚,今年:35,来自:艾欧尼亚
        ---------修改之后的信息----------
        修改之后的信息:我是:李青,今年:30,来自:均衡教派
        修改之后的信息:我是:艾瑞利亚,今年:35,来自:均衡教派
     */
}

final关键字

final关键字用于修饰不可改变的内容

final:不可改变。可以用于修饰类、方法和变量

  • 类:被修饰的类不能被继承
  • 方法:被修饰的方法不能被重写
  • 变量:被修饰的变量不能被重新赋值

修饰类

final class 类名{
}

修饰方法

修饰符 final 返回值类型 方法名(参数列表){
    //方法体
}

修饰变量

1、局部变量--基本类型
基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改

public class Demo01 {    
    public static void main(String[] args) { 
        //声明变量,使用final修饰        
        final int a;        
        //第一次赋值        
        a = 10;       
        //第二次赋值       
        //a = 20; //报错,不可重新赋值        
        
        //声明变量,直接赋值,使用final修饰        
        final int b = 10;        
        //第二次赋值        
        b = 20;//报错,不可重复赋值    
    }
}

**2、局部变量--引用类型
引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再更改,但是不影响对象内部的成员变量值的修改
**

public class Demo02 {
    public static void main(String[] args) {
        //创建user对象        
        final User u = new User();        
        //创建另一个User对象        
        //u = new User();  // 报错,指向了新对象,地址值改变        
        //调用setName方法        
        u.setName("leesin");    
    }
}

3、成员变量
成员变量设计到初始化问题,初始化方式有两种,只能二选一

  • 显示初始化
public class User{
    final String USERNAME = "leesin"
    private int age;
}
  • 构造方法初始化
public class User{
    final String USERNAME;
    private int age;
    public User(String username, int age){
        this.USERNAME = username;
        this.age = age
    }
}

被final修饰的常量名称,一般都有书写规范,所有的字母都大写

posted @ 2020-01-01 16:50  yonugleesin  阅读(1261)  评论(0编辑  收藏  举报