JAVA封装详细讲解 打牢基础

本文目标

1.掌握封装特性
2.掌握代码块
3.掌握内部类

目录

1封装


1.1封装的概念


面向对象程序三大特性: 封装、继承、多态。而类和对象阶段,主要研究的就是封装特性。何为封装呢?简单来说就是套壳屏蔽细节。

比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器,USB插孔等,让用
户来和计算机进行交互,完成日常事务。但实际上:电脑真正工作的却是CPU、显卡、内存等一些硬件元件。

对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的,CPU内部是如何设计的等,用户只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

2访问

Java中主要通过类和访问权限来实现封装: 类可以将数据以及封装数据的方法结合在一起,更符合人类对事物的认知,而访问权限用来控制方法或者字段能否直接在类外使用。Java中提供了四种访问限定符

NO.范围privatedefaultprotectedpublic
1同一包中的同一类
2同一包中的不同类
3不同包中的子类
4不同包中的非子类

 比如:
public: 可以理解为不设防,谁都可以访问
default: 对于自己家族中(同一个包中)不是什么秘密,对于其他人来说就是隐私了
private: 表示私密,只有自己知道
【说明】
· protected主要是用在继承中,继承部分详细介绍
. default权限指: 什么都不写时的默认权限
.访问权限除了可以限定类中成员的可见性,也可以控制类的可见性

注意:一般情况下成员变量设置为private,成员方法设置为public

3封装扩展----包


3.1 包的概念


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

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


3.2导入包中的类


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

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

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

 

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

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

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

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


3.3自定义包


基本规则

1.在文件的最上方加上一个 package语句指定该代码在哪个包中

2.包名需要尽量指定成唯一的名字通常会用公司的域名的颠倒形式(例如com.qq.demo1 ).

 3.包名要和代码路径相匹配.例如创建 com.qqdemo1 的包,那么会存在一个对应的路径com/qq/demo1 来存储代码.
4.如果一个类没有 package 语句,则该类被放到一个默认包中
操作步骤
1.在IDEA中先新建一个包: 右键 src -> 新建->包

英文

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

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

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

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

 

3.4 包的访问权限控制举例

 

Computer1类位于com.qq.demo1包中,Computer2位置com.qq.demo2包中

3.5 常见的包


1.java.lang:系统常用基础类(String、
Object),此包从DK1.1后自动导入
2.java.lang.reflect:java 反射编程包
3.java.net:进行网络编程开发包。
4.java.sql;进行数据库开发的支持包。
5.java.util:是java提供的工具程序包。(集合类等)非常重要
6.java.io:l/O编程开发包。

 

4.static成员 

4.1static修饰成员变量

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

[静态成员变量特性]

1.不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
2.既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问
3类变量存储在方法区当中
4.生命周期伴随类的一生(即: 随类的加载而创建,随类的卸载而销毁)

我们以调试方式运行上述代码,然后在监视窗口中可以看到,静态成员变量并没有存储到某个具体的对象中 

 

4.2static修饰成员方法

 

一般类中的数据成员都设置为private,而成员方法设置为public,那设置之后,Student类中classRoom属性如何在类外访问呢?

答:Java中,被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员一般是通过静态方法来访问

[静态方法特性]
1.不属于某个具体的对象,是类方法
2.可以通过对象调用,也可以通过类名静态方法名(...)方式调用,更推荐使用后者
3.不能在静态方法中访问任何非静态成员变量

 

4.静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用

 

5.静态方法无法重写,不能用来实现多态(此处大家暂时不用管,后序多态位置详细讲解)。
 

4.3 static成员变量初始化


注意:静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性
静态成员变量的初始化分为两种:就地初始化 和 静态代码块初始化
1.就地始化
就地初始化指的是:在定义时直接给出初始值

2.静态代码块初始化
那什么是代码块呢?继续往后看:)~~       我们一起加油

 

5.代码块

5.1 代码块概念以及分类


又可分为以下四种:
使用{}定义的一段代码称为代码块。根据代码块定义的位置以及关键字,又可分为以下几种
*普通代码块
*构造块
*静态块
*同步代码块(后续讲解多线程部分再谈)

5.2普通代码块

普通代码块:定义在方法中的代码块

5.3构造块

构造块:定义在类中的代码块(不加修饰符)。也叫: 实例代码块。构造代码块一般用于初始化实例成员变量.

 
5.4静态代码块


使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量

 注意事项
1.静态代码块不管生成多少个对象,其只会执行一次。
2.静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的。
3.如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并)。
4.实例代码块只有在创建对象时才会执行。

6内部类


当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么这个内部的完整结构最好使用内部类。在Java 中,可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类。内部类也是封装的一种体现。

 

【注意事项】
1.定义在class类名花括号外部的,即使是在一个文件里,都不能称为内部类 

2.内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件

 

 6.1内部类的分类


先来看下,内部类都可以在一个类的那些位置进行定义

 

根据内部类定义的位置不同,一般可以分为以下几种形式:
1.成员内部类(普通内部类:未被static修饰的成员内部类和静态内部类:被static修饰的成员内部类)
2.局部内部类(不写修饰符)、匿名内部类


注意:内部类其实日常开发中使用并不是非常多,大家在看一些库中的代码时候可能会遇到的比较多,日常开始中使用最多的是匿名内部类。

6.1.1实例内部类


即未被static修饰的成员内部类。

public class OutClass {
    private int a;
    private int b;
    int c ;
    public void methodA(){
        a=10;
        System.out.println(a);
    }
    public void methodB(){
        System.out.println(b);
    }



    // 实例内部类未被 static修饰
   class InnerClass {
        int c;
        int d=10;
        public void methodInner() {
            // 在实例内部类中可以直接访问外部类中: 任意访问限定符修饰的成员
            a = 100;
            b = 200;
            methodA();
            methodB();

            // 如果外部类和实例内部类中具有相同名称成员时,优先访问的是内部类自己的
            c = 300;
            System.out.println(c);

            // 如果要访问外部类同名成员时候,必须,外部类名称this.同名成员名字
            OutClass.this.c = 400;
            System.out.println(OutClass.this.c);

        }
    }

    public static void main(String[] args) {
        // 外部类: 对象创建 以及 成员访问
        OutClass outClass = new OutClass();
        System.out.println(outClass.a);
        System.out.println(outClass.b);
        System.out.println(outClass.c);
        outClass.methodA();
        outClass.methodB();
        System.out.println("========实例内部类的访问============");
            // 要访问实例内部类中成员,必须要创建实例内部类的对象
            // 而普通内部类定义与外部类成员定义位置相同,因此创建实例内部类对象时必须借助外部类
            // 创建实例内部类对象
        OutClass.InnerClass innerClass1 = new OutClass().new InnerClass();
            // 上述语法比较怪异,也可以先将外部类对象先创建出来,然后再创建实例内部类对象
        OutClass.InnerClass innerClass2 = outClass.new InnerClass();
        innerClass2.methodInner();
        System.out.println(innerClass2.d);;
    }

    }

[注意事项]
1.外部类中的任何成员都可以在实例内部类方法中直接访问
2.实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束
3.在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名称this.同名成员来访问
4.实例内部类对象必须在先有外部类对象前提下才能创建
5实例内部类的非静态方法中包含了一个指向外部类对象的引用
6.外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。 

 

 6.1.2静态内部类


被static修饰的内部成员类称为静态内部类 

[注意事项]
1.在静态内部类中只能访问外部类中的静态成员
如果确实想访问,我们该如何做?
2.创建静态内部类对象时,不需要先创建外部类对象

  

6.2局部内部类


定义在外部类的方法体或者0中,该种内部类只能在其定义的位置使用,一般使用的非常少,此处简单了解下语法格式。

[注意事项]
1.局部内部类只能在所定义的方法体内部使用
2.不能被public、static等修饰符修饰
3.编译器也有自己独立的字节码文件
命名格式:外部类名字$数字内部类名字.class
4.几乎不会使用

6.3名内部类


后序讲抽象类和接口时给大家详细介绍。

7.对象的打印
package com.qq.demo1;//创建的Java包

public class Computer1 {
    private String cpu;  //cpu
    private String memory;  //内存
    public String screen;  //屏幕
    String brand; //品牌——默认default属性
    public Computer1(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 Surfs(){
        System.out.println("上网");
    }

    public static void main(String[] args) {
        Computer1 p=new Computer1("HW","I8","16G","13*14");
        System.out.println(p);//输出com.qq.demo1.Computer1@4eec7777
    }

}

如果想要默认打印对象中的属性该如何处理呢?答案:重写toString方法即可

package com.qq.demo1;

public class Computer1 {
    private String cpu;  //cpu
    private String memory;  //内存
    public String screen;  //屏幕
    String brand; //品牌——默认default属性
    public Computer1(String brand,String cpu,String memory,String screen){
        this.brand=brand;
        this.cpu=cpu;
        this.memory=memory;
        this.screen=screen;
    }

    @Override
    public String toString() {
        return "Computer1{" +
                "cpu='" + cpu + '\'' +
                ", memory='" + memory + '\'' +
                ", screen='" + screen + '\'' +
                ", brand='" + brand + '\'' +
                '}';
    }

    public void Boot(){
        System.out.println("开机");
    }
    public void PowerOff(){
        System.out.println("关机");
    }

    public void Surfs(){
        System.out.println("上网");
    }

    public static void main(String[] args) {
        Computer1 p=new Computer1("HW","I8","16G","13*14");
        System.out.println(p);//输出Computer1{cpu='I8', memory='16G', screen='13*14', brand='HW'}
    }

}

  • 19
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值