封装
什么是封装?
如何正确的设计对象的属性和方法
为啥要封装?
安全考虑,封装后用起来更安全
封装的好处
对象代表什么,就得封装对应的数据,并提供数据对应的行为
如何去实现一个封装的代码呢?
使用private修饰方法
private关键字是一个权限修饰符,可以修饰成员(成员变量和成员方法)使用private修饰后的成员只能在本类当中才能访问,如果想要被其他类使用,我们就要提供set方法,用于给成员变量赋值,方法修饰public,提供get方法,用于获取成员变量的值,方法用public修饰
eat方法的权限就被缩小到这个类的范围,出了这个范围的地方eat是不能被调用的
当private修饰我们的当前的成员变量之后,那也意味着当前的成员变量,只能在当前类中使用,所以在类外你是无法访问到内部以及我们在这个地方的eat也不行
如果说有一天我想体现出我的封装性,我不想让类外看到name这个地段,那我们就给它改成private,当我们改成private后也可以看到,写明main方法中用到的name也会报错,而且通过点号也不会给你提示name
private修饰了我们当前的成员变量之后,那也就意味着我们当前的成员变量只能在当前类中使用,所以我们在类外是无法访问到name成员变量,及我们用private修饰的eat方法,这样的话对于类外来说我就拿不到name也拿不到eat方法啦,如果我们想拿到eat方法我们就改成public,此时既然name直接拿不到拿我们可以间接的拿到,可以在Student这个类里面写一个方法,用this.来给成员变量进行初始化
class Student{
private String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public void eat(){
System.out.println(this.name+"正在吃饭");
}
}
public class Java {
public static void main(String[] args) {
Student student = new Student("张三",10);
student.setName("小王");
student.eat();
}
}
运行结果:
小王正在吃饭
我们可以在类里面加一个方法,这个方法返回的是this.name我们在main方法中打印出来
class Student{
private String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public void eat(){
System.out.println(this.name+"正在吃饭");
}
public String getName(){
return this.name;
}
}
public class Java {
public static void main(String[] args) {
Student student = new Student("张三",10);
student.setName("小王");
System.out.println(student.getName());
student.eat();
}
}
运行结果:
小王
小王正在吃饭
这就是我们就对name进行了封装,我们只是提供了公开的这些方法,让你去修改name的值和获得name的值 ,实现封装后类外就无法直接拿到这个name的字段了,封装不是说这个东西不能修改而是说在类外拿不到这个字段,但是我们修改是可以的,就像我们刚刚操作的那样
set方法可以给成员变量赋值
get方法对外提供成员变量的值
1.private关键字是一个权限修饰符
2.可以修饰成员(成员变量和成员方法)
3.被private修饰的成员只能在本类中才能访问
4.针对private修饰的成员变量,如果需要被其他类使用,提供相应的操作
5.提供“setXxx(参数)”方法,用于给成员变量赋值,方法用public修饰
6.提供“getXxx()”方法,用于获取成员变量的值,方法用public修饰
我们先写一个GirlFriend类
public class GirlFriend {
//属性,成员变量
private String name;
private int age;
private String gender;
//有参无返回的,它是给成员变量name进行赋值的
// 我们要用形参来接收n的值,n什么值就用什么值来接收
public void setName(String n){
name = n;//表示把传递过来的值用n来接收,再把它赋值给成员变量name
}
//getName对外提供,name属性的,既然是对外提供的那我们肯定不用接收数据
// 所以不用写形参,我只要把name给外面就可以啦
//而成员变量name又是String类型的,那我们方法的返回值就是String
public String getName(){
return name;
}
public void setAge(int a){
if(a>=18&&a<=50){
age = a;
}
else {
System.out.println("不符合女朋友的标准");
}
}
public int getAge(){
return age;
}
public void setGender(String a){
gender=a;
}
public String getGender(){
return gender;
}
}
再写一个GirlFriend测试类
public class GirlFriendTest {
public static void main(String[] args) {
GirlFriend nuhai = new GirlFriend();
nuhai.setAge(18);
nuhai.setName("萱萱");
nuhai.setGender("女");
System.out.println("姓名:"+nuhai.getName());
System.out.println("年龄:"+nuhai.getAge());
System.out.println("性别:"+nuhai.getGender());
}
}
代码运行:
姓名:萱萱
年龄:18
性别:女
封装快速生成
像我代码中的age也可以封装起来,如果类里面出现了大量的成员变量需要封装那我们就可以使用快捷键来进行操作
Getter and Setter如果点ok它会对name跟age各生成gat和set方法
构造方法也是可以被封装的 ,没有特殊情况我们的构造方法都是有public修饰的
标准的JavaBean类
1.类名需要见名知意,驼峰命名
2.为了表示数据的安全性,所有的变量我都要用private修饰
3.构造方法我们至少要提供两个,一个是空参的,一个是带全部参数的构造方法
4.针对私有化的成员变量我们还要提供对应的setXxx()/getXxx()如果说还有一些其他的行为也要写上
访问限定符
限定符实际上只有三个public是公用的,公开的,protected受保护的,private封装还有一个不是叫做default默认的
public公用的公开的
我们可以给字段或者成员方法,修饰为public
protected受保护的
也就是说你可以把这个字段,修饰为protected
也可以把方法修饰为protected
default不能主动修饰
default不能主动去修饰,没有这个权限
我们就什么都不写,就是默认情况下,所以default并不是一个关键字,它就是一个英文它是默认的
封装扩展之包
包它会对类,接口进行所谓的组织,第一如果说我们在idea上定义或者说去搞一个包,该怎么搞?第二我们现在有用过包没有?有自己导的包
如何在idea新建一个包
如果我们要建一个包,这个包也是在src底下,一般来说我们的包名都是采用全部小写的形式,并且大部分情况下我们都采用域名逆置,比方说百度的域名是www.baidu.com 那我们创建的包名是com.baidu.www那怎么建这样的一个包呢?
这里面输入你的包名,比如说com.bit.www,再回车
这个时候就已经建好啦
我们建的包其实就是文件夹,每个包底下的类是不一样的,如果没有包的情况下我们是不是得在src底下,再建一个text.java?建不了,同一个目录地下文件名是不能重复的,但是我们可以放在包里面
它为什么不冲突呢?就是因为一个是src地下的,一个是www底下的 ,我们相当于在不同的文件夹下面创作类,就这样简单
这个就是包所在的目录底下
导入包中的类
比方说我们想使用Date这个类,我们可以不导包直接手动指定的,然后我们可以对Date进行打印
但是我们这样写会比较长,那我们一般都是这样来写,我可以简写一下,简写一下我要知道这个Date 是从哪里来的,我们可以通过import语句来导
import javax.xml.crypto.Data;
import java.util.Date;
public class text {
public static void main(String[] args) {
Date data = new Date();
}
}
如果说我们不知道这个类在哪里的情况下,可以Alt加回车
通配符*
像这样导包代码我们不用写两行,可以写一行,用通配符*
import java.util.*;
只要你用的东西在util底下它都可以帮你找到,要哪一个它就会匹配哪一个,但是我们更推荐显示类名那种,因为你的Date不仅在一个地方有,所以要指明你到底要哪一个
包的访问权限控制
default同一个包底下的不同类
那我们来看一下,刚刚在demo1包下面创建的两个TestDwmo1跟TestDwmo2,我们先在TestDwmo1这里面定义一个count的字段,然后我们给他赋值一个99,给此字段赋值99, 此时count就是我们的成员变量,没有被修饰, /前面什么都没有加,就是包访问权限,也就是默认权限 包访问权限就是这个count只能在当前的这个包中使用,而我当前在哪个包底下呢?
package com.bit.demo1;
也有在package com.bit.demo1;底下我才能使用我的count,那我们试一下,我们刚刚在 TestDemo2定义的count看一下能不能在TestDemo1当中使用呢?是可以的
default同一个包底下的同一类
它是在同一包同一类里面也是需要实例化对象,再进行使用
default在不同的包底下,不同的类
defauli在不同的底下,不同的类下面是找不到的,权限只能是在同一包底下,不同包底下它是没有这个权限的
java.lang底下的编译器自动导入,不需要通过import导入
比如说:我们用String修饰的时候,就不用自己导import
常见的包
static成员
static关键字呢我们C语言阶段也学习过,静态的,我们要知道为什么要有这个静态的,我们就拿这个Studen来举例,这个是我们的Studen改封装的我们给它封装起来,公开的就是公开的,假设呢现在有三个同学,分别是张三,李四,王麻子如果说我们要去上课,一定会去同一个教室上课,都是一个班的, 我们肯定去一个教室上课不可能说我去305,你去307肯定不合适,所以起始对于我们来说是有一个教室的概念的
import javax.xml.crypto.Data;
class Student{
private String name;
private int age;
private String classRoom;
public String getClassRoom() {
return classRoom;
}
public void setClassRoom(String classRoom) {
this.classRoom = classRoom;
}
public Student(String name, int age)
{
this.name=name;
this.age=age;
}
public String getName(){
return name;
}
public static void main(String[] args){
Student student1 = new Student("zhangsan",11);
student1.setClassRoom("2-103");
Student student2 = new Student("wangermazi",12);
student2.setClassRoom("2-103");
Student student3 = new Student("niuergou",13);
student3.setClassRoom("2-103");
System.out.println("");
}
}
现在是三个学生,都是在同一间教室上课
每个对象它都有一个room,它都是一样的,它是在同一个教室上课,如果放到对象里面,相当于30个学生,30个对象,每个对象你都存一个classRoom,我能classRoom只有一个呢?这个时候呢java说既然我们有一些共同的属性,那么我们可以给他加一个static关键字,加了static意味着这个classRoom
被static修饰的成员变量不属于对象,属于类,那我们通过对象名能不能访问classRoom?
我们访问不了,只能访问到公开的get和set
static修饰成员变量后,合理的访问方式
合理的访问方式是通过类名访问classRoom
import javax.xml.crypto.Data;
class Student{
private String name;
private int age;
public static String classRoom;
public String getClassRoom() {
return classRoom;
}
public void setClassRoom(String classRoom) {
this.classRoom = classRoom;
}
public Student(String name, int age)
{
this.name=name;
this.age=age;
}
public String getName(){
return name;
}
public static void main(String[] args){
Student student1 = new Student("zhangsan",11);
Student.classRoom ="3-105";
student1.setClassRoom("2-103");
Student student2 = new Student("wangermazi",12);
student2.setClassRoom("2-103");
Student student3 = new Student("niuergou",13);
student3.setClassRoom("2-103");
System.out.println("");
}
}
被static修饰的成员变量不属于对象,属于类,所以有些书上会把被static修饰的成员叫做“类变量”,相当于它不是我们每个人的,我们定义类里面了。值能通过类型来访问它,这就叫做static修饰的成员,那换句话说,我们在mian方法这样写
Student.classRoom="2-101";
classRoom初始化或者访问的时候需要实例化对象吗?不需要!因为静态关键字不属于对象也不依赖于对象
总结:类的成员变量 其实有2种:
一.静态成员变量
1.属于类的,不属于对象的,只有1分
2.类名+点号来访问静态成员变量[合理的,对象来访问不合理]2.非静态成员变量/普通成员变量
二.非静态成员变量/普通成员变量
1.属于对象的,每实例化一个对象,都会有一个对应的非静态成员变量。每个对象都有。
2.对应的引用+点号来访问
类被销毁 而销毁静态的成员变量 随着类被加载 而 创建
static修饰成员方法
我们在Student类里面写一个sleep,我们要想调用它的话,就要通过对象的引用来调用我的sleep方法
import javax.xml.crypto.Data;
class Student{
private String name;
private int age;
public static String classRoom;
public String getClassRoom() {
return classRoom;
}
public void setClassRoom(String classRoom) {
this.classRoom = classRoom;
}
public Student(String name, int age)
{
this.name=name;
this.age=age;
}
public String getName(){
return name;
}
public void sleep(){
System.out.println(this.name+"正在睡觉");
}
public static void main(String[] args){
Student student1 = new Student("zhangsan",11);
Student.classRoom ="3-105";
student1.setClassRoom("2-103");
Student student2 = new Student("wangermazi",12);
student2.setClassRoom("2-103");
Student student3 = new Student("niuergou",13);
student3.setClassRoom("2-103");
student1.sleep();
Student.classRoom="2-101";
}
}
代码运行:
zhangsan正在睡觉
我们看一下用static修饰之后的方法可以被调用吗?
import javax.xml.crypto.Data;
class Student{
private String name;
private int age;
public static String classRoom;
public String getClassRoom() {
return classRoom;
}
public void setClassRoom(String classRoom) {
this.classRoom = classRoom;
}
public Student(String name, int age)
{
this.name=name;
this.age=age;
}
public String getName(){
return name;
}
public static void sleep(){
System.out.println("正在睡觉");
}
public static void main(String[] args){
Student student1 = new Student("zhangsan",11);
Student.classRoom ="3-105";
student1.setClassRoom("2-103");
Student student2 = new Student("wangermazi",12);
student2.setClassRoom("2-103");
Student student3 = new Student("niuergou",13);
student3.setClassRoom("2-103");
student1.sleep();
Student.classRoom="2-101";
}
}
运行结果:
正在睡觉
那为什么加了this它会报错呢?
其实这里面不是this的问题,是name都不能用,