Java面向对象——类和对象&深入构造器
类是一批对象的抽象。
这是类与对象的关系,通过这句话就可以知道什么是类什么是对象了。如果有一个类叫手机,那么对象就是客观存在的手机实体了。
1、类的定义
1.1 类的定义语法
修饰符 class 类名{
零到多个成员变量(field )
零到多个构造器
零到多个方法
}
<1> 修饰符可以是 public、final、abstract,或者完全省略。类名要符合标识符的命名规则
<2>定义成员变量的语法格式:【修饰符】 类型 成员变量名 【=默认值】; 作用:用于定义该类或该类的对象所包含的状态数据
* 修饰符 : 修饰符可以省略,也可以是 public protected private static final,其中 public protected private 只能出现其一,可以与static final组合起来修饰成员变量
* 类型 : 可以是Java允许的任何数据类型
*成员变量名:符合标识符命名规则
*默认值:成员变量可以指定一个可选的默认值
<3>构造器 构造器是一个特殊的方法,
作用:用于类创建对象,如果一个类没有构造器,那么这个类将无法创建对象。如果程序员没有编写构造器 那么系统则会为该类默认一个无参的构造器,如果程序员编写了构造器,系统就不会在为该类提供无参构造器。
定义构造器语法:【修饰符】 构造器名(形参列表){
//由零条到多条可执行语句组成的构造器执行体
}
*修饰符:public protected private之一,或省略
*构造器名:必须与类名相同
*形参列表:与方法的形参列表格式相同
无参构造器与有参构造器:无参构造器创建对象创建的对象只有在堆内存中的默认地址,属性的值为默认值。有参构造方法创建的对象除了有在堆内存的默认地址之外还有在堆内存中引用的值。
构造器不能定义返回值类型,也不能使用void关键字声明构造器没有返回值,否则编译也不会出错,但是Java会把这个所谓的构造器当成普通方法来处理,这样它就不在是构造器。那么实际上构造器是有返回值的,返回的是一个对象的实例。返回是隐式的,所以不能用return来返回当前类的对象。
下面我们来创建一个类:
1 public class User{ 2 public String name; 3 public int age; 4 public User(){ 5 6 } 7 public User(String name,int age){ 8 this.name = name; 9 this.age = age; 10 } 11 public void eat(){ 12 System.out.println("吃的方法"); 13 } 14 }
2、对象的创建和使用
2.1创建对象
创建对象的根本途径是构造器,通过new关键字来调用某个类的构造器即可创建这个类的实例。
User u ;//使用User类定义一个该类的变量
u = new User();//通过new关键字调用User类的构造器,返回一个User实例。将返回的 实例赋给p变量。
2.2 使用对象
对象的作用 :访问对象的实例变量和调用对象的方法
**如果访问权限允许,类里定义的方法和成员变量都可以通过类或实例来调用。类或实例访问方法或成员 变量的语法是:类.类变量/方法或实例.实例变量/方法。。static修饰的方法和成员变量可以听通类来调用,也可以通过实例来调用。没有用static来修饰的方法和成员变量只可以通过实例来调用。
3、对象、引用和指针
User p = new User();
这行代码创建了一个 User实例,这个User对象被赋给u变量。这行代码产生了两个东西:一个是User实例 另一个是p变量。下面用两张图来说明这两个东西在内存中是怎么存放的。
由上图可以看出User对象是由多块内存组成,不同内存块存放了User对象的不同成员变量。
那么如何把这个对象赋值给一个引用变量呢?如下图所示
类也是一种引用数据类型,因此程序中定义的User类型的变量实际上是一个引用,它被存放在栈内存中。栈内存中的引用变量并未真正存储对象的成员变量。从这个角度看,引用变量与C语言里的指针很像,它们都是存储一个地址值,通过这个地址来引用到实际对象。实际上,Java里的引用就是指正,只是Java语言把这个指针封装起来了,避免开发者进行繁琐的指针操作。当一个对象创建成功后,这个对象将保存在堆内存中,Java程序不允许直接访问堆内存中的对象,只能通过该对象的引用来操作该对象。当P访问成员变量和方法时,实际上是p所引用的对象的成员变量和方法。
堆内存的对象可以有多个引用,即多个应用变量指向同一个对象
4、对象的this引用和static关键字
*static是一个特殊的关键字,它可用于修饰方法、成员变量等成员。static修饰的成员表明该成员属于这个类本身,而不属于该类的单个实例,因此把static修饰的方法和成员变量称为类方法或者类成员。把static修饰的方法和成员变量称为实例变量或者实例方法。静态成员不能直接访问非静态成员。有static修饰的成员属于类本身,没有static修饰的成员属于实例。
根据this出现的位置不同,this作为对象的默认引用有两种情形:构造器中引用该构造器正在初始化的对象、在方法中引用调用该方法的对象。
实际上this最大的用途是让类中的一个方法,访问该类里的另一个方法或实例变量,但是this在使用的时候往往被省略,最大的一个作用表现的很含蓄。
来看这段代码,之前不是说没有static修饰的方法只能用对象来调用吗?为什么下面的代码在没有static修饰的jump方法可以直接调用run方法吗?实际上就像注释写的那样是将前面的this给省略掉了,this是run方法的主调者。
1 public class Dog { 2 public void run(){ 3 System.out.println("跑的方法"); 4 } 5 public void jump(){ 6 run();//this.run(); 7 System.out.println("跳得方法"); 8 } 9 10 }
对于static修饰的方法而言,则可以使用类来直接调用该方法,如果在static修饰的方法中使用this关键字,则这个关键字就无法指向合适的对象。所以,static修饰的方法不能访问不使用static修饰的普通成员,因此Java语法规定:静态成员不能直接访问非静态成员。
大多数this可以省略,但是当防止局部变量与成员变量重名可以加上this。
4、深入构造器
4.1使用构造器初始化对象
构造器的最大作用就是在创建对象时进行初始化。
如果程序员自定义了构造器,那么系统就不会默认提供无参构造器
通常使用public 作为构造器的修饰符。
4.2 构造器重载
这个地方有这么一个问题,如果定义了多个构造器,但是A构造器的参数列表完全包含了B构造器的参数列表,同时执行体也完全包含了B构造器的执行体。那么这个时候就可以使用this关键字来在B构造器中调用A构造器。
1 public class Person { 2 public int num; 3 public String name; 4 public String sex; 5 6 public Person() { 7 8 } 9 10 public Person(int num, String name, String sex) { 11 this(num, name); 12 this.sex = sex; 13 } 14 15 public Person(int num, String name) { 16 this.num = num; 17 this.name = name; 18 } 19 20 }
使用this调用另一个重载构造器只能在构造器中使用,而且必须作为构造器执行体的第一句语句。使用this调用重载构造器时,系统会根据this后面括号里面的实参来匹配具有相同形参的构造器。