JAVA学习笔记面向对象

Posted 目之子叶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA学习笔记面向对象相关的知识,希望对你有一定的参考价值。

  • 编程语言的发展
  • 面向过程的设计思想
  • 面向对象的设计思想
  • 对象和类的概念
  • 类之间的关系
  • 对象和引用
  • Java类的定义
  • 构造函数
  • 对象的创建和使用
  • this关键字
  • static关键字
  • package和import语句
  • 访问控制
  • 类的继承
  • 方法的重写
  • final关键字
  • object类
  • 对象转型
  • 多态
  • 抽象类
  • 接口

编程语言的发展

  • 机器语言
  • 汇编语言
  • 高级语言–面向过程的语言
  • 面向对象的语言

面向过程的思想和面向对象的设计思想

面向对象思维:

  • 合适的方法出现在合适类中

在问题域中,不再考虑一步一步的过程,而是将问题域中的对象抽象出来,弄清楚对象和对象之间的关系。

这里写图片描述

重点:面向对象实现的三个步骤:

  1. 问题中有哪些类哪些对象。
  2. 这些类这些对象有哪些属性和方法。
  3. 类和类之间具备哪些关系:关联(弱),继承(强),聚合(强),实现(父类和子类之间),多态。

对象和类的概念

  • 类:一类事物的一个抽象,包括静态属性(成员变量)和动态属性(方法)。“瓶子”
  • 对象:一类事务的具体的实例。“某个瓶子”

    这里写图片描述

类(对象)之间的关系 之

  • 关联关系

    这里写图片描述

    关联关系:某个类的方法关联到某个类的对象。

  • 继承关系(一般和特殊)

    容易形成继承树

    XX是一种XX:球类运动员是一种运动员。

    这里写图片描述

    一类可以从不同的多个类继承。【多重继承:C++】

  • 聚合关系(整体和部分)

    聚集:松耦合

    组合:必不可少

    这里写图片描述

  • 实现关系

    父类的方法,子类来实现。

    这里写图片描述

  • 多态

    这里写图片描述

练习:

这里写图片描述

类:旅行社,旅客,机票,账目

机票
属性:班次
方法:送票,作废,显示航班时间

Java与面向对象

必须先定义类才能有对象

  • 对象是Java程序的核心,在Java程序中“万事万物皆对象”。
  • 对象可以看成是静态属性(成员变量)和动态属性(方法)的封装体。
  • 类是用来创建同一类对象的“模板”,在一类中定义了该类对象所应具有的成员变量及方法。
  • J2SDK本身提供了很多类供编程人员使用,编程人员也可定义自己的类。

为什么用对象?

这里写图片描述

Java类的定义

约定俗成的命名规则:

  • 类名的首字母大写
  • 变量名和方法名的首字母小写
  • 运用驼峰标识
//用class关键字定义一个类,例如:
class Person{

    //成员变量定义
    private int id;
    private int age = 20;

    //方法定义
    public int getAge(){
        return age;
    }
    public void setAge(int i){
        age = i;
    }
    public int getId(){
        return id;
    }
}

成员变量

  • 成员变量可以使Java语言中任何一种数据类型(包括基本类型和引用类型)。

  • 在定义成员变量时,可以对它初始化,也可以不对它初始化,不初始化时,Java会给出默认初始化值。

    这里写图片描述

  • 成员变量的作用范围为整个类体。

引用

Java中除了基本类型之外的变量类型都称为引用类型。

Java中的对象是通过引用对其操作。

  • 基本类型:占一块内存。
  • 引用类型:占两块内存(一小块内存指向一大块内存)。(引用(栈) + 真正的对象(存放在堆内存中))

类和对象的关系

这里写图片描述

构造方法(构造函数)

  • 使用new+构造方法 创建一个新对象。
  • 构造函数是定义在Java类中的一个用来初始化对象的函数。
  • 构造函数与类同名且没有返回值。

    public class Person{
        int id;
        int age;
        Person(int n,int i){
                id = n;
                age = i;
    }
    }
  • 创建对象时,使用构造函数初始化对象的成员变量。

    public class Test{
        public static void main(String args[]){
                Person tom = new Person(1,25);
                Person john = new Person(2,27);
    }
    }

    这里写图片描述

  • 当没有指定构造函数时,编译器为类自动添加形如:类名( ){ } 的构造函数。

    class Point{
       public int x;
       public int y;    
    }
    
    ... Point p = new Point();

    这里写图片描述

方法重载

  • 方法的重载是指一个类中可以定义有相同的名字,但参数不同的多个方法。调用时,会根据不同参数表选择对应的方法。

    void info() {
        System.out.println("my id is :" + id);
    }
    
    void info(String t) {
        System.out.println(t + " my id is" + id);
    }
  • 构造方法也可以重载。

    Person() {
        id = 100;
        age = 20;
    }
    
    Person(int _id) {
        id = _id;
        age = 30;
    }
    
    Person(int _id, int _age) {
        id = _id;
        age = _age;
    }
    

对象创建与使用

  • 必须使用 new 关键字创建对象
  • 使用对象【引用.成员变量】来引用对象的成员变量
  • 使用对象【引用.方法(参数列表)】来调用对象的方法
  • 同一类的每一对象有不同的成员变量存储空间
  • 同一类的每个对象共享该类的方法
    • 非静态方法是针对每个对象进行调用

this 关键字

  • 在类的方法定义中使用的this关键字代表使用该方法的对象的应用
  • 在必须指出当前使用方法的对象是谁时要使用this
  • 有时使用this可以处理方法中成员变量和参数重名的情况
  • this可以看作是一个变量,它的值时当前对象的引用

    public class Leaf{
        int i = 0;
        Leaf(int i ){ this i = i; }
        Leaf increament() {
            i++;
            return this;
        }
        void print(){ System.out.println("i = "+i); }
        public static void main(String[] args){
            Leaf leaf = new Leaf(100);
            leaf.increament().increament().print();
        }
    }

static 关键字

  • 在类中,用static声明的成员变量为静态成员变量,它为该类的公用变量,在第一次使用时被初始化,对于该类的所有对象来说,static成员变量只有一份。
  • 用static声明的方法为静态方法,在调用该方法时,不会将对象的引用传递给它,所以在static方法中不可访问非static的成员。
    • 静态方法不再是针对某个对象调用,所以不能访问非静态成员。
  • 可以通过对象引用或类名(不需要实例化)访问静态成员。

package 和 import 语句

为了便于管理大型软件系统中数目众多的类,解决类的命名冲突问题,Java引入包(package)机制,提供类的多重类命名空间。

  • 如果想把一个类放入包中,在这个类源文件第一句话写package
  • 必须保证该类的class文件位于正确目录下
  • 该类的源码可能会产生影响
    • 删除或转移到另外的目录
  • 另外的类想访问的话
    • 写全名
    • 引入
      • *
      • 具体类名
      • 访问位于同一个包中的类不需要引入
  • 必须class文件的最上层包的父目录位于classpath下
  • 执行一个类需要写全包名

J2SDK 中主要的包介绍

  • java.lang 包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能。
  • java.awt 包含了构成抽象窗口工具类(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。
  • java.applet 包含applet运用所需的一些类。
  • java.net 包含执行与网络相关的操作的类。
  • java.io 包含能够提供多种输入/输出功能的类。
  • java.util 包含一些实用工具类,如定义系统特性、实用与日期日历相关的函数。
  • java.lang包中的类,不需要引入,可以直接使用。
  • 把自己的类打成jar包:jar -cvf xxx.jar * . *

类的继承

  • Java中使用extends关键字实现类的继承机制,其语法规则为:

    <modifier> class <name>  [extends <superclass>]
    { ...  ... }
  • 通过继承,子类自动拥有了基类(superclass)的所有成员(成员变量和方法)。

  • Java只支持单继承,不允许多继承:

    • 一个子类只能有一个基类,一个基类可以派生出多个子类
    //继承中的权限控制
    class Parent{
        private int n_private = 1;
                    int n_friendly = 2; // 包权限:同一个包内可以访问
        protected int n_protected = 3;
        public int n_public = 4;
    }
    class Child extends Parent {
         public void f () {
                // n_private = 10; 错误,继承中私有变量不能访问
                 n_friently = 20;
                 n_protected = 30;
                 n_public = 40;
         }
    }

访问控制

  • Java权限修饰符public protected private 置于类的成员定义前,用来限定其他对象对该类对象成员的访问权限。

    这里写图片描述

  • 对于class的权限修饰只可以用 public 和 default

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

方法重写

  • 在子类中可以根据需要对从基类中继承来的方法进行重写

  • 重写方法必须和被重写方法具有相同方法名称,参数列表和返回类型

  • 重写方法不能使用比被重写方法更严格地访问权限

super 关键字

  • 在Java类中使用 super 来引用基类的成分,例如:

    class FatherClass {
        public int value;
        public void f () {
                value = 100;
                System.out.println("FatherClass.value = "+value);
        }
    }
    class ChildClass extends FatherClass {
        public int value;
        public void f () {
                super.f(); //super指向当前对象的父对象
                value = 200;
                System.out.println("ChildClass.value ="+value);
                System.out.println(value);
                System.out.println(super.value);
    }
    }

继承中的构造方法

  • 子类的构造的过程中必须调用其基类的构造方法。
  • 子类可以在自己的构造方法中使用super(argument_list)调用基类的构造方法。
    • 使用this(argument_list)调用本类的另外的构造方法
    • 如果调用super,必须写在子类构造方法的第一行
    • 如果子类的构造方法中没有显示地调用基类构造方法,则系统默认调用基类无参数的构造方法
    • 如果子类构造方法中既没显示调用基类构造方法,而基类中又没有无参的构造方法,则编译出错。

参数拷贝来拷贝去,最终剩下堆里的对象和栈里的引用以及数据区的静态变量。

Object类

  • Object 类是所有Java类的根基类
  • 如果在类的声明中未使用extends关键字指明其基类,则默认基类为Object类

         public class Person {
              ...   ...
         }

    等价于:

         public class Person extends Object{
              ...   ...
         }

toString 方法

  • Object 类中定义有public String toString() 方法,其返回值是String类型,描述当前对象的有关信息
  • 在进行String与其它类型数据的连接操作时(如:System.out.println(“info”+person)),将自动调用该对象类的toString() 方法
  • 可以根据需要在用户自定义类型中重写toString()方法

hashcode 解释

每一个对象都有一个独一无二的哈希编码,可以通过这个哈希编码在内存中找到这个对象并确定这个对象的位置。

equals 方法

  • public boolean equals(Object obj)方法
    • 定义对象是否“相等”的逻辑
  • Object 的 equals方法定义为:x.equals(y)当x和y是同一个对象的引用时,返回true否则返回false
  • J2SDK提供的一些类,如String,Date等,重写了Object的equals方法,调用这些类的equals方法,x.equals(y),当x和y所引用的对象是同一类对象且属性内容相等时(并不一定是相同对象),返回true否则返回false
  • 可以根据需要在用户自定义类型中重写equals方法

    public class TestEquals {
         public static void main(String[] args) {
    
                Cat c1 = new Cat(1,2,3);
                Cat c2 = new Cat(1,2,3);
    
                //类Cat重写从Object类默认集成的方法equals()
                System.out.println(c1 == c2); //false
                System.out.println(c1.equals(c2)); //true
    
                //String类已经中重写了方法equals()
                String s1 = new String("hello");
                String s2 = new String("hello");
                System.out.println(s1 == s2); //false
                System.out.println(s1.equals(s2)); //true
         }
    }
    
    class Cat {
        int color;
        int height, weight;
        public Cat(int color, int height, int weight) {
                this.color = color;
                this.height = height;
                this.weight = weight; 
        }
        public boolean equals(Object obj) {
            if(obj == null) return false;
            else {
                if(obj instanceof Cat) {
                    Cat c = (Cat)obj;
                    if(this.color == c.color && this.height == c.height && this.weight == c.weight) {
                        return true;                        
                    }   
                }
            }
            return false;
        }   
    }

对象转型(casting)

  • 一个基类的引用类型变量可以“指向”其子类的对象
  • 一个基类的引用不可以访问其子类对象新增加的成员(属性和方法)
  • 可以使用引用变量 instanceof 类名来判断该引用型变量所“指向”的对象是否属于该类或该类的子类。
  • 子类的对象可以当做基类的对象来使用称为向上转型(upcasting),反之称为向下转型(downcasting)。

    class Animal {
        public String name;
        Animal (String name) {
                this.name = name;
        }
    }
    class Cat extends Animal {
        public String eyesColor;
        Cat (String n, String c) {
                super(n);
                eyesColor  = c;
        }
    }
    class Dog extends Animal {
        public String furColor;
        Dog (String n, String c) {
                super(n);
                furColor  = c;
        }
    }
    public class Test {
        public static void main(String args[]) {
                Animal a = new Animal("name");
                Cat c = new Cat("catname","blue");
                Dog d = new Dog("dogname","black");
    
        System.out.println(a instanceof Animal); //true 
        System.out.println(c instanceof Animal); //true
        System.out.println(d instanceof Animal); //true
        System.out.println(a instanceof Cat); //false
    
        a = new Dog("bigyellow","yellow");
        System.out.println(a.name); //bigyellow
        //System.out.println(a.furname); //!error
        System.out.println(a instanceof Animal); //true 
        System.out.println(a instanceof Dog); //true
        Dog d1 = (Dog)a; //要加强制转换符
        System.out.println(d1.furColor); //yellow                       
        }
    }
    public class Test {
         public static void main(String args[]) {
                 Test test = new Test();
                 Animal a = new Animal("name");
                 Cat c = new Cat("catname","blue");
                 Dog d = new Dog("dogname", "black");
                 test.f(a);
                 test.f(c);
                 test.f(d);
         }
         public void f(Animal a) {
                 System.out.println("name: "+a.name);
                 if(a instanceof Cat) {
                         Cat cat = (Cat)a;
                         System.out.println(" "+cat.eyesColor+" eyes");
                 }
                 if(a instanceof Dog) {
                         Dog dog = (Dog)a;
                         System.out.println(" "+dog.furcolor+ "fur");
                 }
         }
    }

动态绑定和多态

  • 动态绑定:是指在执行期间(而非编译期间)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法
  • 下面的例子中,根据Lady对象的成员变量pet所引用的不同的实际类型而调用相应的enjoy方法

    class Animal {
        private String name;
        Animal (String name) { this.name = name;}
    
        private void enjoy() {
            System.out.println("叫声。。。。。");
        } 
    }
    class Cat extends Animal {
        private String eyesColor;
        Cat(String n, String c) { super(n); eyesColor = c;}
        public void enjoy() {
                System.out.println("猫叫声。。。。。");
        }
    }
    
    class Dog extends Animal {
        private String furColor;
        Cat(String n, String c) { super(n); furColor = c;}
        public void enjoy() {
                System.out.println("狗叫声。。。。。");
        }
    }
    
    class Lady {
        private String name;
        private Animal pet;
        Lady(String name, Animal pet) {
                this.name = name;
                this.pet  = pet;
        }
        public void myPetEnjoy() { pet.enjoy(); }
    }
    
    public class Test {
        public static void main(String args[]) {
                Cat c = new Cat("catname","blue");
                Dog d = new Dog("dogname","black");
    
        Lady l1 = new Lady("l1",c);
        Lady l2 = new Lady("l2",d);
        l1.myPetEnjoy();
        l2.myPetEnjoy();
    
        }
    }
  • 多态的存在有三个必要条件:
    1. 要有继承;
    2. 要用重写;
    3. 父类引用指向子类对象;

抽象类

  • 用abstract关键字来修饰一个类时,这个类叫做抽象类;用abstract来修饰一个方法时,该方法叫做抽象方法。
  • 含有抽象方法的类必须被声明为抽象类,抽象类必须被继承,抽象方法必须被重写。
  • 抽象类不能被实例化。
  • 抽象方法只需声明,而不需实现。

    abstract class Animal {
        private String name;
        Animal (String name) {
                this.name = name;
        }
        public abstract void enjoy();
    }
    
    class Cat extends Animal {
        private String eyesColor;
        Cat(String n, String c) {
                super(n);
                eyesColor = c;
        }
        public void enjoy() {
                System.out.println("猫叫声。。。。");
        }
    }

Final关键字

  • final 的变量的值不能够被改变
    • final 的成员变量
    • final 的局部变量(形参)
  • final 的方法不能够被重写
  • final 的类不能被继承

接口

  • 接口(interface)是抽象方法和常量值的定义的集合。
  • 从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。

    //接口中没有abstract,但是所有的都是abstract
    public interface Runner {
        //public static final int id = 1;
        int id = 1; //默认是public static final 关键字写不写都行 
        public void start();
        public void run();
        public void stop();
    }

接口特性

  • 接口可以多重实现 (意思:可以实现多继承)
  • 接口中声明的属性默认为 public static final 的,也只能是public static final
  • 接口中只能定义抽象方法,而且这些方法默认为pubic的,也只能是public的
  • 接口可以继承其他的接口,并添加新的属性和抽象类
  • 多个无关的类可以实现同一个接口
  • 一个类可以实现多个无关的接口
  • 与继承关系类似,接口与实现类之间存在多态性
  • 定义Java类的语法格式:

          <modifier>  class  <name> [extends <superclass>] [implements <interface> [, <interface>]* ] { <declarations>*}
    
    interface Singer {
        public void sing();
        public void sleep();
    }
    
    class Student implement Singer {
        private String name;
        Student(String name) {
            this.name = name;
        }
        public void study() {
            System.out.println("studying");
        }
        public String getName() {
                return name;
        }
        public void sing() {
                System.println("Student is singing");
        }
        public void sleep() {
                System.out.println("Student is sleeping");
        }
    }
    interface Singer {
        public void sing();
        public void sleep();
    }
    
    interface Painter {
        public void paint();
        public void eat();
    }
    
    class Student implement Singer {
        private String name;
        Student(String name) {
            this.name = name;
        }
        public void study() { System.out.println("studying"); }
        public String getName() { return name; }
        public void sing() { System.println("Student is singing"); }
        public void sleep() { System.out.println("Student is sleeping");  }
    }
    
    class Teacher implements Singer,Painter {
        private String name;
        public String getString() {
                return name;
        }
        Teacher(String name) {
                this.name = name;
        }
        pulic void teach() { System.out.println("teaching"); }
        pulic void sing() { System.out.println("teaching is singing"); }
        pulic void sleep() { System.out.println("teaching is sleeping"); }
        pulic void paint() { System.out.println("teaching is painting"); }
        pulic void eat() { System.out.println("teaching is eating"); }
    }
    
    public class TestImplement {
        public static void main (String[] args) {
                Singer s1 = new Student("le");
                s1.sing();
                s1.sleep();
                Singer s2 = new Teacher("steven");
                s2.sing();
                s2.sleep();
                Painter p1 = (Painter)s2;
                p1.paint();
                p1.eat();
        }
    }

总结

  • 对象和类的概念
  • 类(对象)之间的关系
  • 面向对象思想
  • class
  • new
    • 引用的概念
    • 构造方法的概念
  • 方法重载
    • 构造方法重载
  • this
  • static
  • package & import
  • private default protected public
  • extends
  • overwrite
  • final
  • Object
    • toString
    • equals
  • upcasting downcasting
  • polymophysm / dynamic binging / late binging
  • abstract class
  • interface
    • implements

以上是关于JAVA学习笔记面向对象的主要内容,如果未能解决你的问题,请参考以下文章

java学习笔记之面向对象多态

JAVA学习笔记面向对象

java学习笔记之面向对象

Java面向对象开发学习笔记

Kotlin学习笔记之面向对象

Kotlin学习笔记之面向对象