【从零开始的Java开发】1-3-2 Java封装、包package、static关键字、代码块

封装

  • 将类的某些信息隐藏在类内部,不允许外部程序直接访问
  • 通过该类提供的方法来实现对隐藏信息的操作和访问
  • 隐藏对象的信息,也留出访问的接口

三个步骤

实现步骤:

  1. 修改属性的可见性:设为private
  2. 创建getter/setter方法:设为public用于属性的读写
  3. 在getter/setter方法中加入属性控制语句:对属性值的合法性进行判断

举个例子:
类Cat中的name属性设为private

private String name;

则测试类中会报错:属性不可被访问。
在这里插入图片描述
创建get/set方法

	//get方法
	public String getName() {
		return this.name;
	}
	
	//set方法
	public void setName(String name) {
		
	}

在get/set方法中添加对属性的限制
(其实就是在对应方法里写方法体)

	//get方法
	public String getName() {
		return this.name;
	}
	
	//set方法
	public void setName(String name) {
		this.name=name;
	}

测试类:

one.setName("A");
System.out.println("我叫"+one.getName());

输出:

我叫A

关于在get/set方法中添加对属性的限制
如:

public void setAge(int age) {
		if (age < 0)
			System.out.println("年龄不能为负数");
		else this.age = age;
	}

在测试类中运行:

one.setAge(-3);
System.out.println("年龄是" + one.getAge());

输出:

年龄不能为负数
年龄是0

则-3没有被输入进年龄——被限制了。

补充:与构造函数联动
若类的内容如下:

public class Cat {	
	int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		if (age < 0)
			System.out.println("年龄不能为负数");
		else
			this.age = age;
	}

	public Cat(int age) {
		this.age = age;
	}
}

测试类:

public static void main(String[] args) {		
		Cat one = new Cat(-3);		
		System.out.println("年龄是" + one.getAge());
	}

输出:

年龄是-3

这里构造函数直接赋值,没有使用set函数——没有限制。

但如果:
构造函数如下:

public Cat(int age) {
		setAge(age);		
	}

输出:

年龄不能为负数
年龄是0

这里set有限制,所以-3没有被输入进age属性。

eclipse自动生成get和set方法

右键-Sourse-Generate Getters and Setters

在这里插入图片描述
然后就可以选要自动生成的方法:
在这里插入图片描述
Select All后:

public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public double getWeight() {
		return weight;
	}

	public void setWeight(double weight) {
		this.weight = weight;
	}

	public String getSpecies() {
		return species;
	}

	public void setSpecies(String species) {
		this.species = species;
	}

使用包进行类管理

在Java中,我们通过包来管理Java文件,解决同名文件冲突问题。

假设我们现在要创建一个新的类,也叫Cat,用来描述机器猫。

创建包

在同一个包中不能有同名的类:
在这里插入图片描述
所以我们这里要创建一个新的包:
命名(习惯)方式:域名倒序+模块+功能。(——全小写)

包名:com.machine
在包里创建一个Cat类:

package com.machine;//表示这个类是封装在这个包里的——一定要放在第一行

public class Cat {

}

导入包

定义包:package com.test表示当前类封装在这个包里的。

导入包(三种方法):
加载包中所有的类:.*import com.pet.*;
加载包中特定的类:import com.pet.Cat 只加载了Cat类

如:导入了所有类,则两个类都可以调用。
在这里插入图片描述

如:只导入了一个类,则另一个类不能调用:
在这里插入图片描述
一般来说:导入包中的某个类效率更高。

在程序中可以直接加载某个类:

//直接加载com.pet.CatTest
com.pet.CatTest t=new com.pet.CatTest();

这样就不会报错了:
在这里插入图片描述

如果想同时导入pet里的Cat和machine里的Cat怎么办?
不能两个都是Cat:
在这里插入图片描述

解决方法1:把一个变成导入包中所有的类。
在这里插入图片描述
那么问题来了:如果我们这里要实例化一个Cat类,我们实例化的是pet的Cat还是machine的Cat?

我们令两个Cat类的构造函数分别为:

package com.pet;

public class Cat {
	public Cat() {
		System.out.println("我是pet.Cat");
	}
}
package com.machine;

public class Cat {
	public Cat() {
		System.out.println("我是machine.Cat");
	}
}

测试类如下:

package com.test;
import com.pet.Cat;
import com.machine.*;
public class Test {
	public static void main(String[] args) {
		Cat cat1=new Cat();		
	}
}

输出:

我是pet.Cat

若先导入import com.machine.*;,输出也是我是pet.Cat

则:加载类的顺序跟import语句的位置无关,会先去找能够直接解析到的类
这里可以直接解析到pet.Cat的Cat,所以先找到的是pet的Cat。

如果我们想访问machine的Cat,我们就要在程序中直接写出machine.Cat:

com.machine.Cat cat1=new com.machine.Cat();

输出:

我是machine.Cat

那么问题来了,我们可以通过com.machine.*找到这个包下所有的类,那我们可以通过com.*找到com包下所有的类吗?——不可以。

会报错:无法解析到CatTest类。

在这里插入图片描述
原因是:import 包名.*; 只能访问指定包名下的类,无法访问其子包下的类。

在这里,com下面只有machine,pet,test三个包,没有类,所以没有类可以访问。

包的总结

作用:

  1. 管理Java文件
  2. 解决同名文件冲突

定义包

语法:package 包名;

  • 必须放在Java源文件中的第一行
  • 一个Java源文件中只能有一个package语句
  • 包名全部英文小写
  • 命名方式:域名倒序+模块+功能

导入包

语法:import 包名.类名;
加载包中所有的类:.*import 包名.*;
加载包中特定的类:import 包名.类名;

系统常用包
在这里插入图片描述

关于调试

在这里插入图片描述

static关键字

static表示静态信息

一些代码:
Cat类:

package com.pet;

public class Cat {

	// 属性:昵称、年龄、体重、种类、售价
	private String name;	
	private int age;
	private double weight;
	private String species;	
	private int price;
	
	//封装:get方法和set方法
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public double getWeight() {
		return weight;
	}
	public void setWeight(double weight) {
		this.weight = weight;
	}
	public String getSpecies() {
		return species;
	}
	public void setSpecies(String species) {
		this.species = species;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}

}

测试类:

package com.test;

import com.pet.Cat;

public class Test {
	public static void main(String[] args) {
		Cat one = new Cat();

		// 用set类赋值
		one.setName("A");
		one.setAge(2);
		one.setPrice(2000);
		one.setSpecies("英短");

		Cat two = new Cat();
		two.setName("B");
		two.setAge(1);
		two.setPrice(100);
		two.setSpecies("中华田园");
		
		System.out.println(one.getName()+"的价格为:"+one.getPrice());
		System.out.println(two.getName()+"的价格为:"+two.getPrice());
	}
}

输出如下:

A的价格为:2000
B的价格为:100

接下来进行一些修改:

public static int price;

在这里插入图片描述

price变成了斜体

且测试类中直接对price属性进行访问:会得到提示——要对它进行静态的访问。
在这里插入图片描述
添加了static后再次运行测试类,输出得到:

A的价格为:100
B的价格为:100

——原因是:
static表示静态。
被静态关键字修饰的成员为静态成员,也称为类成员。
无论类实例化多少对象,这个成员都会用同一份内存空间。

静态成员特征:

  • 类对象共享
  • 类加载时产生,销毁时释放,生命周期长

静态成员的访问方法:

  1. 类名.静态成员——无警告
  2. 对象名.静态成员——有警告

在上面的代码里,price是Cat类的静态成员,所以这样访问:int a=Cat.price;
在这里插入图片描述
这样就没有警告信息了。

代码:

package com.test;

import com.pet.Cat;

public class Test {
	public static void main(String[] args) {
		Cat one = new Cat();

		// 用set类赋值
		one.setName("A");
		//两种访问方法
		one.setPrice(2000);
		Cat.price=100;

		
		System.out.println(one.getName()+"的价格为:"+one.getPrice());

	}
}

结果如下:

A的价格为:100

静态方法
static放到方法前,也成为类方法。
调用方法:

  • 通过对象名调用
  • 通过类调用(推荐)

静态方法不能访问非静态方法
在这里插入图片描述
这里eat如果想访问run,则可以把run改成静态方法:
在这里插入图片描述
这样就不报错了。

——静态方法不能直接访问同一个类的非静态成员,只能直接调用同一个类的静态成员

一个静态方法不能访问非静态属性的例子:
在这里插入图片描述
一个静态方法中间接访问非静态成员的例子:通过对象实例化后,对象.方法的方式访问

public static void run() {
		Cat temp = new Cat();
		temp.eat();
		System.out.println("run!");
	}

	public void eat() {
		System.out.println("eat!");
	}

这样不会报错。

类前面不能加static
只能加:publicabstractfinal
在这里插入图片描述
局部变量前不能加static
只能加final
在这里插入图片描述

代码块

普通代码块
在普通方法中。
顺序执行,先出现,先执行。

如类Cat中有方法如下:

public void run() {
		{
			System.out.println("普通代码块1");
		}
		System.out.println("run!");
		{
			System.out.println("普通代码块2");
		}
	}

调用one.run();,输出:

普通代码块1
run!
普通代码块2

构造代码块
在类中定义。
创建对象时调用,优先于构造方法执行
可以有多个。

如:

public class Cat {

	public void run() {
		{
			System.out.println("普通代码块1");
		}
		System.out.println("run!");
		{
			System.out.println("普通代码块2");
		}
	}

	{
		System.out.println("构造代码块1");
	}

}

调用one.run();,输出:

构造代码块1
普通代码块1
run!
普通代码块2

静态代码块
在代码块前加关键字static
类加载时调用,优先于构造代码块执行。
可以有多个。

public class Cat {

	public void run() {
		{
			System.out.println("普通代码块1");
		}
		System.out.println("run!");
		{
			System.out.println("普通代码块2");
		}
	}

	{
		System.out.println("构造代码块1");
	}
	
	static
	{
		System.out.println("静态代码块1");
	}

}

调用one.run();输出:

静态代码块1
构造代码块1
普通代码块1
run!
普通代码块2

静态代码块,无论实例化多少次对象,都只会执行一次。
构造代码块,每实例化一次对象都会执行一次。
——仅希望执行一次的代码可以放在静态代码块中。

类如下:

public class Cat {

	{
		System.out.println("构造代码块1");
	}
	
	static
	{
		System.out.println("静态代码块1");
	}

}

测试类如下:

Cat one = new Cat();
Cat two = new Cat();

输出:

静态代码块1
构造代码块1
构造代码块1

普通代码块、构造代码块中可以给属性赋值(静态或非静态)。
静态代码块中只能给静态属性赋值。
与静态方法中的成员调用相似。

总结

面向对象编程的三大特征

  • 封装
  • 继承
  • 多态

封装

  • 通过该类提供的方法来实现对隐藏信息的操作和访问
  • 隐藏对象的信息,留出访问的接口

特点

  • 只能通过规定的方法访问数据
  • 隐藏类的实例细节,方便修改和实现

步骤

  1. 修改属性的可见性:设为private
  2. 创建getter/setter方法:设为public用于属性的读写
  3. 在getter/setter方法中加入属性控制语句:对属性值的合法性进行判断

1:隐藏对象
2、3:留出接口

包:
——作用

  1. 管理Java文件
  2. 解决同名文件冲突

定义包

语法:package 包名;

  • 必须放在Java源文件中的第一行
  • 一个Java源文件中只能有一个package语句
  • 包名全部英文小写
  • 命名方式:域名倒序+模块+功能

导入包

语法:import 包名.类名;
加载包中所有的类:.*import 包名.*;
加载包中特定的类:import 包名.类名;

static

  1. static+属性——静态属性、类属性
  2. static+方法——静态方法、类方法
  3. static+类——不存在
  4. static+方法内局部变量——不存在
  5. static+(构造)代码块——静态代码块

代码块
在普通方法中:普通代码块
在类中:构造代码块
static+构造代码块:静态代码块

注意

  • 静态成员的生命周期:类加载时产生,销毁时释放,生命周期长
  • 静态方法中的成员调用:只能直接访问类内的静态成员,如果实在要访问非静态成员,就对象实例化,通过对象的方式来访问
  • 各种代码块的执行顺序:静态代码块只执行一次,构造代码块在每次对象构造的时候调用
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

karshey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值