面向对象程序设计
一. 类和对象
1. 类的定义
-
类定义也称为类的声明,分别是 成员变量 和 成员方法
-
public class Test { private String temp; // 修饰符 类型 成员变量 public void tempMethod(int num){ // 修饰符 返回值类型 成员方法 参数列表、 System.out.println("方法体"); // 方法体 } }
-
class是关键字,表明后定义的是一个类,含有class的这一行称为类头
-
大括号括住的是类体
-
class前的修饰符可以有多个
-
类定义的成员变量 成员方法可以有多个
-
方法体是真正要执行的语句,没有返回值写void
-
参数列表可以含有0个或者多个参数,使用前要声明改参数的类型
-
-
修饰符访问权限
- 否 表示不可访问到
类型 无修饰符 private protected public 同一类 是 是 是 是 同一包中的子类 是 否 是 是 同一包中的非子类 是 否 是 是 不同包中的子类 否 否 是 是 不同包中的非子类 否 否 否 是 -
Java中除了Object之外所有类都有一个且只有一个父类,Object是唯一没有父类的类
-
若没有指明从哪个类派生来的,则从默认的父类Object派生而来
2. 构造方法
-
构造方法是一类特殊的方法
public class Test { private String temp; public Test() { // 无参构造 } public Test(String temp) { // 有参构造 this.temp = temp; } }
- 名字与类名相同
- 无返回值
- 创建对象实例时通过new运算符自动调用
- 可以重载,一个类可以有多个具有不同参数列表的构造方法
-
构造方法作于是用来创建类的实例
-
通常说明为public类 ,不能从父类继承
-
默认的构造方法
- 每个类至少有一个构造方法
- 如果没有定义构造方法,系统会自动生成一个默认构造,参数列表以及方法体均为空
- 一旦手动创建有参构造,一定要加上一个默认构造
-
构造方法重载
-
构造方法中会有重复的代码,或者一个构造方法可能包含另一个构造方法中的全部代码,为了简化代码书写,可以在一个构造方法中引用另一个构造方法
-
使用this关键字来代替本类中的其他构造
public class Test { private String name; private int age; public Test(String n, int a) { //第一个构造方法 name = name; age = a; } public Test(String n) { //第二个构造方法 this(n,20); } public Test() { //第三个构造 this("张三"); } }
- 第三个构造没有任何参数,它调用 this(“张三”); 实际上把控制权转给了第二个构造,并为其提供了字符串参数
- 第二个构造,通过调用 this(n,20); 把控制器交给了第一个构造,并为其提供了所需的两个参数
-
-
this 引用
- 除了可以在构造方法值之外,也可以用来指明要操作的对象自身
- Java自动用this关键字把所有变量和方法引用结合在一起
- this也可以省略,去掉不必要的this,提高代码可读性
3. 对象的创建和初始化
-
变量声明后,在内存中为其建立了一个引用也称为对象的句柄,此时不指向任何内存空间
-
需要使用new 申请相应的内存空间,内存大小依class的定义而分配,该内存的首地址赋给建立的引用
-
调用new 为新对象分配空间,就是调用类的构造方法
- 使用构造方法是生成实例的唯一途径
- 当在new 分配内存时,如果构造方法中没有为成员变量赋初值,那么系统会自动初始化
- 数值变量 初始为 0
- 布尔变量 初值为 false
- 对于引用,初值为 null
-
实例化过程
public class Test { private int x = 5; private String name = "Fred"; // 显示的初始化 private Date created = new Date(); // 显示的初始化 }
- 如果创建了Test实例,那么在系统为其进行默认的初始化之后,还要给实例中变量x赋值5,给**name赋值字符串 **“Fred”
-
类引用与实例创建
- 声明了today之后,他内存只没有存放任何值如图只有???
- 当实例化之后,也就是执行了new Date( ),才在内存中分配了Date实例的地址
- 并在相应的3个成员变量内存中放了初始值 0,同时将这实例的首地址存放到了引用 today中
-
基本变量的赋值
public static void main(String[] args) { int x = 7; int y = x; x= 5; System.out.println(y); } 控制台: 7
- 对一个变量的再修改不会影响到另外一个变量
-
引用变量的赋值
- 引用之间的赋值,对于任何一个变量的改变,改变的都是这个对象,所以都会影响到另外一个变量的值
- 内存地址是一样的,指向同一个World
public static void main(String[] args) { String s = "Hello"; String t = s; s = "World"; t = s; System.out.println(s.hashCode()); System.out.println(t.hashCode()); System.out.println(t); System.out.println(s); } 控制台: 83766130 83766130 World World
-
在Java中,null值表示引用不指向任何对象
二. 定义方法
1. 方法的定义
-
方法名必须是一个合法标识符
-
修饰符字段有几个类型
- public 公开的,所有类可访问
- private 私有的 同一类可访问
- protected 受保护的 同一包中可访问,非同一包中的子类可访问
- 默认 同一个包可访问
-
返回类型是方法返回值的类型
- 如果不返回,声明为void
- 返回值必须与所声明的类型匹配
-
参数列表是传递给方法的参数表
-
块表示方法体,是实际要执行的代码段,由一对大括号括起来
2. 按值传送
-
调用方法时,传给方法的值称为实参,方法的参数列表中列处出的值称为形参
-
方法里形参变化不影响实参
- 如果形参是基本数据类型的,调用方法时,将实参的值复制给形参
- 返回时,形参的值并不会带回给实参
-
如果形参是引用,则调用方法是传递给形参的是一个地址
- 实参指向的对象首地址,方法返回时,这个地址也不会改变,但是地址中保存的内容是可以改变的
public class Test { private String str; private float ptValue; public void changeInt(int value) { value = 55; } public void changeStr(Test test) { test.str = "dis"; } public void changeObjValue(Test ref) { ref.ptValue = 99f; } public static void main(String[] args) { int val; Test pt = new Test(); // 创建类的实例 val = 11; // 给整形量val赋值 pt.changeInt(val); // 改变value的值 System.out.println("现在val的值是:"+val); // 打印当前val的值 11 pt.str = "world"; pt.changeStr(pt); System.out.println("当前str的值为:"+pt.str); pt.ptValue = 101f; // 给ptValue赋值 pt.changeObjValue(pt); // 通过对象引入改值 System.out.println("当前ptValue的值:"+pt.ptValue); } } 控制台: 现在val的值是:11 当前str的值为:dis 当前ptValue的值:99.0
- 程序执行时,创建pt对象,给方法内局部变量val设置了11,调用方法返回之后,val值并没有发生改变
- 当传递str字符串的时候,传入一个引用对象,传给形参的是一个World,该引用中的地址并没有改变,但是内容可以变化,到了调用changeStr赋值时,内存地址中的字符串变成了World,等到执行到test.str = “dis”;又将字符串修改为dis返回
3. 重载方法名
- 允许多个方法使用同一个方法名,但是方法的参数列表必须不完全相同
- 参数列表包括(参数个数,顺序,类型)称为方法签名,方法签名一定不能相同
- Java是根据参数列表来查找适当的方法并进行调用的
三. 静态成员
1.静态成员与普通成员方法的区别
- Java允许中系统生成类的每个实例对象时,会为每个对象的实例变量分配内存,然后才能访问对象的成员,而且不同对象的内存空间相互独立,也就是说不同对象的成员,内存地址是不一样的
- 静态成员则系统在类定义时就会其分配内存,此时还没创建对象,也没有进行实例化,以后生成该类的实例对象时,将不再为静态成员分配内存
- 不同对象的静态变量将共享同一块内存空间
2. 静态变量
-
将一个变量定义为静态变量的方法就是将这个变量标记上关键字static
-
静态变量也称为类变量,调用的时候,不需要创建实例,直接 类名. 即可
private static String str;
-
Java中没有全局变量的概念,从某种意义上来说 静态变量 类似于其他语言中的全局变量
-
静态变量如果同时被定义为public,那么其他类一样可以使用这一变量,调用时直接使用类名指向它
3.静态方法
-
一个静态方法只能使用其内部定义的参数或静态变量,如果想使用非静态变量将发生编译错误
- 由于静态方法可以在没有定义它所属的类的对象情况下,加以调用。所以不存在this值
-
静态方法不能被重写,也就是说,在这类的子类中,不能有相同名称,相同参数列表的方法
public class Test {
private static String str;
private float ptValue = 9f; // ptValue不是静态变量
public static void main(String[] args) {
ptValue = 10f; // 无法从静态方法值引用非静态变量ptValue
}
}
四. 包装类
-
要管理的数据分为:基本数据类型 和 对象引用
-
当想用处理对象的方式来处理基本类型的数据时,必须将基本数据类型值包装成一个对象,为此Java提供了包装类
-
包装类是一种特殊的基本类型
-
例如Integer类表示一个普通的整形量,由Integer类创建的对象只保存一个int型的值
-
包装类的构造方法接收一个基本类型的值,并保存它
-
Integer ageObj = new Integer(40);
- 执行这条语句之后,ageObj对象 就将整数40看作一个对象,它可以用在程序中需要对象而不是需要基本类型值的地方
-
-
对于每种基本数据类型,Java都有一个对应的包装类,所有的包装类都在Java.lang 包下
-
基本数据类型 包装类 基本数据类型 包装类 byte Byte double Double short Short char Character int Integer boolean Boolean long Long void Void float Float -
对应于void类型的包装类是Void,但和其他包装类不一样的是,Void类不能被实例化,只表示void引用的概念
-
下面列举几个Integer类中几个方法,其他包装类也有类似的
-
public Integer(int value) { // 构造方法,创建Integer对象,用来保存值value this.value = value; } public byte byteValue() { // 按照各自对应的基本数据类型返回Integer对象的值 return (byte)value; } public short shortValue() { // 等等....如上 return (short)value; }
-
-
-
Java包装类中一般含有常量
- 例如Integer类中有两个常量 MIN_VALUE 和 MAX_VALUE
- 它们分别保存int型中的最大最小值
- 其他包中也有类似的常量
- 例如Integer类中有两个常量 MIN_VALUE 和 MAX_VALUE
-
自动装箱
-
自动将基本数据类型转换为对应的包装类的过程称为自动装箱
public static void main(String[] args) { Integer obj1; int num1 = 89; obj1 = num1; // 自动创建Integer对象 // 逆向的转换也称为拆箱,也是自动完成的 Integer obj2 = new Integer(89); int num2; num2 = obj2; // 自动解析出int型 }
-
自动装箱与自动拆箱只能用在基本数据类型和对应的包装类之间
-
如果将基本数据类型赋给对应引用变量,或者将引用变量赋给基本数据类型,会编译错误
-