目录
类和对象概述
类和对象的操作:
类的声明
对象的创建和使用
声明对象变量
创建对象
构造方法和对象的初始化
构造方法相关特点:
例子
对象销毁
类的封装
访问权限
类成员
类成员方法
从程序设计的角度,事物的属性可以用变量描述,行为用方法描述。
类是定义属性和行为的模板,对象是类的实例,对象与类的关系就像变量和数据类型的关系一样。
对象:事物存在的实体
类:类是封装对象的属性和行为的载体,反过来说具有相同属性和行为的一类实体被称为类。
封装:将对象的属性和行为封装起来,而将对象的属性和行为封装起来的载体就是类
继承:以现有的类为基础,复制它,然后通过添加和修改这个副本来创建新类
多态:一个接口(可以是接口、抽象类或基类)可以被不同的子类实现,或者一个方法可以被不同类型的对象调用,而产生不同的行为
总结:对象是表示现实世界中某个具体的事物;类是对对象的抽象描述。
[访问修饰符] class 类名 [extends 父类名] [implements 接口名列表] {
成员变量(字段)
[访问修饰符] 数据类型 成员变量名;
构造方法
[访问修饰符] 类名([参数列表]) {
构造方法体
}
方法(成员函数)
[访问修饰符] 返回类型 方法名([参数列表]) {
方法体
}
其他成员(如内部类、初始化块等)
}
各个部分的解释如下:
访问修饰符:可选的部分,用于控制类、方法或成员变量的可见性。常见的访问修饰符有 public
、protected
、private
和默认(没有显式指定)。
class 关键字:用于声明一个新的类。
类名:遵循Java的命名规则,通常是首字母大写的驼峰命名法。
extends 父类名:可选的部分,用于表示该类继承自另一个已存在的类。如果类没有父类,则可以省略这部分。
implements 接口名列表:可选的部分,用于表示该类实现了一组接口。接口名之间用逗号分隔。
成员变量(字段):类中定义的变量,用于存储对象的状态信息。
构造方法:特殊的方法,用于初始化新创建的对象。构造方法的名称必须与类名相同,并且没有返回类型。
方法(成员函数):类中定义的行为,用于描述对象可以执行的操作。方法包含一个返回类型、一个方法名和一个参数列表。
e.g一个简单的类声明示例
public class Animal {
private String name;
private int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
首先,需要声明一个对象变量,该变量的类型是类名。这并不创建对象,只是为对象分配了一个引用。
ClassName objectName;
使用 new
关键字和类的构造方法来创建一个新的对象实例。构造方法用于初始化新创建的对象。[修饰符] 类名 对象名=new 类名(实参列表);
或
[修饰符] 类名 对象名;
对象名=new 类名(实参列表);
objectName = new ClassName([构造方法参数列表]);
注意: 类属于复合数据类型,因此,在声明对象时,系统并没有为对象分配空间,用户需要应用new完成分配空间的任务。
访问对象的成员(字段和方法)/对象的引用
创建对象后,可以使用点运算符 .
来访问对象的成员变量(字段)和调用对象的方法。
引用成员变量:对象名.成员变量名
引用方法:对象名.方法名(参数列表)
// 访问对象的字段
objectName.fieldName;
// 调用对象的方法
objectName.methodName([方法参数列表]);
e.g定义一个表示圆形的类,能够计算圆面积和周长
class Circle1
{
float r;
final double PI=3.14159;
public double area() //计算面积
{
return PI*r*r;
}
public void setR(float x) //设置半径
{
r=x;
}
public double perimeter() //计算周长
{
return 2*PI*r;
}
public static void main(String args[])
{
double x,y;
Circle1 cir=new Circle1(); //创建Circle1类的对象cir
cir.setR(12.35f); //引用cir对象的setR()方法
x=cir.area(); //引用cir对象的area()方法
y=cir.perimeter(); //引用cir对象的perimeter()方法
System.out.println("圆面积="+x+"\n圆周长="+y);
}
}
类中有一种特殊的成员方法,其方法名与类名相同,称为构造方法。
构造方法是Java中一种特殊的方法,用于初始化新创建的对象。
当使用new运算符实例化一个对象时,系统为对象创建内存区域并自动调用构造方法初始化成员变量
1.构造方法名与类名相同;
2.构造方法没有返回值,也没有void;
3.构造方法的主要作用是对对象初始化。
对象的生命周期: 在Java中,当我们使用 new
关键字创建一个对象时,这个对象的生命周期就开始了。新创建的对象需要一些初始状态或值,以便在程序中正确地使用和操作。
初始化过程:初始化是设置对象状态的过程,包括为对象的成员变量赋初始值、执行必要的设置操作等。构造方法就是在这个过程中起主要作用的。
自动调用:当我们创建一个对象时,相应的构造方法会被自动调用。这意味着,只要我们定义了一个构造方法,它就会在每次创建该类的新对象时被隐式调用。
定制初始化:通过构造方法,我们可以根据需要为新创建的对象提供特定的初始状态。这使得每个对象在创建时都能够处于一致和有效的状态,有助于确保程序的正确性和稳定性。
4.构造方法不能显式地直接调用;
5.一个类中可以定义多个构造方法,但各构造方法的参数表不能相同,即各构造方法的参数个数不同或参数类型不同;
解释:因为构造方法沿用的是类名,是要通过各构造方法的不同参数来区分不同的构造方法
6.如果没有声明构造方法,系统为该类生成一个无参数的默认构造方法。
解释:如果一个类中没有显式地定义任何构造方法,那么Java编译器会自动为该类生成一个默认的无参数构造方法。这个默认构造方法的作用是提供一种无需任何参数即可创建对象的方式。
默认构造方法的行为:默认构造方法通常是一个空的方法体,不执行任何特定的初始化操作。这意味着,当使用默认构造方法创建对象时,类的成员变量将被赋予它们各自的默认值(例如,基本类型的默认值为0或false,对象引用类型的默认值为null)。
自动生成的机制:当编译器在类中找不到任何显式定义的构造方法时,它会自动插入一个无参数的默认构造方法。这个过程是编译器在编译期间完成的,程序员无需手动编写代码来实现默认构造方法。
影响继承和子类:如果一个父类没有显式定义任何构造方法,并且子类也没有定义任何构造方法,那么子类也会继承父类的默认构造方法。然而,如果父类提供了至少一个构造方法(无论是否有参数),那么子类必须提供至少一个构造方法,否则编译器不会为子类生成默认构造方法。
e.g实例1(单个构造方法)
class Student
{
String name; //成员变量
String address; //成员变量
int score; //成员变量
public void setMessage(String x1,String x2, int x3) //成员方法
{
name=x1;
address=x2;
score=x3;
}
public static void main(String args[])
{
Student s1=new Student(); //创建Student类对象s1
System.out.println(s1.name+" "+s1.address+"
"+s1.score);
//输出缺省构造方法的初始化结果
s1.setMessage("张三","西安市兴庆路1号",75);
// 调用成员方法给成员变量赋值
System.out.println(s1.name+" "+s1.address+"
"+s1.score);
}
}
e.g实例2(多个构造方法)
class Time1
{
private int hour; //0-23
private int minute; //0-59
private int second; //0-59
public Time1()
{ setTime (0,0,0); }
public Time1(int hh)
{ setTime (hh,0,0); }
public Time1 (int hh, int mm)
{ setTime (hh,mm,0); }
public Time1(int hh, int mm, int ss)
{ setTime (hh,mm,ss); }
public void setTime (int hh, int mm, int ss)
{
hour = ((hh >= 0 && hh < 24) ? hh : 0);
minute = ((mm >= 0 && mm < 60) ? mm : 0);
second = ((ss >= 0 && ss < 60) ? ss : 0);
}
public String toString()
{
return (hour + ":" +(minute < 10 ? "0" : "") + minute + ":" +
(second < 10 ? "0" : "") + second);
}
}
public class MyTime1
{
private static Time1 t0, t1, t2, t3;
public static void main(String args[])
{
t0=new Time1();
t1=new Time1(11);
t2=new Time1(22, 22);
t3=new Time1(33, 33, 33);
System.out.println(" t0= " + t0.toString());
System.out.println("t1= " + t1.toString());
System.out.println("t2= " + t2.toString());
System.out.println(“t3= ” + t3.toString());
}
}
通过new运算符实例化对象时,系统为对象分配所需的存储空间,存放其属性值。但内存空间有限,不能存放无限多的对象。为此,Java提供了资源回收机制,自动销毁无用对象,回收其所占用的存储空间。如果需要主动释放对象,或在释放对象时需要执行特定操作,则在类中可以定义finalize()方法。
public void finalize()
{
方法体;
}
将数据和对数据的操作组合起来构成类,类是一个不可分割的独立单位;
类中既要提供与外部联系的接口,同时又要尽可能隐藏类的实现细节
public: public
关键字表示成员(包括类、方法和变量)对所有其他类都是可见的。无论这些类是否在同一包中,都可以直接访问 public
成员。
protected: protected
关键字表示成员对同一包中的其他类以及所有子类都是可见的。这意味着,如果一个类在同一个包中或者是一个子类,那么它可以访问 protected
成员。
默认(无修饰符): 如果没有明确指定访问修饰符,成员的访问权限默认为“包级私有”(package-private)。这意味着该成员只对同一包中的其他类可见,对其他包中的类不可见。
private: private
关键字表示成员只能在其所在的类中访问。这意味着,即使是在同一包中的其他类或子类,也无法访问 private
成员。
有关同一包的解释:指的是源代码中具有相同包声明的类。包(package)是Java中一种用于组织和管理类的命名空间机制。
访问控制 |
本类 |
同一包 中的类 |
其他包 中子类 |
其他包 中的类 |
public |
Ö |
Ö |
Ö |
Ö |
protected |
Ö |
Ö |
Ö |
× |
缺省 |
Ö |
Ö |
× |
× |
private |
Ö |
× |
× |
× |
e.g
class Time
{
private int hour; //0-23
private int minute; //0-59
private int second; //0-59
public Time()
{ setTime(0,0,0); }
public void setTime(int hh, int mm, int ss)
{
hour = ((hh >= 0 && hh <24) ? hh : 0);
minute = ((mm >= 0 && mm < 60) ? mm : 0);
second = ((ss >= 0 && ss < 60) ? ss : 0);
}
public String toString()
{
return (hour + ":" + (minute < 10 ? "0" : "") + minute + ":" +
(second < 10 ? "0" : "") + second );
}
}
public class MyTime2
{
public static void main(String args[])
{
Time time = new Time();
time.hour = 11; //欲将11赋给hour成员变量,但属于非法访问
System.out.println("time" + time.toString());
}
}
类访问权限
声明一个类可使用的权限修饰符只有public和缺省2种 。
虽然一个Java源程序文件中可以包含多个类,但只能有一个类使用public修饰符,该类的名字与源程序文件的名字相同。
当程序中创建多个类时,必须运行包含main()方法的类,否则出错。
类成员变量:在类中声明成员变量时,没有使用static修饰的变量为实例成员变量,使用static修饰的变量为类成员变量
class Student
{
String name; //实例成员变量
String sex; //实例成员变量
static int count=0; //类成员变量
public Student(String m, String s )
{
name=m;
sex=s;
count=count+1;
}
}
当创建对象时,每个对象拥有各自的实例成员变量,各对象的实例成员变量具有不同的值;而系统仅为类成员变量分配一个存储单元,所有对象共享一个类成员变量。
实例成员变量属于对象,只能通过对象引用;类成员变量属于类,既可以通过类名访问,也可以通过对象名访问。
实例成员变量的访问方法为:对象名. 实例成员变量名
类成员变量的访问方法为:对象名.类成员变量名(不鼓励)或 类名.类成员变量名
e.g类成员变量和实例成员变量的对比
class Student1
{
String name; //实例成员变量
String sex; //实例成员变量
static int count=0; //类成员变量
public Student1(String m, String s )
{
name=m;
sex=s;
count=count+1;
}
}
public static void main(String args[])
{
Student1 p1=new Student1("李明","西安市未央区");
Student1 p2=new Student1("张敏", "上海市闽行区");
System.out.println(p1.name+" "+p1.address+" "+p1.count);
Student1.count=Student1.count+1;
System.out.println(p2.name+" "+p2.address+" "+p2.count);
p1.count=p1.count-1;
System.out.println(p2.name+" "+p2.address+" "+p2.count);
}
}
程序运行结果如下:
李明 西安市未央区 2
张敏 上海市闽行区 3
张敏 上海市闽行区 2
在类中声明成员方法时,没有使用static修饰的方法为实例成员方法,使用static修饰的方法为类成员方法
public static double area(double r)
{
return 3.14*r*r;
}
类成员方法中除使用本方法中声明的局部变量外,只可以访问类成员变量,不能访问实例成员变量;实例成员方法中除使用本方法中声明的局部变量外,还可以访问类成员变量及实例成员变量。
class Course
{ String no; //实例成员变量:课程编号
int score; //实例成员变量:成绩
static int sum=0; //类成员变量:总成绩
public Course(String n, int s)
{
no=n;
score=s;
}
public static void summarize(int s) //类方法:统计总成绩
{
sum+=s;
}
}
public class Statistic
{
public static void main(String args[])
{
Course c1,c2;
c1=new Course("210",90);
Course.summarize(90);
System.out.println("sum="+c1.sum);
c2=new Course("300",80);
c2.summarize(80);
System.out.println("sum="+Course.sum);
}
}
程序运行结果如下:
sum=90
sum=170