封装的概念和特点
封装
1.将类的某些信息隐藏在类内部,不允许外部程序直接访问。
2.通过该类提供的方法来实现对隐藏信息的操作和访问。
3.隐藏对象的信息。
4.留出访问的接口
特点:
1.只能通过规定的方法访问数据;
2.隐藏类的实例细节,方便修改和实现;
封装的代码实现(上)
封装的代码实现实现步骤:
1.修改属性的可见性设为private(限定只能在当前类中被访问)
2.创建getter/setter方法,设为public用于属性的读写
3.在getter/setter方法中加入属性控制语句;
例子:
package com.imooc.animal;
/**
- 宠物猫类
- @author HeFeihong
*
*/
public class Cat {
//成员属性:昵称、年龄、体重、品种
//修改属性的可见性---private限定只能在当前类内访问
private String name;//昵称
int month;//年龄
double weight;//体重
String species;//品种
public Cat() {
}
public Cat(String name) {
System.out.println("我是带参构造方法");
}
public Cat(String newName,int newMonth,double newWeight,String newSpecies) {
name=newName;
month=newMonth;
weight=newWeight;
species=newSpecies;
}
//创建get/set方法
//在get/set方法中添加对属性的限定
public void setName(String name) {
this.name=name;
}
public String getName() {
return "我是一只名叫:"+this.name+"的宠物猫";
}
}
package com.imooc.animal;
public class CatTest {
public static void main(String[] args) {
//对象实例化
Cat one=new Cat("花花",2,1000,"英国短毛猫");
//测试
one.setName("凡凡");
System.out.println(one.getName());
}
}
封装的代码实现(下)
属性只有setXXX方法--只读属性
属性只有getXXX方法--只写属性
package com.imooc.animal;
/**
- 宠物猫类
- @author HeFeihong
*
*/
public class Cat {
//成员属性:昵称、年龄、体重、品种
//修改属性的可见性---private限定只能在当前类内访问
private String name;//昵称
private int month;//年龄
private double weight;//体重
private String species;//品种
public Cat() {
}
public Cat(String name) {
System.out.println("我是带参构造方法");
}
public Cat(String newName,int newMonth,double newWeight,String newSpecies) {
name=newName;
month=newMonth;
weight=newWeight;
species=newSpecies;
}
//创建get/set方法
//在get/set方法中添加对属性的限定
public void setName(String name) {
this.name=name; //最好改为this.setName=name;
}
public String getName() {
return "我是一只名叫:"+this.name+"的宠物猫";
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
if(month<=0) {
System.out.println("输入信息错误,宠物猫的年龄必须大于0");
}else
this.month = month;
}
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;
}
}
package com.imooc.animal;
public class CatTest {
public static void main(String[] args) {
//对象实例化
Cat one=new Cat("花花",2,1000,"英国短毛猫");
//测试
one.setName("凡凡");
one.setMonth(-3);//=-3
System.out.println(one.getName());
System.out.println(one.getMonth());
}
}
编程练习
编写自定义类实现图书信息设置。请按照编辑器中的注释,在对应的空白区域填写对应的代码,完成程序设计。
运行参考效果如下所示:
输入信息错误,图书价格必须大于10
书名:红楼梦
作者:曹雪芹
出版社:人民文学出版社
价格:10.0元
==================================
书名:小李飞刀
作者:古龙
出版社:中国长安出版社
价格:55.5元
任务
属性:书名、作者、出版社、价格
方法:信息介绍
要求:
1、 设计构造函数实现对属性赋值
2、 设置私有属性,get/set方法实现对属性的访问
3、 限定图书价格必须大于10,如果无效需进行提示,并强制赋值为10
4、 限定作者、书名均为只读属性
5、信息介绍方法描述图书所有信息
public class Book {
//私有属性:书名、作者、出版社、价格
private String name;
private String author;
private String press;
private double price;
//通过构造方法实现属性赋值
public Book(){
}
public Book(String name,String author,String press,double price){
this.name=name;
this.author=author;
this.press=press;
this.price=price;
}
/*通过公有的get/set方法实现属性的访问,其中:
1、限定图书价格必须大于10,如果无效需进行提示,并强制赋值为10
2、限定作者、书名均为只读属性
*/
//信息介绍方法,描述图书所有信息
public String getName() {
return "书名:"+this.name;
}
public String getAuthor(){
return "作者:"+this.author;
}
public void setPress(String press){
this.press=press;
}
public String getPress(){
return "出版社:"+this.press;
}
public void setPrice(double price){
if(price<10){
System.out.println("输入信息错误,图书价格必须大于10");
this.price=10;
}else
this.price=price;
}
public double getPrice(){
return this.price;
}
}
public class BookTest {
// 测试方法
public static void main(String[] args) {
//实例化对象,调用相关方法实现运行效果
Book one=new Book("红楼梦","曹雪芹","人民文学出版社",15);
one.setPrice(5);
System.out.println(one.getName());
System.out.println(one.getAuthor());
System.out.println(one.getPress());
System.out.println("价格:"+one.getPrice()+"元");
System.out.println("==================================");
Book two=new Book("小李飞刀","古龙","中国长安出版社",55.5);
System.out.println(two.getName());
System.out.println(two.getAuthor());
System.out.println(two.getPress());
System.out.println("价格:"+two.getPrice()+"元");
}
}
使用包进行类管理--创建包
包:
一个包内,类不能重名
域名的倒叙+模块+功能
域名全都小写
每个包存储信息功能单一
使用包进行类管理--导入包
如果要导入的多个包中有相同的类名,如:
import com.imooc.animal.Cat;
import com.imooc.mechanics.Cat;
第二条语句系统会报错,系统分不清要导入哪个Cat。
再比如:
import com.imooc.mechanics.*;
import com.imooc.animal.Cat;
这样系统调用Cat类时,会解析animal下的类,而不会找到mechanics下的Cat类。因为animal下的Cat类首先解析。如果要访问mechanics下的Cat类时,只能在代码中直接加载。
import加载时,如有 import com.imooc.*;只能加载imooc文件夹下能找到的类,而不会再向下级文件查找。没有类的话就找不到。
//import com.imooc.animal.*;//加载com.imooc.animal下所有类
import com.imooc.animal.Cat;//加载com.imooc.animal下指定的cat类
//直接加载com.imooc.animal.catTest
com.imooc.animal.CatTest tex=new com.imooc.animal.CatTest();
常用系统包
java.lang baohjava语言基础的类,该包系统加载时默认导入,如System、String、Math
java.tuil 包含Java语言中常用工具,如Scanner、Random
java.io 包含输入、输出相关功能的类,如File、InputStream
编程练习2
编写自定义类实现用户信息类。请按照编辑器中的注释,在对应的空白区域填写对应的代码,完成程序设计。
程序参考运行效果图如下:
用户名Lucy
密码:123456
用户名Mike
密码:123456
========================
用户名不一致
密码一致
任务
- 用户类:
属性:用户名、密码
- 用户管理类:
方法:用户信息验证
要求:
1、 设计构造函数实现对属性赋值
2、 设置私有属性,get/set方法实现对属性的访问
3、用户信息验证判断两个用户信息是否一致
PS: 可以通过equals()方法进行字符串内容的判断,如果内容相等返回值为true,反之为false,如当str代表用户性别时,可以通过如下代码,判断性别为“男”还是“女”
public class UserManager{
// 用户信息验证的方法
public String checkUser(User one, User two) {
// 判断用户名是否为空,是否一致
/* if(one.getUsername().equals(null)){
System.out.println("用户名为空");
}
else*/ if(one.getUsername().equals(two.getUsername())){
System.out.println("用户名一致");
}
else{
System.out.println("用户名不一致");
}
// 判断密码是否为空,是否一致
/* if(one.getPassword().equals("")){
System.out.println("密码为空");
}
else*/ if(one.getPassword().equals(two.getPassword())){
System.out.println("密码一致");
}
return "" ;
}
}
public class User{
//定义属性用户名、密码
private String username;
private String password;
public User(){
}
public User(String username,String password){
}
public void setUsername(String username){
this.username=username;
}
public String getUsername(){
return this.username;
}
public void setPassword(String password){
this.password=password;
}
public String getPassword(){
return this.password;
}
public void message(){
System.out.println("用户名"+username);
System.out.println("密码:"+password);
}
}
public class Test{
// 测试方法
public static void main(String[] args) {
//实例化对象,调用相关方法实现运行效果
User one=new User();
User two=new User();
one.setUsername("Lucy");
one.setPassword("123456");
two.setUsername("Mike");
two.setPassword("123456");
UserManager test=new UserManager();
one.message();
two.message();
System.out.println("========================");
System.out.println(test.checkUser(one,two));
}
}
static关键字
static:静态成员、类成员
特征:类加载时就产生,无论创建多少个对象,它们共用同一块静态空间,只有当所有对象被销毁时,static开辟的静态空间才会被销毁。static定义的变量以最后赋值为基准,
静态成员的访问方法:
1:对象.成员
2:类.成员
static(静态,静态成员,类成员): 可以添加到成员属性或成员方法前面
1.添加到成员属性前面→成员属性变为静态属性(类属性)→类属性的调用(对象名或类名)
2.添加到普通成员方法前面→成员方法变成类方法→类方法的调用(同上,通过对象名或类名)
3.添加到类前面是非法的
4.在方法中可定义局部变量,在局部变量前面不可以添加static修饰符,只能加final
5.在我们前面定义的成员方法当中,我们可以直接调用当前类当中的任意成员,比如在普通成员方法run()中,既可以直接调用与它同一类的静态方法eat(),也可以通过this关键字调用普通成员属性或静态属性。也就是说,在成员方法中,可以直接访问类的静态成员
6.但是静态方法当中不能直接访问非静态成员(包括非静态的方法和属性),只能直接调用静态成员
7.static和this关键字也是冲突的,static代表类共享,而this代表实例,因此在静态方法中不可以使用this关键字
{}代码块 (知识点梳理)
1.(1)当它出现在方法里的时候,我们称之为普通代码块,它的执行顺序和一般语句的执行顺序是一样的,即顺序执行。
(2)它可以有任意数量,在方法中有任意位置。
2.(1)当它在不在方法中,而在类里单独出现时,被称为构造代码块,在创建对象时即被调用,优先于构造方法执行。
(2)在类中同样能有多个。
(3)在构造代码块前面加static之后,它就升级成了静态代码块,静态代码块首先执行,在类中能有多个静态代码块。
3.问:静态代码块代表的是类共有的相关信息,当我们在测试类中创建了多个对象实例的时候,静态代码块会执行几次,而构造代码块又会执行几次呢?
答:静态代码块,无论实例化多少个对象,它只会被执行一次,而且是最先被全部执行完毕;而构造代码块,每次进行实例化的时候,它都会被执行一次
4.在静态代码块中,只能给静态成员进行赋值,不能给普通成员赋值;在构造代码块中就没这些限制咯
编程练习3
请根据效果图以及任务要求完成代码。
程序参考运行效果图如下:
CodeBlock的静态代码块
CodeBlock的主方法
产生Code类实例对象
Code静态代码块
Code构造代码块
Code构造方法
产生CodeBlock类实例对象
CodeBlock的构造代码块
CodeBlock构造方法
任务
- 创建类Code,类中编写构造块、静态代码块以及构造方法
- 创建CodeBlock,类中编写的构造块、静态代码块以及构造方法
- 在主函数中测试他们的执行的优先顺序(运行结果参见效果图)
class Code{
//创建外部类Code构造块(构造块)
{
System.out.println("Code构造代码块");
}
//创建外部类Code静态代码块(静态代码块)
static{
System.out.println("Code静态代码块");
}
//创建外部类Code构造方法(构造方法)
public Code(){
System.out.println("Code构造方法");
}
}
public class CodeBlock{
// 创建CodeBlock的构造块
{
System.out.println("CodeBlock的构造代码块");
}
//创建CodeBlock的静态代码块
static{
System.out.println("CodeBlock的静态代码块");
}
//创建CodeBlock的构造方法
public CodeBlock(){
System.out.println("CodeBlock构造方法");
}
public static void main(String[] args){
//编写代码测试运行优先顺序,运行结果参见效果图
System.out.println("CodeBlock的主方法");
System.out.println("产生Code类实例对象");
Code code=new Code();
System.out.println("产生CodeBlock类实例对象");
CodeBlock codeblock=new CodeBlock();
}
}
static关键字(续)
代码块内部的变量存活周期是从代码块开始到代码块结束,作用范围只在代码块内有效,结束之后会被回收。
而方法体的局部变量的作用范围,从定义的位置直到方法体完,且不会回收。
方法体中局部变量的作用域:
1、代码块内部:只在该代码块内生效;
2、代码块外部:从变量被定义开始生效一直到方法结束。