Java----封装
前言:在面向对象的编程语言中,有三个特性:封装,继承,多态
(一).封装
1.概念
简单的来说,成员变量不能在类外直接使用,但是可以通过其他方法去用变量
比如,我们用的电脑,实际上电脑已经被封装好了的,电脑里面的CPU,显卡等,我们统统都是看不到的,我们只关心如何去使用电脑即可。 
那么在Java中,我们如何进行封装呢?
首先我们现在看一下什么是访问修饰限定符
2.访问修饰限定符

四者的区别:
public:谁都能使用
private:只有同一个包同一个类中才能使用
default:只要是同一个包中就可以使用
在Java中,我们通常会把类当中的成员设置为private,设想一下,如果我们类中设置了username和password两个成员变量,那么我们肯定是不希望别人能看到的,那么我们就可以讲username和password设置为private,这样,我们的username和password就只能在类当中去访问了,一旦出了类,我们就访问不了

通过图片可以看到,我先把username设置成了public,那么我们在类外是可以使用username的。
但是我将password设置成了private,我们可以看到,我们是拿不到password的
那么我现在就是想访问我的password,怎么办?
我们可以通过set和get方法,来访问我的password
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
通过提供set和get方法,我们就可以在类外访问我们的password成员变量了
class User{
public String username;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
public class Main {
public static void main(String[] args) {
User user=new User();
user.username="zhangsan";
user.setPassword("123");
System.out.println(user.getPassword());
}
}

通过打印,我们可以看到,我们成功访问到了我们的password属性
当然,我们可以通过编辑器来快速导入我们的set和get方法
首先右击鼠标
通过图片上的内容,我们就可以通过编辑器,快速生成我们的get和set方法了
(二).包
在日常生活中,我们通常会用文件夹来放不同类型的文件,每一个大文件夹中包含着多个小文件夹。换成Java的角度,那么每个大文件夹就可以理解为包,多个小文件夹就可以理解为多个类
包是对类和接口等的封装机制的体现,是一种对类或接口等的很好的组织形式
常见的Java包有:
1.java.lang:常用的基础类(String、Object)
2.java.util:java提供的工具程序包
当我们想要打印数组中的内容是,我要需要调用Arrays.toString()这个方法来讲数组转为字符串
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] arr={1,2,3,4,5};
System.out.println(Arrays.toString(arr));
}
}
当我们使用toString()这个方法的时候,我们就需要导入一个java.util这个包,同时我们要说明这个包底下的Arrays这个类
导入包中的类的三种方式
1.直接使用
包名.类名.方法
public class Main {
public static void main(String[] args) {
int[] arr={1,2,3,4,5};
System.out.println(java.util.Arrays.toString(arr));
}
}
缺点:每次使用Arrays.toString这个方法都需要写java.util.Arrays.toString(),所以会比较麻烦,一般不使用
2.通过import语句来导入包种的类
格式 :import 包名.类名;
举例:import java.util.Arrays;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] arr={1,2,3,4,5};
System.out.println(Arrays.toString(arr));
}
}
3.导入包中所有的类
import java.util.*;
缺点:不知道具体使用了哪个类,如果当两个不同的包中有相同的类,那么编辑器就不知道具体是使用的哪个类了
import java.util.Date;
import java.sql.Date;
}
public class Main {
public static void main(String[] args) {
Date date=new Date();
}
}

通过图片中可以看出,程序报错了,这就是因为,util包中也都Date类,sql包中也有Date类,当同时导入的时候,编辑器就不知道是哪个类了。
自定义包
右键src
通过上述操作,我们就可以创建一个包了
(三).关键字static
我们先通过一个例子来引入static关键字
class Studnet{
public String name;
public int age;
public String classNum;
public Studnet(String name, int age, String classNum) {
this.name = name;
this.age = age;
this.classNum = classNum;
}
}
public class test {
public static void main(String[] args) {
Studnet studnet1=new Studnet("张三",20,"1班");
Studnet studnet2=new Studnet("李四",22,"1班");
Studnet studnet3=new Studnet("王五",36,"1班");
}
}
我们创建了一个Student类,并实例化了三个对象,分别是students1,students2,students3

调试起来看,他们都是有classNum这个属性,属性值也一样
那么这时候,我们就可以将这个属性设置为公用的属性,如何设置呢?
通过static关键字


通过图片来看,classNum属性没有了。
那是因为,一旦成员变量被staitc修饰了,那么被static修饰的成员属性不再依赖于对象,简单的来说,这个classNum属性不属于对象了,这个classNum只有一份,存放在了方法区中
那么,如果我想访问这个classNum成员属性,应该如何访问?
答:可以通过类名进行访问,即类名.静态成员变量
静态的不依赖于对象,意味着不需要对象的引用来访问
静态成员变量的初始化方法:
1.就地初始化
2.可以通过set和get方法进行初始化
3.可以通过构造方法进行初始化
同时我们也要注意使用static的注意事项下·
1.static方法中不能使用this关键字

其实这一点也好想,static不依赖于对象,调用的时候直接通过类来调用,而this必须依赖于创建的对象才能存在,所以二者在定义的时候就会发生冲突。
2.在静态方法中不能使用非静态方法

如果想要在静态方法中访问非静态的方法,只能通过类来实例化一个对象,通过对象的引用来调用非静态的方法。

3.在非静态方法中可以直接调用静态方法

总结:
方法或者成员变量的调用就2种情况:
(1).通过类名进行调用
(2).通过对象的引用进行调用
(四).代码块
1.概念
使用{}定义的一段代码就叫代码块。
2.分类
代码块分为普通代码块,静态代码块,构造代码块,同步代码块(多线程会深入)
3.普通代码块
普通代码块定义在方法中

我在{}种写了
int a=10;
System.out.println(a);
那么a的作用域就在{}种,一旦出了{},那么a就销毁了,所以当出了{}后,我再打印a,就会报错
4.构造代码块
定义在类中的代码块,也叫实例代码块。一般用于初始化实例成员变量。

快速创建构造代码块的方法

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

为什么说静态代码块一般用于静态成员变量的初始化?
因为静态代码块在类加载的时候就会被执行。也就是说,当程序跑起来的时候,首先执行的就是静态代码块。
如果出现多个静态代码块,都是静态的情况下,和定义的顺序有关。
class Studnet{
public String name;
public int age;
public static String classNum;
static {
System.out.println("静态代码块1");
}
static {
System.out.println("静态代码块2");
}
public Studnet(String name, int age) {
this.name = name;
this.age = age;
// System.out.println("构造代码块");
}
}
public class test {
public static void main(String[] args) {
Studnet studnet=new Studnet("张三",20);
}
public static void main1(String[] args) {
}
}

class Studnet{
public String name;
public int age;
public static String classNum;
static {
System.out.println("静态代码块2");
}
static {
System.out.println("静态代码块1");
}
public Studnet(String name, int age) {
this.name = name;
this.age = age;
// System.out.println("构造代码块");
}
}
public class test {
public static void main(String[] args) {
Studnet studnet=new Studnet("张三",20);
}
public static void main1(String[] args) {
}
}

通过上面两个代码可以看出,当静态代码块2定义在静态代码块1前面的时候,就会先打印静态代码块2,所以有多个静态代码块的时候,会按照定义的顺序来执行。
6.静态代码块,实例代码块,构造代码块执行的先后顺序
class Studnet{
public String name;
public int age;
public static String classNum;
public Studnet(String name, int age) {
this.name = name;
this.age = age;
System.out.println("构造代码块");
}
{
System.out.println("实例代码块");
}
static {
System.out.println("静态代码块");
}
}
public class test {
public static void main(String[] args) {
Studnet studnet=new Studnet("张三",20);
}
}
![]()
通过代码的运行结果我们可以看出,先执行的是静态代码块,然后是实例代码块,最后是构造代码块
让我们实例化多个对象看看
class Studnet{
public String name;
public int age;
public static String classNum;
public Studnet(String name, int age) {
this.name = name;
this.age = age;
System.out.println("构造代码块");
}
{
System.out.println("实例代码块");
}
static {
System.out.println("静态代码块");
}
}
public class test {
public static void main(String[] args) {
Studnet studnet=new Studnet("张三",20);
System.out.println("=========");
Studnet studnet1=new Studnet("李四",55);
}
}

当我们实例了多个对象之后,我们会发现,“静态代码块”就打印了一次,说明静态代码块就执行了一次,也就是说,这个类就加载了一次。[知识点]双亲委派模型
更多推荐







所有评论(0)