Java基础-对象和类
基本概念
定义
- 对象:对象是类的一个实例,有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。
- 类:类是一个模板,它描述一类对象的行为和状态。
类型变量
- 局部变量:在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。
- 成员变量:成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。
- 类变量:类变量也声明在类中,方法体之外,但必须声明为 static 类型。
成员变量和类变量的区别
由static修饰的变量称为静态变量,其实质上就是一个全局变量。如果某个内容是被所有对象所共享,那么该内容就应该用静态修饰;没有被静态修饰的内容,其实是属于对象的特殊描述。
不同的对象的实例变量将被分配不同的内存空间, 如果类中的成员变量有类变量,那么所有对象的这个类变量都分配给相同的一处内存,改变其中一个对象的这个类变量会影响其他对象的这个类变量,也就是说对象共享类变量。
区别:
1、两个变量的生命周期不同
成员变量随着对象的创建而存在,随着对象的回收而释放。
静态变量随着类的加载而存在,随着类的消失而消失。
2、调用方式不同
成员变量只能被对象调用。
静态变量可以被对象调用,还可以被类名调用。
3、别名不同
成员变量也称为实例变量。
静态变量也称为类变量。
4、数据存储位置不同
成员变量存储在堆内存的对象中,所以也叫对象的特有数据。
静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。
static
static 关键字,是一个修饰符,用于修饰成员(成员变量和成员函数)。
特点:
1、想要实现对象中的共性数据的对象共享。可以将这个数据进行静态修饰。
2、被静态修饰的成员,可以直接被类名所调用。也就是说,静态的成员多了一种调用方式。类名.静态方式。
3、静态随着类的加载而加载。而且优先于对象存在。
弊端:
1、有些数据是对象特有的数据,是不可以被静态修饰的。
因为那样的话,特有数据会变成对象的共享数据。这样对事物的描述就出了问题。所以,在定义静态时,必须要明确,这个数据是否是被对象所共享的。
2、静态方法只能访问静态成员,不可以访问非静态成员。
因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。
3、静态方法中不能使用this,super关键字。
因为this代表对象,而静态在时,有可能没有对象,所以this无法使用。
成员变量和局部变量区别
区别
1、声明位置不同
成员变量也就是属性,在类中声明的。
局部变量,在方法中声明或代码块中声明。
2、初始值不同
成员变量如果没有赋值则是有默认值的,数据类型不同则默认值不同。
局部变量是没有默认值,也就是说必须先声明,再赋值,最后才使用。
3、在一个类中,局部变量可以与成员变量同名,但是局部变量优先,如果非要访问成员变量的属性,则必须使用 this
this 代表当前这个对象,也就是当前谁调用这个方法则这个对象就是谁。
构造方法
1、构造方法的名字和类名相同,并且没有返回值。
2、构造方法主要用于为类的对象定义初始化状态。
3、我们不能直接调用构造方法,必须通过new关键字来自动调用,从而创建类的实例。
4、Java的类都要求有构造方法,如果没有定义构造方法,Java编译器会为我们提供一个缺省的构造方法,也就是不带参数的构造方法。
5、如果定义了任何一个构造函数,就不会再自动构造,需要自己定义全部的构造函数。
new关键字的作用
1、为对象分配内存空间。
2、引起对象构造方法的调用。
3、为对象返回一个引用。
对象与引用区别
对象是具体的一个实例,如:new Student(); new 表示创建一个对象,并在堆内存中开辟一块空间。
引用名称是存放的对象的地址。
例如:
1 //一个带显式构造函数的类 2 Public class People{ 3 int age = 23; 4 Public void getAge(){ 5 System.out.print("the age is "+ age); 6 } 7 // 显式声明一个带参数的构造函数,用于初始化年龄 8 Public People(int a){ 9 this.age = a; 10 } 11 } 12 13 //用这个类来实例化一个对象 14 People xiaoMing = new People(20); // 使用带参数的构造函数来实例化对象 15 People xiaoMing2 = new People(); // ERROR:一旦显示定义了一个构造函数,就不会再生成默认的构造函数 16 xiaoMing.getAge(); // 打印出来的年龄变为20
创建对象
对象是根据类创建的。在Java中,使用关键字 new 来创建一个新的对象。创建对象需要以下三步:
- 声明:声明一个对象,包括对象名称和对象类型。
- 实例化:使用关键字 new 来创建一个对象。
- 初始化:使用 new 创建对象时,会调用构造方法初始化对象。
1 public class Student{ 2 public Student(String name){ 3 System.out.println("学生的名字是 : " + name ); 4 } 5 public static void main(String[] args){ 6 Student stu = new Student( "tom" ); 7 } 8 }
访问实例变量和方法
通过已创建的对象来访问成员变量和成员方法,如下所示:
1 /* 实例化对象 */ 2 Object referenceVariable = new Constructor(); 3 /* 访问类中的变量 */ 4 referenceVariable.variableName; 5 /* 访问类中的方法 */ 6 referenceVariable.methodName();
类的访问权限
四种访问修饰符
private
Java语言中对访问权限限制的最窄的修饰符,一般称之为“私有的”。被其修饰的属性以及方法只能被该类的对象访问,其子类不能访问,更不能允许跨包访问。
default
即不加任何访问修饰符,通常称为“默认访问权限“或者“包访问权限”。该模式下,只允许在同一个包中进行访问。
protected
介于public 和 private 之间的一种访问修饰符,一般称之为“保护访问权限”。被其修饰的属性以及方法只能被类本身的方法及子类访问,即使子类在不同的包中也可以访问。
public
Java语言中访问限制最宽的修饰符,一般称之为“公共的”。被其修饰的类、属性以及方法不仅可以跨类访问,而且允许跨包访问。
四种修饰符的访问权限范围:
这里需要注意的是,所谓的访问,可以分为两种不同方式:第一,通过对象实例访问;第二,直接访问。
比如说,某父类protected权限的成员,子类是可以直接访问的,换一种说话是子类其实继承了父类的除了private成员外的所有成员,包括protected成员,所以与其说是子类访问了父类的protected成员,不如说子类访问了自己的从父类继承来的protected成员。另一方面,如果该子类与父类不在同一个包里,那么通过父类的对象实例是不能访问父类的protected成员的。
例如:
新建个类,四个类的结构如下,Aclass 和Bclass 是同包的类,Cclass 和Dclass是同包的类,Cclass 继承了Aclass。
Aclass类的定义如下,有四个成员变量,权限分别为private、default、protected、public。四个成员方法,权限分别为 private、default、protected、public。
1 package com.study.test1; 2 3 /** 4 * @description: none 5 * @author: luguilin 6 * @date: 2021-09-22 21:47 7 **/ 8 public class Aclass { 9 private int a1 = 10; 10 int a2 = 20; 11 protected int a3 = 30; 12 public int a4 = 40; 13 14 private void showA1() { 15 System.out.println(a1); 16 } 17 18 void showA2() { 19 System.out.println(a2); 20 } 21 22 protected void showA3() { 23 System.out.println(a3); 24 } 25 26 public void showA4() { 27 System.out.println(a4); 28 } 29 }
Bclass类定义如下,它和Aclass类同属于 test1包 ,在里面定义了一个成员方法show(),该方法通过两种方法对Aclass类的所有成员进行了访问,第一方法通过实例化一个Aclass类对象aa对成员变量及方法进行访问,第二种是直接访问Aclass中的成员。通过IDE的自动检测报错,可以看出,Bclass类是不能直接访问Aclass类的成员的,但通过对象的方法可以访问default权限以下(default、protected、public)的成员。
1 package com.study.test1; 2 3 /** 4 * @description: none 5 * @author: luguilin 6 * @date: 2021-09-22 21:52 7 **/ 8 public class Bclass { 9 public void show(){ 10 // 方法 11 Aclass aa = new Aclass(); 12 // aa.showA1(); // 'showA1()' has private access in 'com.study.test1.Aclass' 13 aa.showA2(); 14 aa.showA3(); 15 aa.showA4(); 16 17 // showA1(); // showA1的修饰符是private同包的类不能访问 18 // showA2(); // showA2的修饰符是default拥有同包访问以上权限 19 // showA3(); // showA3的修饰符是protected拥有不同包子类以上访问权限 20 // showA4(); // showA4的修饰符是public拥有公开访问权限 21 22 //变量 23 // System.out.println(aa.a1); // 'a1' has private access in 'com.study.test1.Aclass' 24 System.out.println(aa.a2); 25 System.out.println(aa.a3); 26 System.out.println(aa.a4); 27 28 // System.out.println(a1); // a1 的修饰符是private同包的类不能访问 29 // System.out.println(a2); // a2的修饰符是default拥有同包访问权限 30 // System.out.println(a3); // a3 的修饰符是protected拥有不同包子类以上访问权限 31 // System.out.println(a4); // a4 的修饰符是public拥有公开访问权限 32 } 33 }
Cclass类定义如下,它和Aclass类属于不同的包,但是Cclass继承了Aclass ,在里面定义了一个成员方法show(),该方法同样通过两种方法对Aclass类的所有成员进行了访问,第一方法通过实例化一个Aclass类对象aa对成员变量及方法进行访问,第二种是直接访问Aclass中的成员。通过IDE的自动检测报错,可以看出,Cclass类是可以直接访问Aclass类权限为protected、public的成员(因为子类的缘故),但通过对象的方法只能访问 public权限的成员(因为Cclass和Aclass不同包)。
1 package com.study.test2; 2 3 import com.study.test1.Aclass; 4 5 /** 6 * @description: none 7 * @author: luguilin 8 * @date: 2021-09-22 21:56 9 **/ 10 public class Cclass extends Aclass { 11 Cclass(){ 12 super(); 13 } 14 15 public void show(){ 16 Aclass aa = new Aclass(); 17 // 方法 18 // aa.showA1(); // 'showA1()' has private access in 'com.study.test1.Aclass' 19 // aa.showA2(); // 'showA2()' is not public in 'com.study.test1.Aclass'. Cannot be accessed from outside package 20 // aa.showA3(); // 'showA3()' has protected access in 'com.study.test1.Aclass' 21 aa.showA4(); 22 23 // showA1(); // showA1的修饰符是private,同包的类不能访问 24 // showA2(); // showA2的修饰符是default。拥有同包访问以上权限 25 showA3(); // showA3的修饰符是protected,拥有不同包子类以上访问权限 26 showA4(); // showA4的修饰符是public,拥有公开访问权限 27 28 29 // 变量 30 // System.out.println(aa.a1); //'a1' has private access in 'com.study.test1.Aclass' 31 // System.out.println(aa.a2); //'a2' is not public in 'com.study.test1.Aclass'. Cannot be accessed from outside package 32 // System.out.println(aa.a3); //'a3' has protected access in 'com.study.test1.Aclass' 33 System.out.println(aa.a4); 34 35 36 Cclass cc = new Cclass(); 37 // cc.showA1(); // 'showA1()' has private access in 'com.study.test1.Aclass' 38 // cc.showA2(); // 'showA2()\' is not public in \'com.study.test1.Aclass\'. Cannot be accessed from outside package' 39 cc.showA3(); 40 cc.showA4(); 41 42 // System.out.println(a1); // a1 的修饰符是private同包的类不能访问 43 // System.out.println(a2); // a2的修饰符是default拥有同包访问权限 44 // System.out.println(a3); // a3 的修饰符是protected拥有不同包子类以上访问权限 45 System.out.println(a4); // a4 的修饰符是public 拥有公开访问权限 46 47 48 // 通过子类访问 49 // System.out.println(cc.a1); // 'a1' has private access in 'com.study.test1.Aclass' 50 // System.out.println(cc.a2); // 'a2' is not public in 'com.study.test1.Aclass'. Cannot be accessed from outside package 51 System.out.println(cc.a3); 52 System.out.println(cc.a3); 53 } 54 55 }
Dclass类定义如下,它是Aclass类不同包的一般类,在里面定义了一个成员方法show(),该方法同样通过两种方法对Aclass类的所有成员进行了访问,第一方法通过实例化一个Aclass类对象aa对成员变量及方法进行访问,第二种是直接访问Aclass中的成员。通过IDE的自动检测报错,可以看出,Dclass类是不可以直接访问Aclass类的成员(因为不是子类的缘故),但通过对象的方法只能访问 public权限的成员(因为class和Aclass不同包)。
1 package com.study.test2; 2 3 import com.study.test1.Aclass; 4 5 /** 6 * @description: none 7 * @author: luguilin 8 * @date: 2021-09-22 22:01 9 **/ 10 public class Dclass { 11 public void show(){ 12 Aclass aa = new Aclass(); 13 // 方法 14 // aa.showA1(); // 'showA1()' has private access in 'com.study.test1.Aclass' 15 // aa.showA2(); // 'showA2()' is not public in 'com.study.test1.Aclass'. Cannot be accessed from outside package 16 // aa.showA3(); // 'showA3()' has protected access in 'com.study.test1.Aclass' 17 aa.showA4(); 18 19 // showA1(); // showA1的修饰符是private同包的类不能访问 20 // showA2(); // showA2的修饰符是default拥有同包访问以上权限 21 // showA3(); // showA3的修饰符是protected拥有不同包子类以上访问权限 22 // showA4(); // showA4的修饰符是public拥有公开访问权限 23 24 // 变量 25 // System.out.println(aa.a1); //'a1' has private access in 'com.study.test1.Aclass' 26 // System.out.println(aa.a2); //'a2' is not public in 'com.study.test1.Aclass'. Cannot be accessed from outside package 27 // System.out.println(aa.a3); //'a3' has protected access in 'com.study.test1.Aclass' 28 System.out.println(aa.a4); 29 30 // System.out.println(a1); // a1 的修饰符是private同包的类不能访问 31 // System.out.println(a2); // a2的修饰符是default拥有同包访问权限 32 // System.out.println(a3); // a3 的修饰符是protected拥有不同包子类以上访问权限 33 // System.out.println(a4); // a4 的修饰符是public拥有公开访问权限| 34 } 35 }