初学Java入门--类与对象

初学|对象

4.2 类与对象
4.2.1 类
在面向对象的语言中,类是个很重要的概念。面向对象的方法把所有的处理对象进行归类。具有相同性质的对象归为一类。例如学校里有很多学生,每个学生都是一个对象,而“学生”则是一个类,它包含了所有在学校学习的人。
在Java语言里,对象是一组描述对象的属性和操作方法的集合,其中属性表明对象的状态,方法表明对象的行为。类是对象的定义。一个对象具有哪些属性和方法,由类来决定。从编程角度看,类是一种复合数据类型,它封装了一组变量和方法(函数)。
声明一个类的一般形式如下所示:
修饰符 class 类名{
//类体
}
其中修饰符说明了类的属性,可以是public、abstract、final等。这些修饰符的含意将会在后继的章节中介绍。类体就是类的成员变量和成员方法的声明。修饰符和类体的声明都是可以选的。下面是一个“人”的类的声明,虽然类体是空的:
class Person{
}

4.2.2 对象
对象与类是不同但是又紧密相联的概念。类是对象的定义,对象由类来生成。类与对象的关系好比铸造车间里模具与产品的关系。模具只有一个,但是用这个模具可以浇铸出很多成型的产品出来,模具的形状决定了浇铸出来的产品的外形。在Java语言里用new关键字来生成对象,通常的格式为:
类名 对象名=new 类名([参数]);
这里的对象名可以是任意合法的Java标识符。new关键字后带小括号的类名称为构造方法(函数)。默认的、也是最简单的构造方法是不带参数的,也可以自定义不同形式的构造方法以供不时之需。下例利用刚才的Person类来生成两个Person对象Mike和John:
Person Mike=new Person();
Person John=new Person();
用new Person()生成一个对象时不仅分配了内存空间还进行了一些初始化的工作,对象所包含的不仅只是各个属性名了,而是属性的具体值。如果没有给属性赋值,虚拟机会自动给它们赋于相应数据类型默认的初值。生成一个对象的过程也称为实例化,所以一个对象就是一个实例。Mike和John是对象名,对象名是用来引用对象的,对象里的变量和方法可以通过对象名来引用,所以对象名也称为引用(Reference)。引用类似于C/C++中指针的概念,与指针不同,引用不是直接指向对象所在的内存位置,但是它包含了内存地址的信息。Java中并没有指针,以指针进行内存操作常造成不预知的错误,还可能破坏安全性,也正是因为如此,Java被认为是“安全的”编程语言。上例中生成的对象和引用如下图所示:

图4-1 引用与对象
在某些特殊的情况下,可能生成实例但不需要引用,那可以直接用new来实例化。如下所示:
new Person();
new Person();
上面两行程序生成两个Person对象,但是每次生成的对象分别占用不同的内存空间,改变其中一个对象的状态不会影响其它对象的状态。就象每次用模具倒出一个毛坯一样, 尽管两个毛坯看起来很象,但它们绝对是两个不同的毛坯。
4.2.3 成员变量
在面向对象的思想中,通常用属性来描述对象的特征。在编程语言里,这一组从属于某类对象的属性是用变量来表示的,例如前文提到用来表示人的特征的身高、体重、姓名等等,就可以分别用不同类型的变量:double型的height、float型weight、String型的name来表示。这些属于类的变量,称为类的成员变量。
声明成员变量的一般形式如下:
修饰符 数据类型 成员变量名;
其中修饰符说明了类的成员变量的属性,可以是public、protected、private、static、transient、final、volatile等等。成员变量的类型可以是Java内置的或者是自定义的复杂数据类型,包括简单类型、类、接口、数组。例如,描述一个人有一座房产可以用House类型的变量house来表示,这里的House是用户自定义的类(复杂数据类型)。调用成员变量的一般形式是:
实例名.成员变量名
下面是一个“人”的类的声明,类名是Person。描述“人”的成员变量有:height、weight、sex、name、age等,还有房产house的声明。
【例4-1】
class Person{
double height;
float weight;
char sex;
String name;
int age;
House house;
}
class House{}
public class E4_1{
public static void main(String args[]){
Person p_Bill=new Person();
p_Bill.age=26;
p_Bill.height=180;
p_Bill.weight=145;
p_Bill.sex='m';
p_Bill.name="Bill Gates";
p_Bill.house=new House();
}
}
Person类有6个成员变量,其中5个是简单数据类型,1个是复合数据类型House。在类E4_1的main函数里生成了一个引用名为p_Bill的对象。通过这个p_Bill这个引用可以访问到这个人的年龄、身高、体重等属性。
上例的程序可以在全部放在一个源文件中,源文件名为必须为E4_1。Java的一个源文件允许多个类的存在,但是文件名必须和public类一致,一个源文件中只也能有一个public类。
成员变量不需要显式初始化可以直接使用。其实,它们还是有被初始化过的,称为隐式的初始化。没有显式初始化的成员变量是在为对象分配存储空间时自动被初始化,各种类型的变量被赋于默认的初始化值,如下所示:
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'(null)
boolean false
所有复合数据类型 null
下例打印了隐式初始化的Person类成员变量。
【例4-2】
class Person{
double height;
float weight;
char sex;
String name;
int age;
House house;
}
class House{}
public class E4_2{
public static void main(String args[]){
Person p_Bill=new Person();
System.out.println(p_Bill.age);
System.out.println(p_Bill.height);
System.out.println(p_Bill.weight);
System.out.println(p_Bill.sex);
System.out.println(p_Bill.name);
System.out.println(p_Bill.house);
}
}
得到的结果是:
0
0.0
0.0

null
null
4.2.4 成员方法
对象的方法可以用来改变对象的属性,或者用来接收来自其它对象的信息以及向其它对象发送消息。从编程角度看,类是一组Java语句的集合。这里说的方法和面向过程语言C、Pascal等中的函数其实是一个概念。但是在象Java这样的纯面向对象的语言里,“函数”只能包含在类里面,而且是用来描述类的行为的,一般称为方法。
定义方法的一般形式如下所示:
修饰符 返回类型 方法名([参数类型 参数名,…])[throws 异常列表] {
//方法体
}
方括号中为可选项。修饰符可以是public、protected、private、static、final、abstract、native、synchronized等。返回类型既可以是简单数据类型,也可以是复合数据类型(数组、类或接口)。如果方法没有返回值,也必须在返回类型处用void声明。或者可以说,这个方法返回void类型。例如:void setHeight(){},但是,一旦方法声明某种返回类型,方法体中必须用return关键字返回和声明类型一致的数据。throws用来声明抛出异常,见第七章异常处理与断言。
调用对象方法的一般格式是:
引用名.方法名([参数列表]);
下例是一个person类比较完整的定义:
【例4-3】
public class E4_3{
public static void main(String args[]){
Person p=new Person();
p.setAge(30);
System.out.println(p.getAge());
}
}
class Person{
private double height;
private float weight;
private char sex;
private String name;
private int age;
public void setAge(int age) {
this.age = age;
}
public void setHeight(double height) {
this.height = height;
}
public void setName(String name) {
this.name = name;
}
public void setSex(char sex) {
this.sex = sex;
}
public void setWeight(float weight) {
this.weight = weight;
}
public int getAge() {
return age;
}
public float getWeight() {
return weight;
}
public char getSex() {
return sex;
}
public String getName() {
return name;
}
public double getHeight() {
return height;
}
}
在上例里,每个成员变量都有两个方法与之对应,分别是set和get方法。set方法用来改变成员变量的值,返回类型是void,而get方法用来获取成员变量的值,它们的方法体中都用return来返回与方法声明时一致的数据类型。该例中的this关键字用来引用当前对象。
方法的用法和面向过程语言中的函数的用法是一样的。但是,在Java语言里,没有独立于类之外的方法,所有的方法都在类里面,所以一般通过对象名来调用方法。有些静态(static)方法则可以用类名来调用。上例E4_3类的main方法里生成一个名为p的Person对象,通过p这个引用调用setAge()方法设置p的年龄,最后调用getAge()打印p的年龄。
方法体内可以包含所有合法的Java指令。可以声明该方法所用到的局部变量,它的作用域只在该方法内部,当方法调用结束时,局部变量也就失效了。如果方法体内的局部变量名和类的成员变量的名字相同,则类的成员变量被隐藏,也就是失效了,当前有效的是局部变量。
【例4-4】
public class E4_4{
int x=0,y=0,z=0;
void action(int x){
x=11;//参数x
y=12;//类成员变量y
int z=13;//方法内部变量z
System.out.println("在init()方法内部:");
System.out.println("成员变量:"+"x="+this.x+" y="+this.y+" z="+this.z);
System.out.println("局部变量:"+"x="+x+" z="+z);

}
public static void main(String args[]){
E4_4 e=new E4_4();
System.out.println("调用前:");
System.out.println("成员变量:"+"x="+e.x+" y="+e.y+" z="+e.z);
e.action(1);
System.out.println("调用后:");
System.out.println("成员变量:"+"x="+e.x+" y="+e.y+" z="+e.z);

}

}
程序的输出是:
调用前:
成员变量:x=0 y=0 z=0
在init()方法内部:
成员变量:x=0 y=12 z=0
局部变量:x=11 z=13
调用后:
成员变量:x=0 y=12 z=0
在上例的action方法里,参数x和新定义的变量z作用范围都只在action方法内部,因为它们和类成员变量x,z同名,所以类成员变量被覆盖。在action方法内部使用x和z都将调用参数x和局部变量z,而不是类成员变量。但这不并意味着无法在方法内部调用到成员变量。在上例中,我们用到了this。this代表调用该方法的当前对象(实例)。所以可以用this来调用该对象所有的成员变量和成员方法。
方法可以带多个参数,用逗号分隔开。对于简单数据类型,Java实现的是值传递, 方法接收参数的值,但不改变实参的值。对于复合数据类型,Java实现的是引用的传递,可以改变原参数的值。下例说明了简单数据类型与引用数据类型的区别。
【例4-5】
public class E4_5{
int i=0;
public void primary(int x){
x=3;
}
public void complex(E4_5 e2){
e2.i=3;
}
public static void main(String args[]){
E4_5 e=new E4_5();
System.out.println("调用primary前:e="+e.i);
e.primary(0);
System.out.println("调用primary后:e="+e.i);

System.out.println("调用complex前:e="+e.i);
e.complex(e);
System.out.println("调用complex后:e="+e.i);
}
}
上例的输出是:
调用primary前:e=0
调用primary后:e=0
调用complex前:e=0
调用complex后:e=3
我们在类E4_4中定义了两个方法:primary(int x)和 complex(E4_4 e)。primary方法接收的参数是int类型的值,方法内部对接收到值赋于新值3,但由于该方法接收的是简单数据类型,所以方法内值的修改不会影响方法外成员变量的值。而complex接收的参数是引用类型。这时,引用e和引用e2指向同一个对象,如下图所示:

图4-2 e和e2指向同一个对象
既然它们代表同一个对象,e2对该对象的修改自然就影响了引用e。

时间: 2024-10-28 12:31:54

初学Java入门--类与对象的相关文章

java private-java 一个类的对象访问私有属性的问题

问题描述 java 一个类的对象访问私有属性的问题 public class ModifierTest1 { public static void main( String[] args ) { A a = new A(); //System.out.println(a.s); a.f(); } } class A { private int i; private String s; public A() { i = 123; s = "hello"; } public void f(

java 某个类的几个对象,这些对象调用类中一个函数,是各自拥有自己的函数代码还是使用同一段代码?

问题描述 1.java 某个类的几个对象,这些对象调用类中一个函数(普通的函数),是各自拥有自己的函数代码还是使用同一段代码?2.java 继承中,子类从父类得到一些普通函数,这些函数的代码,是子类自己独自拥有一份还是和父类使用同一段函数代码.3.第一次发帖,积分什么的不会搞,貌似自己也没有积分,呵呵,大家包涵! 解决方案 引用1.java 某个类的几个对象,这些对象调用类中一个函数(普通的函数),是各自拥有自己的函数代码还是使用同一段代码?这几个对象调用的当然是同一段代码了.jvm中有一个ja

抽象方法 对象-初学Java 有个地方看不懂

问题描述 初学Java 有个地方看不懂 /* 汽车类/ public abstract class MotoVehicle { / 将成员变量封装隐藏起来,private 权限只在类内显示 / private String no;//车牌号 private String brand;//品牌 private int perRend;//日租金 public abstract float calRent(int days);//抽象方法 用来计算租金 public abstract void le

对象-初学Java,一些事件处理问题,help!!!!!!

问题描述 初学Java,一些事件处理问题,help!!!!!! **出现以下错误: 1.可以改变对话框中字体大小,无法改变字体种类. 2.且无法将改变的效果传递到主窗口. 3.对话框setModel的值为true,还是能点到主窗口 4.可以通过下拉框可改变标签字体大小,但是为什么我改变了字体大小之后,我点那个字体种类的下拉框没有出现下拉列表呢?是不是两个下拉列表有冲突呢? ** 以下代码分别在4个java文件中 java程序,?编写一个JDialog的子类FontDialog,该类为FontFa

怎么理解java中的,对象,方法,类。

问题描述 我是一名初学java的新人,刚开始看书,对于java中的对象,方法,类总是不能正确的理解,哪位大虾可以帮我解释一下,用通俗点的语言.谢谢! 问题补充:fire_wang 写道 解决方案 类.对象.方法这些都属于面向对象语言共有的,java.c++对这个的理解都是类似的.举个简单的例子,类就是指一类东西,比如灯泡.java里你可以自己定义这个类,类里包含方法和属性,比如灯泡有亮度属性,寿命属性等等,方法有开灯.关灯等等然后对象就是指类的具体的实体,比如某一个灯泡.java里定义一个类pu

JAVA编程中的类和对象

1:初学JAVA,都知道JAVA是面向对象的编程.笔者这节开始说说类和对象.(实例仅供参考,如若复制粘贴记得修改包名和类名,避免出错) 学习JAVA的快捷键,Alt+/代码补全功能,其实此快捷键启动了Eclipse代码辅助菜单,Shift+Ctrl+o快捷键导入包 Ctrl+F可以快速查找API,中文版API,百度云链接:http://pan.baidu.com/s/1slQWhCL 密码:cfxo 首先 对象的创建:类名  对象名=new 类名();也许大多数学习java的都会写,但是理解方面

java中有类的子类一说,那有对象的子对象一说吗?

问题描述 java中有类的子类一说,那有对象的子对象一说吗? java中有类的子类一说,那有对象的子对象一说吗?新手提问莫见笑. 解决方案 类的子类专业点说叫继承,对象的子对象你可以理解成方法的重写或重载等. 解决方案二: 那是不是类中有内部类就可以呢?

JAVA类和对象的使用技巧

刚在网上看到一篇关于Java性能调优的帖子,很是帮助,自己也用了十多年JAVA了,有些感同身受,这里 引用那帖子结合自己的感受来谈下 技巧1:尽量少用new来创建对象 因为用new来创建对象的实例时 ,构造函数链上的所有构造函数都会被依次调用,导致效率很低.其实我们可以用一些小技巧,比如复用已有 对象.比如说,一个类如果实现了Cloneable接口的话,可以调用这个类的对象的clone()方法来创建一个新 对象,这样的对象不会调用任何类的构造函数.所以,这样生成新对象的速度比调用任何类的构造函数

解析Java类和对象的初始化过程

本文主要对类和对象初始化全过程进行分析,通过一个实际问题引入,将源代码转换成 JVM 字节码后,对 JVM 执行过程的关键点进行全面解析,并在文中穿插入了相关 JVM 规范和 JVM 的部分内部理论知识,以理论与实际结合的方式介绍对象初始化和类初始化之间的协作以及可能存在的冲突问题. 问题引入 近日我在调试一个枚举类型的解析器程序,该解析器是将数据库内一万多条枚举代码装载到缓存中,为了实现快速定位枚举代码和具体枚举类别的所有枚举元素,该类在装载枚举代码的同时对其采取两种策略建立内存索引.由于该类