类和对象(两万字超详解析)(三)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 类和对象(两万字超详解析)

6.3 封装扩展之包


6.3.1 包的概念


在面向对象体系中,提出了一个软件包的概念,即:为了更好的管理类,把多个类收集在一起成为一组,称为软件包。有点类似于目录。比如:为了更好的管理电脑中的歌曲,一种好的方式就是将相同属性的歌曲放在相同文件

下,也可以对某个文件夹下的音乐进行更详细的分类。

在Java中也引入了包,包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如:一个包中的类不想被其他包中的类使用。包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。


6.3.2 导入包中的类


Java 中已经提供了很多现成的类供我们使用. 例如Date类:可以使用 java.util.Date 导入 java.util 这个包中的 Date类.


public class Test {
  public static void main(String[] args) {
  java.util.Date date = new java.util.Date();  //这样写比较冗余,不建议
  // 得到一个毫秒级别的时间戳
  System.out.println(date.getTime());
  }
}


使用 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.*;     //不是把util包中所有的类都导进来,而是随用随取,用到哪个类就导哪个类进来
public class Test {     
  public static void main(String[] args) {
  Date date = new Date();
  // 得到一个毫秒级别的时间戳
  System.out.println(date.getTime());
  }
}


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

比如:


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());
  }
} // 编译出错


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


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 static导入包中静态的方法和字段。(不建议这样写,旁门左道)


import static java.lang.Math.*;  //导入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);
  }
}


注意事项: import 和 C++ 的 #include 差别很大. C++ 必须 #include 来引入其他文件内容, 但是 Java 不需要.

import 只是为了写代码的时候更方便. import 更类似于 C++ 的 namespace 和 using


6.3.3 自定义包


基本规则


  1. 在文件的最上方加上一个 package 语句指定该代码在哪个包中.
  2. 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.baidu.demo1 ).
  3. 包名要和代码路径相匹配. 例如创建 com.baidu.demo1 的包, 那么会存在一个对应的路径 com/baidu/demo1 来存储代码.
  4. 如果一个类没有 package 语句, 则该类被放到一个默认包中.


操作步骤


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


dcb20bf926ce478fba80ed1be6d515e5.png


  1. 在弹出的对话框中输入包名, 例如 com.baidu.demo1
  2. 在包中创建类, 右键包名 -> 新建 -> 类, 然后输入类名即可.


77853b89e26447f7913cc21a6eba349e.png


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


d80ac5abfcaa4272a543da816e5a9b46.png


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


95c4bdeb5f56480b9b4b94ce952d8020.png


6.3.4 包的访问权限控制举例


如下两段代码分别在两个包中:Computer类位于com.baidu.demo1包中,TestComputer位置com.baidu.demo2包中:


package com.baidu.demo1;
class Computer {
    private String cpu; // cpu
    private String memory; // 内存
    public String screen; // 屏幕
    String brand; // 品牌
    public Computer(String brand, String cpu, String memory, String screen) {
        this.brand = brand;
        this.cpu = cpu;
        this.memory = memory;
        this.screen = screen;
    }
    public void Boot() {
        System.out.println("开机~~~");
    }
    public void PowerOff() {
        System.out.println("关机~~~");
    }
    public void SurfInternet() {
        System.out.println("上网~~~");
    }
}


package com.baidu.demo2;
import com.baidu.demo1.Computer;
public class TestComputer {
    public static void main(String[] args) {
        Computer p = new Computer("HW", "i7", "8G", "13*14");
        System.out.println(p.screen);
// System.out.println(p.cpu); // 报错:cpu是私有的,不允许被其他类访问
// System.out.println(p.brand); // 报错:brand是default,不允许被其他包中的类访问
    }
}


6.3.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编程开发包。


7. static成员


7.1 再谈学生类


使用前文中介绍的学生类实例化三个对象s1、s2、s3,每个对象都有自己特有的名字、性别,年龄,学分绩点等成员信息,这些信息就是对不同学生来进行描述的,如下所示:


public class Student{
  public String name;
    public String gender;
    public int age;
    public double score;
    public Student(String name,String gender,int age,double score) {
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.score = score;
    }
  public static void main(String[] args) {
  Student s1 = new Student("Li leilei", "男", 18, 3.8);
  Student s2 = new Student("Han MeiMei", "女", 19, 4.0);
  Student s3 = new Student("Jim", "男", 18, 2.6);
  }
}


f907c099bf4046b0995b68e14439fff0.png

假设三个同学是同一个班的,那么他们上课肯定是在同一个教室,那既然在同一个教室,那能否给类中再加一个成员变量,来保存同学上课时的教室呢?答案是不行的。

之前在Student类中定义的成员变量,每个对象中都会包含一份(称之为实例变量),因为需要使用这些信息来描述具体的学生。而现在要表示学生上课的教室,这个教室的属性并不需要每个学生对象中都存储一份,而是需要让所

有的学生来共享。此时我们可以定义一个静态成员。


在Java中,被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,是所有对象所共享的。


7.2 static修饰成员变量


static修饰的成员变量,称为静态成员变量,静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的。


【静态成员变量特性】


  1. 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
  2. 既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问
  3. 类变量存储在方法区当中
  4. 生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁)
public class Student {
    public String name;
    public String gender;
    public int age;
    public double score;
    public static String classRoom = "Bit306";
    public Student(String name,String gender,int age,double score) {
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.score = score;
    }
    public static void main(String[] args) {
// 静态成员变量可以直接通过类名访问
        System.out.println(Student.classRoom);  //通过类名直接访问
        Student s1 = new Student("Li leilei", "男", 18, 3.8);
        Student s2 = new Student("Han MeiMei", "女", 19, 4.0);
        Student s3 = new Student("Jim", "男", 18, 2.6);
// 也可以通过对象访问:但是classRoom是三个对象共享的
        System.out.println(s1.classRoom);
        System.out.println(s2.classRoom);
        System.out.println(s3.classRoom);
    }
}

1781403518234f0bb08ec5224d326eda.png


相关文章
|
26天前
|
存储 Java API
详细解析HashMap、TreeMap、LinkedHashMap等实现类,帮助您更好地理解和应用Java Map。
【10月更文挑战第19天】深入剖析Java Map:不仅是高效存储键值对的数据结构,更是展现设计艺术的典范。本文从基本概念、设计艺术和使用技巧三个方面,详细解析HashMap、TreeMap、LinkedHashMap等实现类,帮助您更好地理解和应用Java Map。
41 3
|
1月前
|
存储 编译器 C语言
C++类与对象深度解析(一):从抽象到实践的全面入门指南
C++类与对象深度解析(一):从抽象到实践的全面入门指南
48 8
|
1月前
|
存储 编译器 数据安全/隐私保护
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解2
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
30 3
|
1月前
|
编译器 C++
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解1
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
45 3
|
1月前
|
Python
深入解析 Python 中的对象创建与初始化:__new__ 与 __init__ 方法
深入解析 Python 中的对象创建与初始化:__new__ 与 __init__ 方法
19 1
|
1月前
|
程序员 开发者 Python
深度解析Python中的元编程:从装饰器到自定义类创建工具
【10月更文挑战第5天】在现代软件开发中,元编程是一种高级技术,它允许程序员编写能够生成或修改其他程序的代码。这使得开发者可以更灵活地控制和扩展他们的应用逻辑。Python作为一种动态类型语言,提供了丰富的元编程特性,如装饰器、元类以及动态函数和类的创建等。本文将深入探讨这些特性,并通过具体的代码示例来展示如何有效地利用它们。
37 0
|
2月前
|
设计模式 存储 人工智能
深度解析Unity游戏开发:从零构建可扩展与可维护的游戏架构,让你的游戏项目在模块化设计、脚本对象运用及状态模式处理中焕发新生,实现高效迭代与团队协作的完美平衡之路
【9月更文挑战第1天】游戏开发中的架构设计是项目成功的关键。良好的架构能提升开发效率并确保项目的长期可维护性和可扩展性。在使用Unity引擎时,合理的架构尤为重要。本文探讨了如何在Unity中实现可扩展且易维护的游戏架构,包括模块化设计、使用脚本对象管理数据、应用设计模式(如状态模式)及采用MVC/MVVM架构模式。通过这些方法,可以显著提高开发效率和游戏质量。例如,模块化设计将游戏拆分为独立模块。
180 3
|
2月前
|
JavaScript 前端开发 API
Javaweb之javascript的BOM对象的详细解析
BOM为Web开发提供了强大的API,允许开发者与浏览器进行深入的交互。合理使用BOM中的对象和方法,可以极大地增强Web应用的功能性和用户体验。需要注意的是,BOM的某些特征可能会在不同浏览器中表现不一致,因此在开发过程中需要进行仔细的测试和兼容性处理。通过掌握BOM,开发者能够制作出更丰富、更动态、更交互性的JavaWeb应用。
31 1
|
3月前
|
缓存 Java 开发者
Spring高手之路22——AOP切面类的封装与解析
本篇文章深入解析了Spring AOP的工作机制,包括Advisor和TargetSource的构建与作用。通过详尽的源码分析和实际案例,帮助开发者全面理解AOP的核心技术,提升在实际项目中的应用能力。
45 0
Spring高手之路22——AOP切面类的封装与解析
|
3月前
|
JSON 图形学 数据格式
Json☀️ 一、认识Json是如何解析成类的
Json☀️ 一、认识Json是如何解析成类的

推荐镜像

更多