面向对象的三大特征: 继承,封装,多态。
封装:
将类的某些信息隐藏在类内部, 不允许外部程序直接访问;通过该类提供的方法来实现对隐藏信息的操作和访问;
隐藏对象的信息 同时 留出访问的接口
生活中的案例:
ATM机,我们可以通过它存取款、转账、余额查询操作。钞票是ATM内的重要信息,但我们在外部是无法直接看到的,这就是ATM机对于钞票这个重要信息的隐藏。但是ATM拥有操作屏, 插卡口,取钞口等,用户通过简单的操作就可以实现隐藏钞票的操作。
特点:
只能通过规定的方法访问数据
隐藏类的实例细节,方便修改和实现
封装的代码实现(上)
private 加在属性上,表明这个属性只能在当前类内被访问。
实现步骤: 修改属性的可见性,设为private; 创建getter/setter方法,设为public,用于属性的读写;在getter/setter方法中加入属性控制语句(对属性值的合法性进行判断:性别只能是男和女啊,年龄只能是正值啊)
宠物猫的年龄应该是正数。
修改属性的可见性
private String name; private int age; private float weight; private String species;
private表示这个属性只能在Cat类内部进行访问。
可以看到此时这些属性已经无法再类外直接通过对象进行访问了。
访问修饰符: private public
还有什么呢?
访问权限是怎样的?
设置公有的getter/setter方法隐藏; 在get/set方法中添加对属性的限定。
public String getName() { return name; }public void setName(String name) { this.name = name; }
可以通过快捷键:
进行快速的生成。
public String getName() { return "我是一只名叫"+name+"小猫"; }
里面可以加入自己的一些逻辑,包装。下面是封装之后的使用:
Cat oneCat = new Cat(); oneCat.setAge(10); oneCat.setName("花花"); oneCat.setSpecies("中华田园猫"); oneCat.setWeight(1000); System.out.println("年龄: "+ oneCat.getAge()); System.out.println("昵称: "+ oneCat.getName()); System.out.println("体重: " + oneCat.getWeight()); System.out.println("品种: " + oneCat.getSpecies());
运行结果:
封装代码实现下
注意只有getXXX方法的属性是只读属性;只有setXXX方法的属性是只写属性。下面我们在set方法中加入一些验证
public void setAge(int age) { if (age <0){ System.out.println("猫的年龄必须大于0"); }else{ this.age = age; } } // 调用 oneCat.setAge(-1);
可以通过异常处理优化程序,后面会详细介绍。如果在构造函数中不使用get set 而是直接赋值,可以正常运行,但是不推荐。因为写在get/set里的验证逻辑将不会被执行。
public Cat(int age){ this.age = age; } Cat oneCat = new Cat(-1); System.out.println("年龄: "+ oneCat.getAge());
因此推荐在构造方法中也同样使用get/set
编程练习
编写自定义类实现图书信息设置,运行参考效果如下所示:
属性: 书名、作者、出版社、价格
方法: 信息介绍
package cn.mtianyan.book;public class Book { public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getPulishingHouse() { return pulishingHouse; } public void setPulishingHouse(String pulishingHouse) { this.pulishingHouse = pulishingHouse; } public float getPrice() { return price; } public void setPrice(float price) { if(price < 10){ System.out.println("图书价格最低10元"); this.price =10; }else{ this.price = price; } } private String title; private String author; private String pulishingHouse; private float price; public Book(String title,String author,String pulishingHouse,float price){ this.setTitle(title); this.setAuthor(author); this.setPulishingHouse(pulishingHouse); this.setPrice(price); } public void info(){ System.out.println("书名: " + this.getTitle()); System.out.println("作者: " + this.getAuthor()); System.out.println("出版社: " + this.getPulishingHouse()); System.out.println("价格: " + this.getPrice()); } }
package cn.mtianyan.book;public class BookTest { public static void main(String[] args) { Book one = new Book("红楼梦","曹雪芹","人民文学出版社",6); Book two = new Book("小李飞刀","古龙","中国长安出版社",55.5f); one.info(); System.out.println("==================="); two.info(); } }
使用包进行类管理
文件夹进行文件管理,同一个文件中可以存放多个不同的文件,同名的文件只能存放在不同的文件夹中。
在Java中如何进行不同类文件的管理呢:java中我们通过包来管理java文件,解决同名文件冲突。
Java中一个包里不能存在同名类
域名倒序+模块+功能(域名全部小写)
package cn.mtianyan.book;
包的定义必须放在Java源文件中的第一行,定义类时,我们应该遵循单一职责原则,因此在建立包的时候,建议每个包内存储信息功能单一。
如何实现跨包的类调用?有几种调用形式?我如何告诉编译器我要调用的是哪个包里的Cat呢?
import cn.mtianyan.animal.*; // 加载包下的所有类import cn.mtianyan.animal.cat; // 加载指定包下的指定类
建议采用 import包名.类名
的方式加载,提高效率
可以直接在程序代码中加载cn.mtianyan.animal.cat
cn.mtianyan.animal.Cat cat = new cn.mtianyan.animal.Cat();
加载类的顺序跟import导入语句的位置无关,具体包的指定,优先级大于通配符。
import cn.mtianyan.*
import包名.*
只能访问指定包名下的类,无法访问子包下的类
包的作用:
管理Java文件
解决同名文件冲突
定义包:
语法: package 包名;例: package cn.mtianyan.animal;
注意: 必须放在Java源文件中的第一行;-个Java源文件中只能有-个package语句;包名全部英文小写;命名方式:域名倒序+模块+功能
导入包语法:
import 包名.类名;
例:导入包中全部类: import cn.mtianyan.*;导入包中指定类: import cn.mtianyan.animal.Cat;
tips(常用系统包):
包名 | 内容 |
---|---|
java.lang | 包含Java语言基础的类,该包系统加载时默认导入 如:System、String、Math |
java.util | 包含Java语言中常用工具 如: Scanner、Random |
java.io | 包含输入、输出相关功能的类 如: File、InputStream |
编程练习
编写自定义类实现用户信息类.
程序参考运行效果图如下:
任务
用户类: 属性(用户名、密码)
用户管理类: 方法(用户信息验证)
package cn.mtianyan.user;public class User { private String username; public User(String username, String password) { this.setUsername(username); this.setPassword(password); } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } private String password; }
package cn.mtianyan.user;public class UserManage { public String checkUser(User one,User two){ System.out.println("用户名: "+one.getUsername()); System.out.println("密码: "+one.getPassword()); System.out.println("用户名: "+two.getUsername()); System.out.println("密码: "+two.getPassword()); System.out.println("================="); if (one.getUsername().equals(two.getUsername())){ return "用户名一致"; }else { return "用户名不一致"; } } }
package cn.mtianyan.user;public class Test { public static void main(String[] args) { User one = new User("Lucy","123456"); User two = new User("Mike","123456"); UserManage userManage = new UserManage(); System.out.println(userManage.checkUser(one,two)); } }
运行结果:
Static关键字(上)
static表示静态信息,它在Java程序中可以和喞些信息組合使用?用它修饰的信息具有哪些特征呢?
public float price; //cat类中
Cat one = new Cat(); one.price = 2000; Cat two = new Cat(); two.price = 150;
上述代码的结果显然脑补都可以脑补到.但假如我们为价格添上static修饰
public static int price; //售价
添加了static修饰之后,price变成了斜体。
可以看到在main中取值时,提示我们静态的成员变量,应该以一种静态的访问方式访问。此时的运行结果中,两只猫的价格都变成了150。
Static表示的是一个静态的,修饰成员时叫做一个静态成员或类成员,它是属于这个类所有的。无论这个类实例化出多少的对象,它都会共用同一块内存空间。
后赋值的会将前面的内存中的内容覆盖掉; 类对象共享;类加载时产生,销毁时释放,生命周期长
one.price = 2000; Cat.price = 3000;
既可以通过对象名,也可以通过类名来访问。
Static关键字中
Static 加在属性前面,被称为静态属性,类属性。同理,Static添加到方法前面就从普通方法,变成了类方法。
public static void eat(){ System.out.println("小猫吃鱼"); }
类方法的调用和我们的静态成员变量的访问时一样的,既可以通过类,也可以通过对象。
oneCat.eat(); Cat.eat();
推荐调用方式:类名.静态成员
除了加在属性,方法,static还可以加在哪些地方呢?
作者:天涯明月笙
链接:https://www.jianshu.com/p/07e3037a3411