篮球哥温馨提示:编程的同时不要忘记锻炼哦!

因为热爱,所以编程


目录

1、封装

1.1 什么是封装?

2.2 访问权限

2.3 private 简单使用

2、封装之包的概念

2.1 什么是包?

2.2 如何导入包中的类?

2.2.1 使用完整类名

2.2.2 使用 import 导入包

2.2.3 使用* 发现冲突的情况

2.2.4 使用 import static 导入静态的方法和字段

2.3 自定义包

3、static修饰符

3.1 为什么需要 static 修饰成员?

3.2 static 修饰成员变量

3.3 static 修饰静态成员方法

3.4 static 成员变量初始化

4、代码块

4.1 代码块的分类及概念

4.2 构造代码块和静态代码块

5、内部类

5.1 内部类的概念和分类

5.2 实例内部类

5.3 静态内部类

5.4 局部内部类


1、封装

1.1 什么是封装?

不知道小伙伴对冰箱有没有观察过,市面上大多数的冰箱他们的嵌入式主板,芯片,制冷装置,以及内部电线,应该都没有暴露在我们的视野中,但是他们给我们提供了一些对外可见的接口,比如,插电头,你插上就有电了, 再比如给我们提供了冰箱门上的按钮,你需要操作这几个按钮或者显示屏就能让冰箱帮你干活,那他的地层一些制冷的装置,以及一些功能的机制实现我们都不了解,也从表面上看不到,但是我们却可以通过他们提供的接口去使用,简而言之这就是封装!

如果把封装的概念放在语言中,那就是:将数据和操作数据的方法进行结合,隐藏对象的属性,和实现细节,仅仅对外公开接口来和对象进行交互。

2.2 访问权限

记得之前,写方法写任何东西,我都是写的 public 为什么呢?也浅提了一个,这个是访问权限限定符,既然是封装,就需要限制外部对类或类的属性设置访问权限,在Java中,主要是通过类和访问权限来实现封装, 类可以将数据及实现数据的方法结合在一起,而访问权限用来控制方法或字段能否直接在类外使用,在Java中,一共提供了四种访问限定符:

private:只允许在同一个包中和同一个类中访问,其他地方均不能访问

默认:只允许在同一个包中任意位置访问,不同的包,其他地方均不能访问(什么都不写就是默认)

portected: 主要用在继承当中,我们下期讲解

public:任意地方都能访问

注意:修饰符除了限定类中的成员,也能限制类的可见性,本期没有讲到的范围,后续会讲到

2.3 private 简单使用

class Student {//成员变量【属性】private String name; //姓名private int age; //年龄private float score; //分数//构造方法public Student() {}public Student(String name, int age, float score) {this.name = name;this.age = age;this.score = score;}//成员方法【行为】public void studentScores() {System.out.println(this.name + "考了" + this.score + "分");}
}
public class Test {public static void main(String[] args) {Student student = new Student("张三", 20, 59.9f);//这里我将成员变量的访问限定符设置为了 private 代表只能在同一个类中访问//student.name = "张三" //error -> 不同类中不能访问//student.age = 20; //error -> 不同类中不能访问//System.out.println(student.name); //error -> 不同类中不能访问student.studentScores(); //yes -> 因为这个类成员方法访问限定符是 public}
}

这里我们可以简单来看一下 Student 这个类(同一份Java文件,只能有一个被public修饰的类),首先我们把成员变量都设置成的 private 属性,也就代表着,这些成员变量只能在 Student 这个类的内部访问,所以我们下边 Test 类就不能直接通过对象访问他们了,但是可以通过对象访问 studentScores 成员方法,因为他是被 public 修饰的!一般我们会将成员变量设置为 private,成员方法设置成 public。

后面我们在讲完包之后,会介绍默认修饰符,也就是什么都不加的情况。


2、封装之包的概念

2.1 什么是包?

女孩子们喜欢买各种包包,主要是背着好看,但是计算机中包可不是这样的,我们可以把文件夹当成一个包,文件夹是用来干嘛的?主要是为了更方便的管理,所以面向对象的体系中,提出了一个软件包的概念,也就是为了更好的管理类,把多个类收集到一起成为一组,成为软件包。

在Java中,也引入了包,包是对类,结构等封装机制的体现,可以更好组织类和接口等,如果一个包中的类,不想被其他包使用,就修改包中类的权限限定符,同时如果你有相同的类名,你只需要让他们俩处在不同的包里即可!

2.2 如何导入包中的类?

记得之前我们了解过输入方法,当我们创建了一个输入对象,编译器则会在最顶部给我们添加一行 import java.util.Scanner; 那如果我们没有这个 import 语句我们要如何用 Scanner 类中的方法呢?

2.2.1 使用完整类名

这里我们用一个我们之前没见过的类,我现在要获取一个时间戳,已知 java.util 包中里面 Date类里面有一个 getTime(); 方法可以获取时间戳,假设我们现在不知道 import 语句,也没有添加 import 语句,该如何做到获取时间戳呢?

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

我们是不是应该这么写,首先我们需要用 Date 类来实例化一个对象,而这个类在 java.util 这个包中,所以我们要通过这个包找到这个类,进行实例化,实例化哪个类呢?还是要通过这个包,里面的类来实例化,最后通过对象来访问类中对应的成员方法进行获取时间戳,并打印!

2.2.2 使用 import 导入包

这样写是不是好麻烦,有那么多重复的地方,所以这里就可以使用 import 语句来导入包,所以当我们需要使用 java.util.Date 类里面方法的时候,我们只需要在类的前面 imprt java.util.Date,导入了这个包即可:

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

那如果你还要使用 java.util 里面的其他类呢?其实有一个方法可以不需要一个个导入,直接写成: import java.util.* 只要是 util 里面的公开的类你都可以像上面一样使用,但是我们更推荐显示式的指定要导入的类名,否则容易出现冲突的情况:

2.2.3 使用* 发现冲突的情况

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

如上代码会报错,也就是出现冲突,因为 java.sql 和 java.util 这两个包中都有 Date 类,编译器也无法识别你需要使用哪个类,所以在这种情况下,我们就需要使用完整的类名:

java.util.Date date = new java.util.Date();

2.2.4 使用 import static 导入静态的方法和字段

至于静态的方法和字段这个我们后面会讲解,这里主要先看下怎么使用,等学了后面内容你就明白了:

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);}
}

这样就可以直接使用方法名了,不需要加类名,但这里必须是静态的方法或者成员才可以,后面会讲到,我们这样用的情况不是很多。

注意: import 跟 C/C++ 的 include 是不一样的,他们差别很大,#include在编译会展开头文件,是来引用其他文件内容,而Java不需要,import只是为了写代码更方便,更类似于C++ 的 namespace 和 using

2.3 自定义包

自定义包也就是我们用户自己建一个包,在IEDA下可以通过右键 src->New->Package 文件的最上方需要加上 package 包名; 来指定该代码在哪个保重,但IDEA编译器会自动帮我们加上,如果你创建的包名叫做 com.lqg.demo,那么则会存在一个对应的路径 com/lqg/demo 来存储代码,要是类中没有 package语句,则表明该类被放在一个默认包中,IDEA对应是 src

有了上面的一些包的学习,相信你们以及能理解 默认 访问限定符的作用了,下来你可以自己建一个包,然后写一个类,类的修饰符是默认,再去另一个包中就会发现无法使用这个类了,这里就教给大家下去自行学习。

这里介绍以下 java.util 包,他是java提供的工具程序包,(集合类等),在后续的学习中我们会接触到更多,还有其他的包,随着我们学习的深入慢慢了解。


3、static修饰符

3.1 为什么需要 static 修饰成员?

这里我们来回顾下之前写过的 Student 类,假设我们有三个学生,对应着三个对象,假设这三个学生为张三,李四,王五, 而他们又是同班同学,那我现在需要给类中加一个教室信息,是直接添加一个教室成员变量吗?在之前的类中,每个对象都会包含一份成员变量,称之为实例变量,但是这次我们要添加的教室属性,并不属于某个对象啊,他是属于所有学生对象共享的!所以在Java中,static 的出现,就是说,被 static 修饰的成员,称之为静态成员,也可也成为类成员,不属于某个具体的对象,所有对象都能共享!

3.2 static 修饰成员变量

这里我们就来给学生类添加一个 static 成员变量,也就是静态成员变量 -> classRoom;

public class Student {//这里表示 name age 成员变量只能在 Student 类中访问private String name; private int age;public static String classRoom = "八年级二班"; //静态成员变量public static void main(String[] args) {Student stu1 = new Student();Student stu2 = new Student();//静态的不依赖于对象!System.out.println(Student.classRoom); //可以直接通过类名访问System.out.println(stu1.classRoom); //也可也通过对象访问,但不推荐System.out.println(stu2.classRoom); //也可也通过对象访问,但不推荐}
}

注意:

static 修饰的成员变量,不属于某个具体的对象,不存储在某个具体对象的空间中,静态成员变量存储在方法区中,生命周期伴随类的一生,即随类的加载而创建,类的销毁而销毁,他既可以通过类名访问,也可也通过对象访问,但更推荐类名访问方式!

3.3 static 修饰静态成员方法

上面看完 static 修饰成员变量,但是我们之前都是建议成员变量用 private 来修饰啊,那这样的话如何在类外访问我们静态成员变量呢?

有了上面的问题,所以Java中可以用 static 修饰成员方法,如果被 static 修饰的成员方法,称之为静态成员方法,也可成为类方法,不属于任何一个对象,所以类方法没有隐藏的 this 参数!

这里我们就把上面的 Student 类里面的类变量改为 private 修饰,增加一个获取教室的类方法:

public class Student {//这里表示 name age 成员变量只能在 Student 类中访问private String name; private int age;public static String classRoom = "八年级二班"; //静态成员变量public static String getClassRom() {return Student.classRom; //类变量,可以通过类名访问,当然在类方法中,也可也省略}
}class TestStudent {public static void main(String[] args) {Student stu = new Student();System.out.println(Student.getClassRoom()); //可以通过类名访问类方法System.out.println(stu.getClassRoom()); //也可也通过对象访问类方法,但不推荐}
}

注意:

static 修饰的成员方法,可以称为类方法,不属于某个具体的对象,在静态成员内部,不能直接访问任何非静态成员变量和方法,前面也说过原因,如果你非要访问,自己用类实例化一个对象吧,但很少这样做,静态方法不支持重写,不能用来实现多态,这个我们后续多态部分时候讲

3.4 static 成员变量初始化

一般来说,我们静态成员变量不会在构造方法中初始化,而一般有两种初始化的方式,就地初始化和静态代码块初始化:就地初始化就是在定义的时候直接给出初始值,至于静态代码块初始化,我们往后看代码块的相关知识:


4、代码块

4.1 代码块的分类及概念

代码块就是用 { } 定义的一段代码叫做代码块,根据代码块定义的位置以及关键字,可以分为四种:

  • 普通代码块 -> 这里我们不多强调,就是定义在方法中的代码块,很少用
  • 构造代码块
  • 静态代码块
  • 同步代码块(多线程的时候讲解)

4.2 构造代码块和静态代码块

构造代码块,也有构造方法两个字,那他跟构造方法是有一定区别的,构造代码块是定义在类中的代码块(不加修饰符) ,也可称为实例代码块,主要是用于初始化实例成员变量,也就是非静态成员变量。

静态代码块,主要是用来初始化静态成员变量的代码块,我们来看具体演示代码:

public class Student {private String name;private int age;private static String classRoom;{//这里是构造代码块,也叫实例代码块,一般用于初始化实例成员变量this.name = "王五";System.out.println("构造代码块执行!");}static {//这里是静态代码块,一般用于初始化静态成员变量Student.classRoom = "八年级二班";System.out.println("静态代码块执行!");}
}
class TestStudent {public static void main(String[] args) {Student stu1 = new Student();Student stu2 = new Student();}
}

我们 new 了两个对象,而静态代码块是定义在构造代码块后面的,我们再来看结果执行main方法的结果:

为什么会是这个结果?为什么静态代码块后定义,但是先执行?为什么构造代码块执行了两次?这里我们一一来解释:

  • 实例代码块每次创建对象都会执行一次,静态代码块不管生成多少个对象只执行一次。
  • 静态成员是类的属性,因此是在JVM加载类时开辟空间的,所以静态代码块要比实例代码块先执行
  • 如果一个类包含多个静态代码块,则按照定义的顺序,也就是从上往下执行(合并)

5、内部类

5.1 内部类的概念和分类

什么是内部类?将一个类定义在另一个类或者一个方法的内部,称为内部类,内部类外面的类可以称为外部类,内部类也是封装的一种体现!

内部类必须定义在外部类的 { } 内部,内部类和外部类是共用一个Java源文件,但是编译之后,内部类会形成单独的字节码文件,这个大家可以在编译之后自行查看。

内部类分为两大类:成员内部类(定义位置跟成员所处位置相同),局部内部类(定义在方法体或者 {} 中)

成员内部类包含:实例内部类,静态内部类

局部内部类包含:局部内部类,匿名内部类(抽象类和接口部分讲)

5.2 实例内部类

public class Student {private String name;private int age;private static String classRoom;class InnerClass {//实例内部类,可以直接访问外部类中:任意访问限定修饰符的成员int age = Student.this.age; //如果访问外部类同名的成员,需要使用类名.this.成员名String room = Student.classRoom;//实例内部类中,不能定义有static修饰的成员,如果非要定义,则需要使用 final 修饰的常量//常量是在程序编译的时候确定的,一旦初始化,就不能改变private static final int a = 10;public void func() {//实例内部类的非静态方法中,包含了一个指向外部类对象的引用,所以可以使用this.访问this.age = 10;}}
}

实例内部类就是指没有被 static 修饰的内部类,那么如何实例化内部类呢?

public static void main(String[] args) {//方法1Student stu1 = new Student();Student.InnerClass stu2 = stu1.new InnerClass();//方法2Student.InnerClass stu3 = new Student().new InnerClass();}

方法1,既然是实例内部类它的定义位置是跟外部类的成员位置相同,我们可以先有一个外部类的对象,所以也就可以借助外部类的对象来实例化内部类。

方法2,我们可以直接先实例化外部类,在紧接着通过实例化的外部类再去实例化内部类,这样也是可以的!

总结:

  • 外部类的任何成员都可以在实例内部类中直接访问
  • 实例内部类所以他所处的位置是于外部类成员位置相同的,因此也可以使用public private限定符来约束
  • 在实例方法中,访问相同的成员时,优先访问自己的,如果要访问外部类的,得使用 类名.this.同名成员 来访问
  • 实例内部类非静态方法中,包含了一个指向外部类的对象的引用
  • 实例内部类不能有static修饰的成员,如果非要,需要用 final 修饰(以后讲解)
  • 如果外部类要访问内部类的成员,必须要先有内部类的对象

5.3 静态内部类

public class Student {private String name;private int age;private static String classRoom;public static String getClassRoom() {return Student.classRoom;}static class StaticInnerClass {//静态类中,可以直接访问外部类的静态成员String room = Student.classRoom;public void func() {String room = Student.getClassRoom();}}
}

我们创建静态类对象呢?首先既然他是静态的那就说明他不依赖于对象,也就是说,不需要先创建外部对象那我们就可以直接使用外部类类名.内部静态类类名来实例化:

public static void main(String[] args) {Student.StaticInnerClass sInClass = new Student.StaticInnerClass();}

关于静态类我们还要注意一点:静态类中不能直接访问外部类非静态成员,如果非要访问外部类非静态成员,我们需要先创建外部类对象,这个也交给小伙伴们下去尝试。

5.4 局部内部类

局部内部类也就是定义在外部类的方法体中或者 {} 中,这种内只能在定义的地方使用,一般使用非常的少,因为是局部的,他并不能被public,static等修饰符修饰,他也有自己独立字节码文件:外部类类名$数字内部类类名.class,这种几乎不使用,我们知道有就可以。

最后,内部类主要是出现在库中代码里面,实际开发用的不算很多,用的最多的是匿名内部类,但是这个我们放到抽象类和接口部分介绍。


 下期预告:【Java SE】继承的详解

【Java SE】封装的详解相关推荐

  1. Java SE MyBatis框架(详解)

    Java SE MyBatis框架 目录 Java SE MyBatis框架 通用框架 1.lib 2.src 2.1.mybatis.xml 2.2.DateBase.properties 2.3. ...

  2. Java SE基础知识详解第[12]期—集合(Set、Collections、Map、集合嵌套)

    写在前面: 每一个不曾起舞的日子,都是对生命的辜负. 希望看到这里的每一个人都能努力学习,不负韶华,成就更好的自己. 以下仅是个人学习过程中的一些想法与感悟,Java知识博大精深,作为初学者,个人能力 ...

  3. Java SE基础知识详解第[13]期—不可变集合、Stream流、异常

    写在前面: 每一个不曾起舞的日子,都是对生命的辜负. 希望看到这里的每一个人都能努力学习,不负韶华,成就更好的自己. 以下仅是个人学习过程中的一些想法与感悟,Java知识博大精深,作为初学者,个人能力 ...

  4. Java SE基础知识详解第[18]期—网络编程(通信)

    写在前面: 每一个不曾起舞的日子,都是对生命的辜负. 希望看到这里的每一个人都能努力学习,不负韶华,成就更好的自己. 以下仅是个人学习过程中的一些想法与感悟,Java知识博大精深,作为初学者,个人能力 ...

  5. java 继承 封装 多态 详解

    1.继承 1.1子类能够继承父类的哪些成员? 1.1.1 public 成员 1.1.2 protected 成员 1.1.3 同一个包中:缺省访问类型的成员 1.1.4 打死不能继承private成 ...

  6. java原生类型没有封装_Java基本数据类型与封装类型详解(int和Integer区别)

    Java基本数据类型与封装类型详解(int和Integer区别) 发布于 2020-4-19| 复制链接 摘记: int是java提供的8种原始数据类型之一.Java为每个原始类型提供了封装类,Int ...

  7. java 封装表单数据类型_Java基本数据类型与封装类型详解(int和Integer区别)

    int是java提供的8种原始数据类型之一. Java为每个原始类型提供了封装类,Integer是java为int提供的封装类(即Integer是一个java对象,而int只是一个基本数据类型).in ...

  8. MP实战系列(十一)之封装方法详解(续一)

    之前写的封装方法详解,比较简要. 今天我主要讲增加和删除及其修改.查的话得单独再详讲. 增删改查,无论是Java或者C#等等,凡是对数据库操作的都离不开这四个. 一.增加方法讲解 MyBatis Pl ...

  9. 你真的弄明白了吗?Java并发之AQS详解

    你真的弄明白了吗?Java并发之AQS详解 带着问题阅读 1.什么是AQS,它有什么作用,核心思想是什么 2.AQS中的独占锁和共享锁原理是什么,AQS提供的锁机制是公平锁还是非公平锁 3.AQS在J ...

  10. Java RMI远程方法调用详解

    Java RMI远程方法调用详解     [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/details/51992182 一.Java R ...

最新文章

  1. Linux的chattr与lsattr命令详解
  2. 2 模版_你还只会套PPT模版吗? | 大学生PPT进阶指南(附免费资源amp;教程)
  3. 面试:从volatile说到i++的线程安全问题
  4. java接收的文件转换成临时文件_Android中怎样使用createTempFile实现将字节数据创建到临时文件并转换成FileOutputStream和FileInputStream...
  5. AI换脸引发全民恐慌,用对方向却能推动行业变革
  6. Android开发之IPC进程间通信-AIDL介绍及实例解析
  7. 【第三期】那些设计漂亮、有创意的电路板!
  8. Android之XUtils的框架总结
  9. Web黑客工具箱之LiveHttpHeaders
  10. mysql 表连接 on_MysQL中表连接中“using”和“on”之间的区别是什么?
  11. python的标准库学习之__buitin__
  12. AD教程系列 | 5 - 绘制原理图
  13. jdbc连接timesten_Java 连接 timesten
  14. 解决Linux版Vivado下载bit流到FPGA Open target失败问题
  15. 浏览器缓存之http缓存和service worker
  16. 计时器(Chronometer)的使用
  17. 数据可视化_EChat
  18. 正点原子STM32F103学习笔记(六)——时钟系统
  19. 紧急求助!!!!VUE页面,V-SHOW的判断条件改变了但是页面没有实际变化
  20. android服务框架下载,GG服务框架安装器

热门文章

  1. 植物大战僵尸:寻找葵花生产速度
  2. mybatis plus 格式话_MyBatisPlus学习整理(二)
  3. TR069协议向导——一个帮助你了解TR069协议的简明教程(一)
  4. jar包是干什么用的
  5. 位置式Pid和增量式Pid的定义及应用
  6. vue-element-admin动态加载接口和报错解决
  7. Qt小项目之txt文本替换
  8. pdf 电子签章 java_在pdf上加盖电子签章
  9. 2016-HitCon-Pwn-house_of_orange学习(附赠FSOP基础知识)
  10. java代理(静态代理和jdk动态代理以及cglib代理)