java面向对象 —— 封装
Posted 行稳方能走远
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java面向对象 —— 封装相关的知识,希望对你有一定的参考价值。
目录
一、封装的概念
将字段(C结构体中的属性)和方法(C结构体中的函数)包装进类中,加上具体实现的隐藏(访问修饰符),共同被称作为封装,其结果是一个同时带有特征和行为的数据类型。
定义类,定义其属性、方法的过程称为封装类。
学会从C语言的结构体中转换概念:
struct Student
{
int age; //类似与java中的属性 特征
char* name;
void (*introduce)(int age,int name,int score); //函数 = 方法
void (*testFunc)();
};
二、类的封装以及使用
//封装一个类
class Student //写规范来,第一个字母大写
{
int age; //特征
String name; //JAVA中没有char*
double score;
void introduce(){ // 方法 = C语言中的函数
System.out.println("my name is"+name + "age:"+age + "score"+score);
} //面向对象的特性就是方法可以访问本类的特征属性,不需要额外的去传参
void testFunc(){
System.out.println("testFunc");
}
}
//怎么使用这个类呢?
public class Demo1 {
public static void main(String[] args) {
Student stu1 = new Student(); //这操作叫实例化一个对象
//类 = 模板,类不能直接使用,不能直接访问变量,需要先实例化,申请一个空间。
//改成Student stu1 = null,好比C语言的指针使用前不malloc开辟空间
/*这操作就等同于在c语言中,我们对结构体指针的定义及访问
struct Student* p;
p = malloc(sizeof(struct Student));
*/
stu1.age = 18;
stu1.score = 99.5;
stu1.name = "小明"; //不需要像C语言中strcpy赋值
stu1.introduce();
}
}
其中比较重要的概念:
面向对象的特性就是方法可以访问本类的特征属性,不需要额外传参
三、访问修饰符
访问修饰符用于信息隐藏,是OOP(Object Oriented Programming面向对象的编程)重要的功能。
隐藏信息的原因:
(1)对模块的任何实现细节所做的更改不会影响使用该模块的代码
(2)防止用户意外修改数据
(3)使模块易于维护和使用(就是电脑配件)
(4)规范方法,特征的使用空间
访问修饰符:访问权限(通过“.”来访问),可以看到private是最严格的:
位置 | private | 默认 | protected | public |
---|---|---|---|---|
同一个类 | 是 | 是 | 是 | 是 |
同一个包(文件)内的类 | 否 | 是 | 是 | 是 |
不同包内的子类 | 否 | 否 | 是 | 是 |
不同包且不是子类 | 否 | 否 | 否 | 是 |
权限怎么理解呢?
下面就以 “只有正确输入银行卡密码才能读取银行卡信息” 为例子
四、属性封装的实现
封装属性:修改属性的可见性来限制对属性的访问。
为每个属性创建一对赋值方法(getter)和取值(setter)方法,用于公开对这些属性的访问接口,在getter和setter方法中,根据需要加入对属性操作的限制。
举一个最简单的例子:
public class Student {
private String name; //可以通过下面的方法间接访问隐私属性
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
五、方法封装的实现
方法封装的目的:隐藏方法实现细节(方法体),向外部提供公开接口(方法头),以供安全调用;简化调用,方便修改维护;可以私有化方法,以提供内部使用——帮助方法helper。
先设置自己的真实年龄为36岁,当别人当面问你多少岁时,通过“封装的”不对外公开的方法修改了自己的真实年龄,再告诉他我18岁。
但是如果直接访问简历上的年龄,通过这个方法访问到的就是真实年龄36岁
class Age//注意这个类的名字第一个大写(好习惯),不能跟下面的age一样
{
private int age;
void setAge(int realAge){
age = realAge;
}
private void tellAlie(int falseAge)
{
age = falseAge;
}
void askMyAge()//当别人问我的姓名 假
{
tellAlie(18); //外部不知道这个方法的存在
System.out.println("别人问我我就说我永远"+age);
}
void resumeAge() //真
{
System.out.println("简历上是真实年龄:"+age);
}
}
public class Demo3 {
public static void main(String[] args) {
Age a1 = new Age();
a1.setAge(36);
a1.resumeAge();//通过这个方法访问到的是真实年龄
a1.askMyAge(); //不对外公开的方法修改了真实年龄
}
}
六、UML类图
UML-Unified Modeling Language 统一建模语言,又称标准建模语言。
(1)类的命名尽量采用应用领域内的术语。
(2)类的属性、操作中的可见性用+ # -分别表示public protected private
七、类的构造方法与可重载
类的构造方法的概念和作用
构造方法负责对象初始化工作,为对象的属性赋合适的初始值。
在用户操作对象之前,系统就已经完成了类的构造方法。
构造方法的语法规则
(1)构造方法名与类名一致
(2)没有返回类型
(3)方法实现主要为特征赋初值
构造方法的调用很特别:实例化对象(new)的时候,自动被调用
java系统保证每个类都有构造方法:如果没有指明,系统将自动为其分配“空参数”的构造方法。
class Student
{
private int age;
int momAge;
String name;
float score;
Student(int newAge,String newName,float newScore)//方法名字与类名相同
{ //构造方法在实例化对象new时会被调用,到时候再传递参数
//如果不写,系统自动实现,无参无内容
System.out.println("构造方法一被调用");
age = newAge;
name = newName;
score = newScore;
}
//java中,方法是可重载的,即为函数名一样,参数列表不同即可,C语言是不允许的
Student(String newName)
{
System.out.println("构造方法二被调用");
name = newName;
}
Student(String newName,float newScore)
{
System.out.println("构造方法三被调用");
name = newName;
score = newScore;
}
Student(float newScore,String newName) //传入参数类型不同,调换顺序就成为新的构造方法
{
System.out.println("构造方法四被调用");
name = newName;
score = newScore;
}
/* 不能同时有两个int int类似的构造方法,否则数据混淆,IDEA不给你用
Student(int newAge,int newMomAge)
{
System.out.println("构造方法五被调用");
age = newAge;
momAge = newMomAge;
}
Student(int newMomAge,int newAge)
{
System.out.println("构造方法五被调用");
age = newAge;
momAge = newMomAge;
}*/
}
public class Demo1 {
public static void main(String[] args) { //使用哪种构造方法,根据传入的参数而定(不仅是靠个数判断)
Student stu1 = new Student(20,"小明",100);
Student stu2 = new Student("小明");
Student stu3 = new Student("小明",100);
Student stu4 = new Student(100,"小明");
//Student stu5 = new Student(100,100);
System.out.println(stu1.name + stu1.score);
}
}
运行结果:
构造方法一被调用
构造方法二被调用
构造方法三被调用
构造方法四被调用
小明100.0
八、this关键字
(1) 调用此方法的对象的引用
(2)可以看做是一个变量,它的值是对当前对象的引用
(3)可以处理方法中的成员变量与形参同名的问题
(4)在类的构造方法中可以调用this([参数列表])来调用该类的指定构造方法
举例子看看这4个用法:
class student
{
String name;
int age;
void thisTest()
{
//第一种使用方法示例:
System.out.println(this.name);
//第二种使用方法示例:
student stuTemp = null;//临时的对象,太像结构体指针了
stuTemp = this; //把当前对象赋给stuTemp.当前对象:如果是对象stu1,那么就是stu1对象赋给它
System.out.println(stuTemp.age);//必须开辟空间(有对象)
}
//第三种使用方法示例:最常用的解决同名问题
/*student(String name,int age){
name = name;
age = age;
} */
student(String name,int age){
System.out.println("构造方法1被调用了");
this.name = name; //name传给当前对象的name
this.age = age;
}
//第四种使用方法示例:构造方法中又调用另一个构造方法
student(String name){
this("小明",21); //this构造方法只能放在第一句!!!
System.out.println("构造方法2被调用了");
this.name = name;
}
}
public class Demo1 {
public static void main(String[] args) {
student stu1 = new student("小明");//被指定了使用这个构造方法
stu1.thisTest();//thisTest是一种方法,而stu1是调用这个方法的对象
//this就是对这个对象的一种引用,引用他的特征,所以
//会输出stu1对象的信息
}
}
九、static关键字
(1)用来修饰类的成员 —— 修饰成员变量的称为类变量(静态变量)
(2)用来修饰成员方法 —— 称之为类方法(静态方法)
(3)用来修饰语句块 —— 称之为静态代码块
静态代码块先于构造方法之前执行,只会执行一次,用来对静态成员做初始化。当类被加载的时候静态代码块就会被加载,优先于对象的存在。
因为静态代码块的优先于对象存在,所以静态方法中不能出现this关键字:this指的是对象的引用,而static是先于对象存在的
(4)不实例化直接使用类的特征,就是依赖于对象直接对类进行访问
(5)调用的时候可以直接通过类名.成员来进行访问。
例子
class Student
{
String name;
int score;
static int money; //1、类变量(静态变量)
Student(String name,int score){ //构造方法
System.out.println("构造方法");
this.name = name;
this.score = score;
}
static { //3、静态代码块的格式要求
System.out.println("静态代码块"); //静态代码块优先于构造方法执行
money = 5; //并且只执行一次,因为静态变量同类一起,一开始就存在了(相对于需要创建的对象)
} //但构造方法每次在实例化一个对象都会执行
/*static void test(){
System.out.println(this.name); //静态方法中不能出现this关键字
}*/ //因为静态代码块早于对象的创建,而this就是对对象的引用
//并且只能对静态成员做初始化 即money
void introduce(){
System.out.println("名字:"+name + " 分数:"+score);
}
}
public class Demo1 {
public static void main(String[] args) {
Student stu1 = new Student("小明",98);
Student stu2 = new Student("陈立臣",100);
Student.money = 10; //不通过对象,直接通过类名访问类的特征。
//这个静态变量优先于对象的存在(当类被加载时,money也就被加载了)
//而对象实例化之后才有
System.out.println("ret = "+add(1,1));//2、不通过对象,直接访问类的方法
/*如果不用static,只能new,用对象.方法的方式来访问
Demo1 d1 = new Demo1();
System.out.println("ret = "+d1.add(1,1));
*/
}
static int add(int a,int b){ //2、类方法 脱离对象,直接使用方法 优先于对象的存在
return a + b;
}
}
运行结果(注意执行顺序!):
静态代码块
构造方法
构造方法
ret = 2
十、方法重载:overload
同一个类中,同名不同参的方法成为重载方法(在上文类的构造方法与可重载中有大量的例子。)
多数程序设计语言(C语言)要求为每个方法(函数)提供一个独一无二的方法名,不存在方法重载的概念。而在java中,规定方法签名是解析方法的规则而不是方法名,为方法重载开创了条件。
方法重载使得在一个类中,方法名相同而参数列表不同的方法可同时存在,代表相似的行为或功能。
注意:仅有返回值不同的方法不能成为重载
System.out.print
下面有很多的构造方法,也就是方法的重载
十一、包:package
标准java库是由一系列包组成,包括java.lang ,java.util,java.net等等。
java.lang
java语言的核心,它提供了java中的基础类。包括基本Object类、Class类、String类、基本类型的包装类、基本的数学类等等最基本的类。
java.net
和网络相关
java.util
集合类、时间处理模式、日期时间工具等各类常用工具包
打包的意义:
1、java的包是为了更好地规划代码,防止命名冲突和混乱。所以java出现了打包机制。
2、当把类组织起来放进一个包内时,也就给包中的成员赋予了相互访问的权限
package —— 声明包
java程序员都可以编写属于自己的java包,为了保证包名唯一性,要求程序员在自己定义包的名字前加上唯一前缀。
由于互联网上的域名名称不会重复,所以推荐采用公司在互联网上的域名的倒置作为包的唯一前缀,如
com.iotek.ch09
(倒置,当然这也不是绝对的啦)
一个类可以使用同一个包中的所有类
一个类可以使用其他包中的所有公开类
怎样使用其他包中的公开类?
①在每个类的签名之前加上完整包名,例如:
java.util.Data today = new java.util.Date();
- 1
②更简洁更通用的方式:使用import语句来导包(ctrl +shift +O快捷导入)
import java.util.Date
- 1
实际地去做一个包
一个类可以使用同一个包中的所有类,不同包之间记得前面加上public
同一个工程中尽量避免出现两个完全一样的类名。容易混淆,虽然有解决的办法(导包)。
同一个类、同一个包、同一个工程。
以上是关于java面向对象 —— 封装的主要内容,如果未能解决你的问题,请参考以下文章