JAVA基础 面向对象(二) 类class 函数 封装 隐藏 构造器 JavaBean UML设计

11 篇文章 0 订阅
5 篇文章 0 订阅

一、Java类及类的成员

1、现实世界的生物体,大到鲸鱼,小到蚂蚁,都是由最基本的细胞构成的。同理, Java代码世界是由诸多个不同功能的类构成的。

2、现实生物世界中的细胞又是由什么构成的呢?细胞核、细胞质、.那么,Java中用类class来描述事物也是如此。常见的类的成员有:

属性:对应类中的成员变量 // 属性(JAVA)=成员变量(C++)=field(高频率 国外API文档叫法)=域、字段(国外翻译)

行为:对应类中的成员方法 // 方法(JAVA) = 函数(C++)=method (国外原生API文档叫法)

特别说明:JAVA是真正面向对象的语言,(不像C++,保留了面向过程的部分)因此万物皆对象。所以不存在单独的函数,所有函数都是类的方法。

二、类的创建:

语法:

class 类名 {

【static class;】  //类本身也是对象,class为每个类的隐藏静态属性,代表类本身所代表的对象 类名.class

//属性

【权限修饰符】 数据类型 成员变量名【=值】;  //权限修饰符就是外部调用成员变量的权限大小(封装性的时候专门讲)

/*添加类属性,可以先给类属性赋值,实例化对象的时候如果没给对象属性赋值,这个值可以就先用作对象的默认值*/

......

//方法

【权限修饰符】 返回类型 方法名(形参列表){   //给类添加方法,一般方法的权限都是public,偶尔有private

函数体;

  }

}

2.1 类的属性   成员变量(非static)

1、类的属性就是类成员变量,成员变量有默认值(和数组的默认值一样)

即:(1)数组元素为整型(byte short int long): 默认初始化为 0

(2)数组元素为浮点型(float double):默认初始化为0.0

(3)数组元素为字符型(char):默认初始化为0 (AscII 的0 对应的符号)

(4)数组元素为boolean型:默认初始化为false (boolean值false的底层是0)

(5)数组元素为引用数据类型(String,类):默认初始化为null

2、成员变量在堆内存中,可添加权限修饰符(public,private,protected)限制外部调用成员变量的范围。(具体参考封装性)

2.2类的方法   (static,final,abstract来修饰的方法后面说)

方法用于描述类具有的功能。比如: Math类:sqrt()\random() 方法

方法声明:

【权限修饰符】 返回值类型 方法名(【形参列表】){ 

函数体;  }   // 如果方法带返回值,函数体中一定要有 return 表达式;

说明:

(1)权限修饰符就是外部调用函数时的权限大小(默认权限为缺省,后文有权限修饰符介绍)

(2)如果函数有返回值,返回值类型可以是基本数据类型也可以是引用数据类型,此时,函数体内必须有"return 表达式"(且表达式的值必须是声明的返回值类型)。如果函数没有返回值,方法声明时,用void替换返回值类型,此时函数体内return后面啥都不能加,表示直接结束函数(函数体中的if场景可能会用到)。或者函数体内不写return。

(3)方法名作为标识符,要符合函数标的命名规范(首字母小写,后面每个单词首字母大写xxYyyZzz(小驼峰式)),并要做到“见名知意”。

(4)形参列表:可以声明0个,1个,或多个形参

格式: 数据类型1 形参1,数据类型2 形参2,数据类型3 形参3,......

(5)return关键字的作用:

  • 结束函数 (函数中嵌套了循环,return终止函数的同时,也退出了循环)
  • 返回指定类型的数据(void没返回值)

(6)方法的定义中,可以调用当前类的属性或方法。但不可用方法中再定义方法(嵌套定义方法)

  • 函数进阶:

(7)函数重载(overload)

       同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可(即参数列表不同),编译器会根据实参类型和实参个数自动选择对的类方法。比如:Array类中 sort方法重载了很多次,可以给byte排序,可以给int排序,可以给char排序

说明:跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系。

(8)可变参数形参 

JDK5中新加的特性,用来替代通过数组传形参。

说明:没有可变参数形参之前,想要给方法传入多个参数,只能靠数组。比如public void show(String[ ] strs){ }

可变个数形参格式: 数据类型...变量名

 说明:

I.当调用可变个数形参的方法时,传入的参数个数可以是:0个,1个,2个...N个。但是数据类型必须一致。

II.可变参数同样可以和类中的同名方法构成重载。特别注意,由于历史遗留,此方法形参会和public void show(String[ ] strs){ }中的形参同名,如果同时出现这两种形参且方法名又刚好相同,编译器会报错(不构成重载)。

III.可变参数形参必须声明在形参的末尾,并且只能有一个,要不编译器会没法识别从而报错。比如: 方法名(数据类型1 形参1,数据类型2 形参2,...数据类型N 可变参数形参N

IV.可变参数形参由于是替代数组,也是一个对象,也拥有自己的属性和方法。其中一个属性就是length,看到底传过来了多少个实参。

exp:

class vargTest {            //定义一个拥有可变形参方法的类vargTest

public void show(String...strs){   //定义类中的可变形参方法show。

 System.out.println("show me"};

}

public static void main(String[ ] args){

   vargTest test = new 构造器();

   test.show("hello");        //一个实参可以调用show方法

   test.show("hello","showgirl");  //两个实参也可以调用show方法

   test.show();  //0个实参也可以调用show方法

}

(9)函数递归(recursion)    写递归真的费脑子啊

     函数递归指一个方法体内调用它自身。

说明:函数递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制

注意:递归一定要向已知方向递归,视情终止递归,否则这种递归会变成无穷递归,类似于死循环。

exp:计算1-100自然数的和

思路:求n个数的和,就是求(n-1)个数的和+n,求(n-1)个数的和,就是求(n-2)个数的和+(n-1).....一直到1

public int sum(int n){

if(n==1) {         //当n一直减到1的时候,必须停止递归,要不死循环了。然后1+2作为返回值,去解上一层sum,直到最外层

return 1;   }

else return n + sum(n-1); 

}

总结:递归解题步骤,写出递推公式,找出终止条件,翻译成递归代码。

三、类的封装

1、概述

     程序设计追求“高内聚”,“低耦合”

    高内聚:类的内部数据操作细节自己完成,不允许外部干涉。

    低耦合:仅对外暴露少量的方法用于使用。

    隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。

2、封装对象内部属性的方法:权限修饰符private

语法: private 数据类型 属性名【=属性值】; 

说明:此时该属性被隐藏。只能通过public方法,对该属性进行赋值。同理,也只能通过类的public方法,调用这个属性。总之,一旦封装了类的属性,就要写公共的get和set方法来获取或者设置属性值。

  • 附录:权限修饰符

(1)JAVA规定了4种权限:private、缺省、protected、public

(2)4种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类

四、类的构造器

构造器 constructor(C++的构造函数)

构造器的作用:创建对象

说明:如果没有显式定义类的构造器,系统会默认隐式提供一个空参的构造器。但是注意,一旦显式定义了类构造器,系统将不再提供默认的类空参构造器

语法: (一般类的第一个方法 就是构造器)

权限修饰符 类名(【形参列表】){}   //权限默认为 类的权限

说明:构造器也可以"重载",通过构造器“重载”,可以初始化对象属性(也可添加一些行为)

五、扩展1 this指针

this指针 指向当前类的本身,可以看做当前类。写在类的内部 //后面类实例化成啥具体对象,这个this指针就指啥对象

说明:由于this是当前类本身,自然有如下语法:

this(形参列表) ;  //调用本类的其他构造器(不能自己调自己),主要用于少写代码

规定:如果用this调用其他构造器,必须放在当前代码块的首行。(由于只有一个首行,隐喻不能调2个构造器)

this.属性名; //调用类的属性,通常可以省略this,遇到和形参重名了,就没法省略了

this.方法名; //调用类的方法

应用场景1:调用当前类本身的构造器

     很多时候,一个类会写多个构造器,每个构造器之间又有80%相同代码+20%自己的特有代码。80%相同代码如果行数很多,就会显得冗余。 此时可以通过 this(形参列表),调用构造器。

应用场景2:调用类属性

     由于要尽量符合标识符命名规范中的“见名知意”,类的属性名,和设置类属性值的形参名都是一个东西,取一样的名字最好识别。虽然由于形参和类属性名作用域不同,不会报错,但是编译器会搞混。因此,可以给类属性名加上this,变成this.属性名,表示此变量时属性,而非形参

exp: class Person{

private int age;

public Person(){

函数体;              //假装有100行代码

    }

public Person(int age){      //构造器的形参名age 和 属性名age 一样了

this();             //直接调用构造器,就少写了(复制)100行代码

this.age = age   //用了this指针,编译器就能很好的区分了

    }

}

扩展2:JavaBean     一种符合特定规范的Java类

     JavaBean是一种Java语言写成的可重用组件

      符合如下JavaBean标准的Java类,都是JavaBean

JavaBean标准:

1、类是公共的      //其他类可见

2、有一个无参的公共构造器    //方便在其他类方法中创建这个类的对象,但此时属性都是默认值

3、有属性,且有对应的get、set方法 //方便在其他类方法中,给这个对象赋值

扩展3 UML设计图

六、对象  (类的实例化)

1、创建类的对象

语法:

类名 变量名 = new 类构造器(【形参列表】);

说明:

(1)Java允许实例化一个空对象,后面给对象属性赋值。(c要求构造函数赋值)

(2)给对象的属性赋值之前,对象可先用类的属性值作为默认值,如果类没赋默认值,成员变量本身还有默认值(规则和数组默认值一样)

2、调用对象的属性、方法

(1)调用对象属性

语法:  变量名.属性名=值;   //注意属性的权限,如果是private,类外只能通过public函数赋值

(2)调用对象方法

语法:变量名.方法名(实参列表);

说明:相当于在方法的函数体作用域内,把实参赋值给形参。  

注意:Java不像C++可以直接按引用传递基本数据类型 即通过&变量名就把数据穿了。

因此 Java要实现变量数据交换等功能,需要先把要交换的数据封装在一个对象里。然后把对象作为实参传给方法(方法必须接收引用数据类型)。

exp:

3、同一类对象之间的赋值   (区别C++  为啥JAVA没有运算符重载)

      对象赋值和数组一样,类对象之间赋值是给的对象的指针,此时两个对象同时指向堆的同一内存块。并不是将某一对象赋值给另一对象。  由于赋值的是指针,自然就没法像c++一样重载运算符“=”,操作想赋值的属性给对象。

结论:引用类型的赋值,都是赋值地址。

exp:

Student Tao = new Student();

Tao.age = 29;

Student Zou = new Student();

Zou=Tao;              // 将Tao对象的指针 赋给  Zou对象,此时对象Tao 和 Zou 都指向同一内存块 

Zou.age =23;   //此时修改Zou,就是修改Tao

System.in.println(Tao.age);  //自然Tao.age 也被改为23

4、对象内存解析 (暂时不讨论方法,不讨论static,不讨论private)

exp:

class Person{

String name;

int age = 1;    //设置类 age属性的默认属性值为1

boolean isMale ;

}

注意:Tom是String,又是引用,在方法区,不在堆里面。这里只是方便

5、匿名对象

如果创建的对象,没有显示的赋值给一个变量名。即为匿名对象。

特征:匿名对象只能调用一次

exp: class Phone{      //定义一个Phone类

double price=2000;

public void sendEmail(){

    }

public void playGame(){

    }

}

new Phone().price=3999; //创建了一个Phone匿名对象,并将其price属性设置为3999

System.in.println("new Phone().price");//又创建了一个Phone匿名对象,并打印其价格,为默认值2000

注意:两次创建的匿名对象不是一个对象,是两个对象。所以price属性,是完全不一样的(匿名对象只能调用一次。)。

  • 匿名对象应用方法  (思路:让匿名对象不再匿名,即可多次使用)

如果将匿名对象作为实参传递给另一个新函数。就相当于把新创建的匿名对象的地址值赋值给了新函数的形参。此时匿名对象不再匿名,他的名字就是新函数形参名,就可以多次使用。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值