Java面向对象编程·上

简介: Java面向对象编程·上

Java面向对象编程·上

  • ⭐小提问⭐
  • 大家好,我是晓星航。今天为大家带来的是面向对象编程相关的讲解!😀

1.包

包 (package) 是组织类的一种方式.

使用包的主要目的是保证类的唯一性.

例如, 你在代码中写了一个 Test 类. 然后你的同事也可能写一个 Test 类. 如果出现两个同名的类, 就会冲突, 导致代码不能编译通过.

1.1导入包中的类

Java 中已经提供了很多现成的类供我们使用. 例如:

public class Test {
    public static void main(String[] args) {
        java.util.Date date = new java.util.Date();
        // 得到一个毫秒级别的时间戳
        System.out.println(date.getTime());
    }
}

可以使用 java.util.Date 这种方式引入 java.util 这个包中的 Date 类.

但是这种写法比较麻烦一些, 可以使用 import 语句导入包.

import java.util.Date;
    public class Test {
        public static void main(String[] args) {
            Date date = new Date();
            // 得到一个毫秒级别的时间戳
            System.out.println(date.getTime());
        }
    }

如果需要使用 java.util 中的其他类, 可以使用 import java.util.*

import java.util.*;
    public class Test {
        public static void main(String[] args) {
            Date date = new Date();
            // 得到一个毫秒级别的时间戳
            System.out.println(date.getTime());
        }
    }

提问:util地下有很多的类。难道一下子全部导入了吗?

答:不是的。Java处理的时候,需要谁,他才会拿谁。C语言里面,通过include关键字,导入之后,就会把这个头文件的内容全部拿过来。

但是我们更建议显式的指定要导入的类名. 否则还是容易出现冲突的情况.

import java.util.*;
import java.sql.*;
    public class Test {
        public static void main(String[] args) {
            // util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 编译出错
            Date date = new Date();
            System.out.println(date.getTime());
        }
    }
// 编译出错
//Error:(5, 9) java: 对Date的引用不明确
//java.sql 中的类 java.sql.Date 和 java.util 中的类 java.util.Date 都匹配

在这种情况下需要使用完整的类名

import java.util.*;
import java.sql.*;
    public class Test {
        public static void main(String[] args) {
            java.util.Date date = new java.util.Date();
            System.out.println(date.getTime());
        }
    }

注意事项: import 和 C++ 的 #include 差别很大. C++ 必须 #include 来引入其他文件内容, 但是 Java 不需要.import 只是为了写代码的时候更方便. import 更类似于 C++ 的 namespace 和 using

1.2静态导入

使用 import static 可以导入包中的静态的方法和字段.

import static java.lang.System.*;
public class Test {
    public static void main(String[] args) {
        out.println("hello");
    }
}

使用这种方式可以更方便的写一些代码, 例如

import static java.lang.Math.*;
    public class Test {
        public static void main(String[] args) {
            double x = 30;
            double y = 40;
            // 静态导入的方式写起来更方便一些. 
            // double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
            double result = sqrt(pow(x, 2) + pow(y, 2));
            System.out.println(result);
        }
    }

虽然写法很简便,但是在日常工作中我们不提倡使用它。

1.3将类放到包中

基本规则:

  • 在文件的最上方加上一个 package 语句指定该代码在哪个包中.
  • 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.bit.demo1 ).

包名要和代码路径相匹配. 例如创建 com.bit.demo1 的包, 那么会存在一个对应的路径 com/bit/demo1 来存储代码.

如果一个类没有 package 语句, 则该类被放到一个默认包中.

操作步骤1)

1.在 IDEA 中先新建一个包(软件包): 右键 src -> 新建 -> 包

2.在弹出的对话框中输入包名, 例如 com.bit.demo1

3.在包中创建类, 右键包名 -> 新建 -> 类, 然后输入类名即可.

4.此时可以看到我们的磁盘上的目录结构已经被 IDEA 自动创建出来了

5.同时我们也看到了, 在新创建的 Test.java 文件的最上方, 就出现了一个 package 语句

1.4包的访问权限控制 - [只能在当前包当中使用]

我们已经了解了类中的 public 和 private. private 中的成员只能被类的内部使用.

如果某个成员不包含 public 和 private 关键字, 此时这个成员可以在包内部的其他类使用, 但是不能在包外部的类使用.

下面的代码给了一个示例. Demo1 和 Demo2 是同一个包中, Test 是其他包中.

Demo1.java

package com.bit.demo;
public class Demo1 {
    int value = 0;
}

Demo2.java

package com.bit.demo;
    public class Demo2 {
        public static void Main(String[] args) {
            Demo1 demo = new Demo1();
            System.out.println(demo.value);
        }
    }
// 执行结果, 能够访问到 value 变量
//10

Test.java

import com.bit.demo.Demo1;
    public class Test {
        public static void main(String[] args) {
            Demo1 demo = new Demo1();
            System.out.println(demo.value);
        }
    }
// 编译出错
//Error:(6, 32) java: value在com.bit.demo.Demo1中不是公共的; 无法从外部程序包中对其进行访问

如果val没有加权限 那么它的权限默认是 包访问权限

1.5常见的系统包

1.java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。

2.java.lang.reflect:java 反射编程包;

3.java.net:进行网络编程开发包。

4.java.sql:进行数据库开发的支持包。

5.java.util:是java提供的工具程序包。(集合类等) 非常重要

6.java.io:I/O编程开发包。

2.继承

意义:可以对代码进行重用,大大的减少了代码量

2.1背景

代码中创建的类, 主要是为了抽象现实中的一些事物(包含属性和方法).

有的时候客观事物之间就存在一些关联关系, 那么在表示成类和对象的时候也会存在一定的关联.

例如, 设计一个类表示动物

注意, 我们可以给每个类创建一个单独的 java 文件. 类名必须和 .java 文件名匹配(大小写敏感).

// Animal.java 
        public class Animal {
            public String name;
            public Animal(String name) {
                this.name = name;
            }
            public void eat(String food) {
                System.out.println(this.name + "正在吃" + food);
            }
        }
// Cat.java 
        class Cat {
            public String name;
            public Cat(String name) {
                this.name = name;
            }
            public void eat(String food) {
                System.out.println(this.name + "正在吃" + food);
            }
        }
// Bird.java 
        class Bird {
            public String name;
            public Bird(String name) {
                this.name = name;
            }
            public void eat(String food) {
                System.out.println(this.name + "正在吃" + food);
            }
            public void fly() {
                System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
            }
}

这个代码我们发现其中存在了大量的冗余代码.

仔细分析, 我们发现Animal和 Cat以及 Bird 这几个类中存在一定的关联关系:

  • 这三个类都具备一个相同的 eat 方法, 而且行为是完全一样的.
  • 这三个类都具备一个相同的 name 属性, 而且意义是完全一样的.
  • 从逻辑上讲, Cat 和 Bird 都是一种 Animal (is - a 语义).

此时我们就可以让 Cat 和 Bird 分别继承 Animal 类, 来达到代码重用的效果.

此时, Animal 这样被继承的类, 我们称为 父类 , 基类 或 超类, 对于像 Cat 和 Bird 这样的类, 我们称为 子类, 派生类和现实中的儿子继承父亲的财产类似, 子类也会继承父类的字段和方法, 以达到代码重用的效果.

2.2语法规则

基本语法

class 子类 extends 父类 {
}

使用 extends 指定父类.

Java 中一个子类只能继承一个父类 (而C++/Python等语言支持多继承).

子类会继承父类的所有 public 的字段和方法.

对于父类的 private 的字段和方法, 子类中是无法访问的.

子类的实例中, 也包含着父类的实例. 可以使用 super 关键字得到父类实例的引用.

对于上面的代码, 可以使用继承进行改进. 此时我们让 Cat 和 Bird 继承自 Animal 类, 那么 Cat 在定义的时候就不必再写 name 字段和 eat 方法.

class Animal {
    public String name;
    public Animal(String name) {
        this.name = name;
    }
    public void eat(String food) {
        System.out.println(this.name + "正在吃" + food);
    }
}
class Cat extends Animal {
    public Cat(String name) {
        // 使用 super 调用父类的构造方法.
        super(name);
    }
}
class Bird extends Animal {
    public Bird(String name) {super(name);
    }
    public void fly() {
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
    }
}
public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat("小黑");
        cat.eat("猫粮");
        Bird bird = new Bird("圆圆");
        bird.fly();
    }
}

extends 英文原意指 “扩展”. 而我们所写的类的继承, 也可以理解成基于父类进行代码上的 “扩展”.

例如我们写的 Bird 类, 就是在 Animal 的基础上扩展出了 fly 方法.

果我们把 name 改成 private, 那么此时子类就不能访问了.

class Bird extends Animal {
    public Bird(String name) {
        super(name);
    }
    public void fly() {
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
    }
}
// 编译出错
//Error:(19, 32) java: name 在 Animal 中是 private 访问控制

父类构造的同时,也要帮助子类来进行构造。(用super来构造子类的方法)

子类构造前(报错):

子类构造后(不报错):

因此在父类使用构造方法时,也要帮助子类一起使用构造方法

当子类和父类都有自己的name使用父类时,我们会优先使用子类自己的name。

eg:子类name:hehe。父类name:没赋值(null)。

打印输出结果:null;

基本格式为:

public 类名(参数即类型,参数即类型) {
    super(参数,参数);
}

2.2.1super[不能出现在静态方法当中]作用总结 父类对象的引用

1、super();//调用父类的构造方法

2、super.func();

3、super.data;

注:super只能在当前类的构造方法中出现(出现在其他地方会报错),而且必须放在第一行。

2.3protected 关键字

刚才我们发现, 如果把字段设为 private, 子类不能访问. 但是设成 public, 又违背了我们 “封装” 的初衷.

两全其美的办法就是 protected 关键字.

  • 对于类的调用者来说, protected 修饰的字段和方法是不能访问的
  • 对于类的 子类 和 同一个包的其他类 来说, protected 修饰的字段和方法是可以访问的
// Animal.java
public class Animal {
    protected String name;
    public Animal(String name) { this.name = name;
    }
    public void eat(String food) {
        System.out.println(this.name + "正在吃" + food);
    }
}
// Bird.java 
public class Bird extends Animal {
    public Bird(String name) {
        super(name);
    }
    public void fly() {
        // 对于父类的 protected 字段, 子类可以正确访问
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
    }
}
// Test.java 和 Animal.java 不在同一个 包 之中了. 
public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal("小动物");
        System.out.println(animal.name); // 此时编译出错, 无法访问 name 
    }
}

小结: Java 中对于字段和方法共有四种访问权限

  • private: 类内部能访问, 类外部不能访问
  • 默认(也叫包访问权限): 类内部能访问, 同一个包中的类可以访问, 其他类不能访问.
  • protected: 类内部能访问, 子类和同一个包中的类可以访问, 其他类不能访问.
  • public : 类内部和类的调用者都能访问

什么时候下用哪一种呢?

我们希望类要尽量做到 “封装”, 即隐藏内部实现细节, 只暴露出 必要 的信息给类的调用者.

因此我们在使用的时候应该尽可能的使用 比较严格 的访问权限. 例如如果一个方法能用 private, 就尽量不要用public.

另外, 还有一种 简单粗暴 的做法: 将所有的字段设为 private, 将所有的方法设为 public. 不过这种方式属于是对访问权限的滥用, 还是更希望同学们能写代码的时候认真思考, 该类提供的字段方法到底给 “谁” 使用(是类内部自己用, 还是类的调用者使用, 还是子类使用).

2.4更复杂的继承关系

刚才我们的例子中, 只涉及到 Animal, Cat 和 Bird 三种类. 但是如果情况更复杂一些呢?

针对 Cat 这种情况, 我们可能还需要表示更多种类的猫~

这个时候使用继承方式来表示, 就会涉及到更复杂的体系.

// Animal.java 
public Animal { 
 ...
        }
// Cat.java 
        public Cat extends Animal { 
 ...
        }
// ChineseGardenCat.java 
        public ChineseGardenCat extends Cat { 
 ...
        }
// OrangeCat.java 
        public Orange extends ChineseGardenCat { 
 ...
        } 
......

如刚才这样的继承方式称为多层继承, 即子类还可以进一步的再派生出新的子类.

时刻牢记, 我们写的类是现实事物的抽象. 而我们真正在公司中所遇到的项目往往业务比较复杂, 可能会涉及到一系列复杂的概念, 都需要我们使用代码来表示, 所以我们真实项目中所写的类也会有很多. 类之间的关系也会更加复杂.

但是即使如此, 我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层次太多, 就需要考虑对代码进行重构了.

如果想从语法上进行限制继承, 就可以使用 final 关键字

2.5final 关键字

曾经我们学习过 final 关键字, 修饰一个变量或者字段的时候, 表示 常量 (不能修改).

final int a = 10;
a = 20; // 编译出错

final 关键字也能修饰类, 此时表示被修饰的类就不能被继承.

final public class Animal { 
     ...
}
public class Bird extends Animal { 
     ...
}
// 编译出错
//Error:(3, 27) java: 无法从最终com.bit.Animal进行继承

final 关键字的功能是 限制 类被继承

“限制” 这件事情意味着 “不灵活”. 在编程中, 灵活往往不见得是一件好事. 灵活可能意味着更容易出错.

是用 final 修饰的类被继承的时候, 就会编译报错, 此时就可以提示我们这样的继承是有悖这个类设计的初衷的.

我们平时是用的 String 字符串类, 就是用 final 修饰的, 不能被继承.

2.6组合

和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果.

例如表示一个学校:

public class Student { 
    ...
}
public class Teacher { 
    ...
}
public class School {
    public Student[] students;
    public Teacher[] teachers;
}

组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段.这是我们设计类的一种常用

可以理解成一只猫也 “是” 一种动物

⭐小提问⭐

下面我们为大家准备了一些问题为了使大家更好地理解我们的包和继承相关的知识,希望大家先自习思考然后再去搜寻答案,下一篇文章我们为大家一一解答这些小问题!!!😆

1.查import和package的区别(通过import导包)

答:

2.查两个相同的类名 怎么导入不报错?

答:

3.问一下两个是不是文件夹?

答:

4.重写和重载的区别?

答:

5.this 和 super 以及this. 和 super.的区别?

答:

至此我们面向对象编程的(上)便全部讲解完毕了,如果有疑惑一定一定要在评论区和作者积极探讨哦!🧐

感谢各位读者的阅读,本文章有任何错误都可以在评论区发表你们的意见,我会对文章进行改正的。如果本文章对你有帮助请动一动你们敏捷的小手点一点赞,你的每一次鼓励都是作者创作的动力哦!😘

目录
相关文章
|
4月前
|
Java 开发者
在Java面向对象编程的广阔海洋中,多态犹如一股深邃的潜流,它推动着代码从单一走向多元,从僵化迈向灵活。
在Java面向对象编程的广阔海洋中,多态犹如一股深邃的潜流,它推动着代码从单一走向多元,从僵化迈向灵活。
44 7
|
4月前
|
Java 开发者
那些年,我们一同踏入Java编程的大门,多态,这个充满魔法的名字,曾无数次点亮我们探索面向对象编程的热情。
那些年,我们一同踏入Java编程的大门,多态,这个充满魔法的名字,曾无数次点亮我们探索面向对象编程的热情。
51 5
|
4月前
|
Java 程序员
Java中的继承和多态:理解面向对象编程的核心概念
【8月更文挑战第22天】在Java的世界中,继承和多态不仅仅是编程技巧,它们是构建可维护、可扩展软件架构的基石。通过本文,我们将深入探讨这两个概念,并揭示它们如何共同作用于面向对象编程(OOP)的实践之中。你将了解继承如何简化代码重用,以及多态如何为程序提供灵活性和扩展性。让我们启程,探索Java语言中这些强大特性的秘密。
|
29天前
|
Java 开发者
Java 面向对象编程
总之,Java 的面向对象编程为开发者提供了一种有效的编程范式,帮助他们构建出高质量、可维护的软件系统。理解和掌握面向对象的概念和原则是成为优秀 Java 开发者的重要基础。
46 3
|
6月前
|
Java
Java面向对象编程新篇章:多态,你准备好了吗?
【6月更文挑战第17天】Java的多态性是面向对象编程的核心,它允许通过统一的接口处理不同类型的对象。例如,在一个虚拟宠物游戏中,抽象类`Pet`定义了`speak()`方法,猫、狗和鹦鹉等子类各自重写此方法以实现独特叫声。在`main`方法中,使用`Pet`类型的引用创建子类对象并调用`speak()`,多态机制确保调用实际对象的方法,实现代码的灵活性和可扩展性。通过多态,我们能以更低的耦合度和更高的复用性编写更优雅的代码。
43 3
|
6月前
|
Java
Java 面向对象编程:父类与子类的“传承”与“创新”之路
【6月更文挑战第16天】Java 中的父类与子类展示了面向对象的“传承”与“创新”。子类`Dog`继承`Animal`,获取其属性和方法如`name`和`makeSound`。子类通过`@Override`增强`makeSound`,显示多态性。设计父类时应考虑普遍性,子类创新专注自身特性,遵循继承最佳实践,利用复用提升效率,构建可维护的软件系统。
160 57
|
4月前
|
存储 前端开发 JavaScript
【前端学java】面向对象编程基础-类的使用(4)
【8月更文挑战第9天】面向对象编程基础-类的使用
28 0
【前端学java】面向对象编程基础-类的使用(4)
|
4月前
|
Java 程序员 开发者
Java的面向对象编程:从基础到深入
【8月更文挑战第21天】在本文中,我们将探讨Java的面向对象编程(OOP)的核心概念,包括类、对象、继承、多态和封装。我们将通过实例和比喻,以通俗易懂的方式,深入理解这些概念的内涵和意义,以及它们如何影响我们的编程思维和实践。无论你是初学者还是有经验的开发者,这篇文章都将帮助你更深入地理解Java的OOP,并启发你思考如何在你的项目中应用这些概念。
|
6月前
|
Java 安全 索引
滚雪球学Java(48):面向对象编程中的StringBuffer类详解
【6月更文挑战第2天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
69 5
滚雪球学Java(48):面向对象编程中的StringBuffer类详解
|
5月前
|
Java API 项目管理
Java中的函数式编程与传统面向对象编程对比
Java中的函数式编程与传统面向对象编程对比