6.1.1对象
在现实世界中,随处可见的一种事物就是对象,对象是事物存在的实体,如人类、书桌、计算机、高楼大厦等。人类解决问题的方式总是将复杂的事物简单化,于是就会思考这些对象都是由哪些部分组成的。通常都会将对象划分为两个部分,即静态部分与动态部分。静态部分,顾名思义,就是不能动的部分,这个部分被称为“属性”,任何对象都具备其自身属性,如一个人,其属性包括高矮、胖瘦、性别、年龄等。然而具有这些属性的人会执行哪些动作也是一个值得探讨的部分,这个人可以哭泣、微笑、说话、行走,这些是这个人具备的行为(动态部分),人类通过探讨对象的属性和观察对象的行为了解对象。
6.1.2 类
类就是同一类事物的统称,如果将现实世界中的一个事物抽象成对象,类就是这类对象的统称,如鸟类、家禽类、人类等。类是构造对象时所依赖的的规范,如一只鸟具有一对翅膀,它可以用这对翅膀飞行,而基本上所有的鸟都具有翅膀这个特性和和飞行的技能,这样具有相同特性和行为的一类事物就称为类,类的思想就是这样产生的。类是封装对象的属性和行为载体,具有相同属性和行为的一类实体被称为类。
6.1.3面向对象程序设计具有以下特点:
封装性。继承性。多态性。
1.封装
封装是面向对象编程的核心思想。将对象的属性和行为封装起来,其载体就是类,类通常对客户隐藏其实现细节,这就是封装的思想。例如,用户使用计算机时,只需要使用手指敲击键盘就可以实现一些功能,无须知道计算机内部是如何工作的,即使可能知道计算机的工作原理,但在使用计算机时也并不完全依赖于计算机工作原理这些细节。
采用封装的思想保证了类内部数据结构的完整性,应用该类的用户不能轻易地直接操作此数据结构,只能执行类允许公开的数据。这样就避免了外部操作对内部数据的影响,提高了程序的可维护性。
2.继承
继承性主要利用特定对象之间的共有属性。
3.多态
将父类对象应用于子类的特征就是多态,多态的实现并不依赖具体类,而且抽象类和接口。
6.2 类与对象
6.2.1 成员变量
在Java中对象的属性也称为成员变量,成员变量的定义与普通变量的定义一样。
语法如下:
数据类型 变量名称[=值];
其中,[= 值]表示可选内容,即定义变量时可以为其赋值,也可以不为其赋值。
代码如下:
public class Bird {
String wing; // 翅膀
String claw; // 爪子
String beak; //喙
String feather; // 羽毛
}
6.2.2成员方法
1.成员方法的定义
定义成员方法的语法格式如下:
[权限修饰符]【返回值类型]方法名( [参数类型参数名 ] ) [throws异常类型]{
…//方法体
return 返回值;
}
其中,“权限修饰符”可以是private、public、protected中的任一个,也可以不写,主要用来控制方法的访问权限,关于权限修饰符将在下一章中详细讲解;“返回值类型”指定方法返回数据的类型,可以是任何类型,如果方法不需要返回值,则使用 void关键字;一个成员方法既可以有参数,
如下: 也可以没有参数,参数可以是对象也可以是基本数据类型的变量
代码如下:
public void showGoods() {
System.out.println("库存商品名称:");
System.out.println(FullName);
}
2.成员方法的参数
调用方法时可以给该方法传递一个或多个值,传给方法的值叫做实参,在方法内部,接收实参的变量叫做形参,形参的声明语法与变量的声明语法一样。形参只在方法内部有效。Java 中方法的参数主要有3种,分别为值参数、引用参数和不定长参数.
(1)值参数
值参数表明实参与形参之间按值传递,当使用值参数的方法被调用时,编译器为形参分配存储单元,然后将对应的实参的值复制到形参中,由于是值类型的传递方式,所以,在方法中对值类型的形参的修改并不会影响实参。
代码如下:
public class Can {
private int add(int x,int y){ //计算两个数的和
x=x+y;//对x进行加y操作
return x;//返回x
}
public static void main(String[] args) {//主方法
Can book=new Can();//创建Book对象
int x=30;//定义实参变量x
int y=40;//定义实参变量y
System.out.println("运行结果:"+book.add(x,y));//输出运行结果
System.out.println("实参x的值:"+x);//输出实参x的值
}
}
运行结果为:
(2)引用参数
如果在给方法传递参数时,参数的类型是数组或者其他引用类型,那么,在方法中对参数的修改会反映到原有的数组或者甘他引用米刑上.这种类型的方法参数,我们称之为引用参数。
代码如下:
zpublic class RefTest {//类名
public static void main(String[] args) { //主方法
RefTest refTest=new RefTest(); //创建RefTest对象
int[]i={0,1,2}; //定义一维数组,作为方法的实参
System.out.print("原始数据:"); //输出内容
for(int j=0;j<i.length;j++){/ /遍历数组
System.out.print(i[j]+" "); //输出数组元素
}
refTest.change(i); //调用方法改变数组元素的值
System.out.print("\n修改后的数据:"); //输出信息
for(int j=0;j<i.length;j++){ //遍历数组
System.out.print(i[j]+" "); //输出数组元素
}
}
public void change(int[]i){//给数组赋值的方法
i[0]=100;/ /给数组与元素赋值
i[1]=200; //给数组与元素赋值
i[2]=300; //给数组与元素赋值
}
}
(3)不定长参数
声明方法时,如果有n个相同类型的参数,可以定义为不定长参数,该类型的参数声明如下:
权限修饰符 返回值类型 方法名(参数类型 参数名称)
代码如下:
public class Can {
public static void main(String[] args) { //主方法
Can multi=new Can(); //创建对象
System.out.print("运算结果:"+multi.add(20,30,40,50,60));//输出信息并调用计算总和方法
}
int add(int...x){ //定义add方法,并指定不定长参数的类型为int
int result=0; //定义一个整型变量
for(int i=0;i<x.length;i++){ //遍历数组
result+=x[i]; //将数组中元素的值相加
}
return result; //返回运算结果
}
}
运行结果为:
3.成员方法的使用
代码如下:
public class Can {
public void gaze(String target){ //凝视,目标是参数target
System.out.println("猎豹凝视:"+target); //输出信息
}
public void run(){//奔跑
System.out.println("猎豹开始奔跑"); //输出
}
public boolean catchPrey(String prey){ //捕捉猎物,返回捕捉是否成功
System.out.println("猎豹开始捕捉"+prey); //输出
return true; //返回成功
}
public void eat(String meat){ //吃肉,参数是肉
System.out.println("猎豹吃"+meat); //输出
}
public void sleep(){ //睡觉
System.out.println("猎豹睡觉"); //输出
}
public static void main(String[]args){ //主方法
Can liebao=new Can(); //在Leopard创建一个对象
liebao.gaze("羚羊"); //调用gaze方法
liebao.run(); //调用run()方法
liebao.catchPrey("羚羊"); //调用catchPrey方法
liebao.sleep(); //调用sleep方法
}
}
运行结果为:
6.2.3构造方法
在类中除了成员方法之外,还存在一种特殊类型的方法,那就是构造方法。构造方法是一个与类同名的方法,对象的创建就是通过构造方法完成的。每当类实例化一个对象时,类都会自动调用构造方法。
构造方法的特点如下:
(1)构造方法没有返回类型,也不能定义为 void.
(2)构造方法的名称要与本类的名称相同。
3)构造方法的主要作用是完成对象的初始化工作,它能把定义对象的参数传给对象成员
在定义构造方法时,构造方法没有返回值,但这与普通没有返回值的方法不同,普通没有返回值的方法使 public void methodEx()这种形式进行定义,但构造方法并不需要使用 void关键字进行修饰。
构造方法的定义语法如下
class Book {
public Book() { //构造方法
}
Public:构造方法修饰符。
Book:构造方法的名称。
在构造方法中可以为成员变量赋值,这样当实例化一个本类的对象时,相应的成员变量也将始化。如果类中没有明确定义构造方法,则编译器会自动创建一个不带参数的默认构造方法。
除此之外,在类中定义构造方法时,还可以为其添加一个或者多个参数,即有参数构造方法,
语法如下:
class Book{
public Book(int args) { //有参数构造方法
//对成员变量进行初始化
}
}
public:构造方法修饰符
Book:构造方法的名称。
args:构造方法的参数,可以是多个参数。注意:
如果在类中定义的构造方法都是有参构造方法,则编译器不会为类自动生成一个默认的无参构造方法,当试调用无参构造方法实例化一个对象时,编译器会报错。所以只有在类中没有定义任何构造方法时,编译器才在该类中自动创建一个不带参数的构造方法。
构造方法除了可以用public修饰以外,还可以用private修饰,即私有的构造方法,私有构造法无法使用new创建对象,这时需要使用静态方法生成类的对象。
代码如下:
public class Can {
private Can()
{ //私有构造方法
} //静态公开方法,向图书馆借书
static public Can libraryBorrow()
{ //创建静态方法,返回本类实例对象
System.out.println("通过调用静态方法创建对象"); //输出信息
return new Can(); //返回本类实例对象
}
public static void main(String[] args) { //主方法
Can book=Can.libraryBorrow(); //创建一个书的对象,不是new实例化的,而是通过方法从图书馆借来的
}
}
运行结果为:
6.2.4局部变量
如果在成员方法内定义一个变量,那么这个变量被称为局部变量。
局部变量在方法被执行时创建,在方法执行结束时被销息段。局部变量在使用时必须进行赋值操作或被初始化,否则会出现编译错误。
代码如下:
public String getName(){ //定义一个getName()方法
int id=0; //局部变量
setName("java"); //调用类中其他方法
return id+this.name; //设置方法返回值
6.2.6 对象的创建
对象可以认为是在一类事物中抽象出某一个特例,可以通过特例来处理这类事物出现的问题。在Java语言中通过new操作符创建对象。每实例化一个对象就会自动调用一次构造方法,实质上这个过程就是创建对象的过准确地说,可以在Java语言中使用new操作符调用构造方法创建对象。
语法如下:
Test test=new Test();
Test test=new Test("a");
Test:类名。
test:创建 Test类对象。
new:创建对象操作符。
a:构造方法的参数。
est对象被创建出来时,就是一个对象的引用,这个引用在内存中为对象分配了存储空间,它可以在构造方法中初始化成员变量,当创建对象时,自动调用构造方法,也就是Java 语言中初始化与创建是被捆绑在一起的。
代码如下:
public class Can {
public Can()
{ //构造方法
System.out.println("创建对象"); //输出信息
}
public static void main(String[] args) { //输出信息
new Can();//创建对象
}
}
运行结果为:
6.2.7 访问对象的属性和行为
用户使用new操作符创建一个对象后,可以使用 “对象.类成员”来获取对象的属性和行为。对象的属性和行为在类中是通过类成员变量和成员方法的形式来表示的,所以当对象获取类成员时,也相应地获取了对象的属性和行为.
代码如下:
public class Can {
int i=47; // 定义一个成员变量
public void call(){ //定义成员方法
System.out.println("调用call()方法"); //输出信息
for(i=0;i<3;i++){ //使用for循环输出0到2
System.out.println(i+" "); //输出信息
if(i==2){ //判断i是否等于2
System.out.println("\n");//换行
}
}
}
public static void main(String[] args) {//主方法
Can t1=new Can(); //创建一个对象
Can t2=new Can(); //创建一个对象
t2.i=60; //将类成员变量赋值为60
System.out.println("第一个实例对象调用变量i的结果:"+t1.i); //输出
t1.call(); //使用第一个对象调用类成员方法
System.out.println("第二个实例对象调用变量i的结果:"+t2.i); //输出信息
t2.call(); //使用第二个对象调用类成员方法
}
}
运行结果为:
6.2.8对象的销毁
每个对象都有生命的周期,当对象的生命周期结束时,分配给该对象的内存地址会被回收。在其它语言中需要手动回收废弃的对象,但在Java拥有一套完整的垃圾回收机制,用户不必担心废弃的对象占用内存,垃圾回收站将回收无用的但占用内存的资源。何种对象会被Java虚拟机视为垃圾。
(1)对象引用超出其作用范围,这个对象将被视为垃圾
(2)将对象赋值为null。
finalize()方法可进行垃圾回收但不一定会发生
System.gc()方法强制启动垃圾回收器。
6.2.9 this关键字
this引用的就是本类的一个对象,在局部变量或方法参数覆盖了成员变量时如果省略this关键字直接写成name=name,那只是把参数name赋值给参数变量本身而已员变量name的值没有改变,因为参数name在方法的作用域中覆盖了成员变量name,this 除了可以调用成员变量或成员方法之外,还可以作为方法的返回值。
代码如下:
public class Can { //创建Can类
String name="abc"; //定义一个成员变量
public void showName(String name)
{ //定义一个showName类并从传入一个参数
System.out.println(name); //输出
}
public static void main(String[] args) {
Can book=new Can(); //在Book2类定义一个对象
book.showName("123"); //调用showName方法
}
}
运行结果为:
6.3 static关键字
由static修饰的变量、常量和方法被称作静态变量、静态常量和静态方法,也被称为类的静态成员。静态成员是属于类所有的,区别于个别对象。
6.3.1 静态变量
很多时候,不同的类之间需要对同一个变量进行操作,比如一个水池,同时打开入水口和出水1,进水和出水这两个动作会同时影响到池中的水量,此时池中的水量就可以认为是一个共享的今量。在 Java 程中,把共享的变量用static修饰,该变量就是静态变量。
可以在本类或其他类使用类名和“.”运算符调用静态变量。
语法如下:
类名.静态类成员
代码如下:
public class Can { //创建Can类
static public int water=0;//定义一个静态的公开的整型变量并赋值
public void outlet(){//放水,一次放出2个单位
if(water>=2){
water=water-2;//水量减2
}else{
water=0;//水量为0
}
}
public void inlet(){//注水,一次注入3个单位
water=water+3;//水量加3
}
public static void main(String[] args) {
Can out=new Can();//在Pool类里创建一个对象
Can in=new Can();//在Pool类里创建一个对象
System.out.println("水池的水量:"+Can.water);//输出信息
System.out.println("水池注水两次。");//输出信息
in.inlet();//调用注水方法
in.inlet();//调用注水方法
System.out.println("水池的水量:"+Can.water);//输出信息
System.out.println("水池放水一次");//输出信息
out.outlet();//调用防水方法
System.out.println("水池的水量:"+Can.water);//输出信息
}
}
运行结果为:
6.3.2 静态常量
有时,在处理问题时会需要两个类共享一个数据常量。例如,在球类中使用PI这个常量,可能除了本类需要这个常量之外,在另外一个圆类中也需要使用这个常量。这时没有必要在两个类中同时创建PI这个常量,因为这样系统会将这两个不在同一个类中的常量分配到不同的内存空间中,浪费了系统资源。为了解决这个问题,可以将这个常量设置为静态的。
代码如下:
public class Can { //创建Can类
final static double PI=3.1415926;//创建静态常量Π
public static void main(String[] args) {
double radius=3.0;//半径
double area=Can.PI*radius*radius;//计算面积
double volume=4/3*Can.PI*radius*radius*radius;//计算体积
Circular yuan=new Circular(radius,area);//在类里创建一个对象
Spherical qiu=new Spherical(radius,volume);//在类里创建一个对象
}
}
class Circular{
double radius;//半径
double area;//面积
public Circular(double radius,double area){
this.radius=radius;//调用变量并初始化
this.area=area;//调用变量并初始化
System.out.println("圆的半径:"+radius+",圆的面积:"+area);//输出信息
}
}
class Spherical {
double radius;//半径
double volume;//体积
public Spherical(double radius,double volume){
this.radius=radius;//调用变量并初始化
this.volume=volume;//调用变量并初始化
System.out.println("圆的半径:"+radius+",圆的体积:"+volume);//输出信息
}
}
运行结果为:
6.3.3 静态方法
如果想要使用类中的成员方法,需要先将这个类进行实例化,但有些时候不想或者无法创建类
的对象时,还要调用类中的方法才能够完成业务逻辑,此时就可以使用静态方法。调用类的静态方法,无需创建类的对象。
语法如下:
类名.静态方法();
代码如下:
public class StaticMethod {
static public void show(){
System.out.println("静态方法无需实例化就可以调用");//输出信息
}
public static void main(String[] args) {
StaticMethod.show();//使用类名调用静态方法
}
}
运行结果为:
6.3.4静态代码块
在类中除成员方法之外,用static修饰代码区域可以和你之为静态代码块。定义一块静态代码块可以完成类的初始化操作,在类声明时就会运行。
语法如下:
public class StaticTest{
stati{
//此处编辑执行语句
}
}
代码如下:
public class StaticTest {
static String name;//定义静态变量
static{
System.out.println(name+"静态代码块");//输出
}
{
System.out.println(name+"非静态代码块");//输出
}
public StaticTest(String a){
name=a;
System.out.println(name+"构造方法");//输出
}
public void method(){
System.out.println(name+"成员方法");//输出
}
public static void main(String[] args) {
StaticTest s1;
StaticTest s2=new StaticTest("s2");//new的时候才会运行构造方法
StaticTest s3=new StaticTest("s3");
s3.method();//只有调用的时候才会运行
}
}
运行结果为:
6.4 类的主方法
主方法是类的入口点,它定义了程序从何处开始;主方法提供对程序流向的控制,Java编译装通过主方法来执行程序。主方法的语法如下:
public static void main(String[] args){
//方法体
}
在主方法的定义中可以看到主方法具有以下特性。
(1)主方法是静态的,所以如要直接在主方法中调用其他方法,则该方法必须也是静态的。
(2)主方法没有返回值。
(3)主方法的形参为数组。其中 args[0]~args[n]分别代表程序的第一个参数到第n+1个参数,可以使用args.length获取参数的个数。
代码如下:
public class TestMain {
public static void main(String[] args) {//定义主方法
for(int i=0;i<args.length;i++){//根据参数个数做循环操作
System.out.println(args[i]);//循环打印参数内容
}
}
}
运行结果为: