对于Java类的思路总结1

Java是面向对象的程序设计语言。类用于描述客观客观世界某一类对象的共同特征,而对象则是具体存在。可以把类当作一种自定义类型,可以使用类来定义变量,这种变量统称为引用变量(引用变量存储的是堆内存中的一块地址,相当于C语言中的指针),也就是说,所有类都是引用类型。
1定义一个普通类(不包括内部类)通常要用到以下几种修饰符
public,final,abstract或者完全省略修饰符。
Java通常有四个级别访问控制级别。
在这里插入图片描述
普通类不能用private修饰,因为private访问控制权限在同一个类中,普通类就算能用private修饰也没有意义。(编译时也会报错)
(1)一个源文件只能有一个public类
针对一个Java源文件(也称为”编译单元“)只会接受一个public类,否者会报错)
(2)在Java文件中也可以没有public类,它并不是必须的
(3)public类的名字要与文件名相同
只是为了方便JVM(虚拟机)在相应的路径找到所对应的字节码文件。
2定义一个类通常有以下几种成员

        (1)成员变量
	(2)方法
	(3)构造器
	(4)初始化块
	(5)内部类

先说说成员变量
(1)成员变量
成员变量修饰符:public,protected,private(访问控制权限看上表)
static,final
static–>类成员变量(属于该类本身),否者为实例变量
final(final类的时候详细讲)
注意:
静态成员不能访问非静态成员

原理:程序最终在内存中执行,变量只有在内存中占有一席之地才能被访问。类的静态成员(变量和方法)属于类本身,在类加载中就会为静态成员分配内存,可以通过类名直接访问,此时不会为非静态成员分配内。
类的非静态成员属于类的对象,所以只有在类的对象产生时才会分配内存,然后通过对象去访问,创建对象时,并不会为静态成员分配内存
在一个类的静态成员中访问其非静态成员之所以会出错是因为在类的非静态成员不存在时类的静态成员就已经存在了,访问一个内存中不存在的东西当然会出错
而类又在什么时候加载呢?
由引导类加载器负责加载的核心类比如String类在JVM启动时(main方法开始执行前)就会被加载,其他类在使用前(new它对象或调用其静态方法访问静态域等等前)会被加载,要注意的是子类被加载前它的所有父类要根据父到子的顺序被逐一加载
(2)方法
修饰符:public,protected,private(访问控制权限看上表)
static,final,abstract(比成员变量多的一个修饰符)
static–>类方法(属于类本身)
final(final类的时候详细讲)
abstract–>(抽象类的时候详细讲)
返回值
允许返回Java语言允许的任何数据类型,包括引用类型和基本类型
(3)构造器
构造器是一个类创建一个对象的根本途径,如果没有构造器,这个类通常无法创建实例,所以当没有为一个类提供构造器时,系统会默认为这个类创建一个无参,无具体实现的构造器。一旦程序为一个类提供了构造器,系统将不再为该类提供构造器。
构造器是一个特殊的方法
修饰符 public,protected,private或者省略
构造器名 必须与类名相同
形参列表 与普通方法完全相同
注意定义构造器不需要指定返回值,连void也不能写,但构造器其实是有返回值的,当用new调用构造器时,返回了类的一个实例,因此构造器返回值类型总是当前类,无需定义返回值类型,但必须之一,不要再构造器中显式的用return来返回当前类的对象,应为构造器的返回值都是隐式的
(4)初始化块
没有名字,也就没有标识,无法通过类或对象来调用初始化块,初始化块只在创建Java对象时隐式执行,而且在执行构造器前执行。一个类里可以有多个初始化块(相同类型的初始化块定义多个并没有意义,因为只有创建对象时隐式调用初始化块,且他们都是全部执行,完全可以把它们合并到一个初始化块中),相同类型(static和普通类型)的初始化块之间有顺序:先定义先执行。初始化块内代码可以使用任何可执行的语句,包括定义局部变量,循环控制语句等等

public class InstanceInitTest
{
   // 先执行初始化块将a实例变量赋值为6
   {
      a = 6;
   }
   //再执行将a实例变量赋值为9
   int a = 9;
   public static void main(String[] args)
   {
      //下面代码将输出9      System.out.println(new InstanceInitTest().a);
   }
}

注意:当Java创建一个对象时,系统先为该对象的所有实例变量分配内存(前提是该类已经被加载过了)(创建对象时是不会为为类变量分配内存的),接着程序开始对这些实例变量进行初始化,其初始化顺序是:先执行初始化块或声明实例变量时指定的初始值(这两个地方指定初始值的执行顺序与他们在源代码中的排列顺序相同),再执行构造器里指定的初始值。
初始化块与构造器的区别于联系
从某种程度讲,初始化块是构造器的补充,初始化块总是在构造器执行之前执行,系统同样可以用初始化块来进行对象的初始化操作。
与构造器不同的是,初始化块是一段固定执行的初始化块代码,它不能接受任何参数。因此初始化块对同一个类的所有对象所进行的处理化处理完全相同。基于这个原因,不难发现初始化块的基本用法,如果有一段初始化处理代码对所有对象完全相同,且无需接收任何参数,就可以把这段代码提取到初始化块中。通过把多个构造器中相同代码提取到初始化块中定义,能更好的提高初始化代码的复用率,提高整个应用的可维护性。
实际上初始化块是一个”假象“,使用javac命令编译Java类后,该类中的初始化块会消失----初始化块代码会被“还原”到每个构造器中,且位于所有代码的前面。
与构造器类似,创建一个Java对象时,不仅会执行该类的普通初始化块和构造器,而且系统会一直上溯到java.lang.Object类的初始化块和构造器(继承,Object类是所有类的父类),先执行Object类的初始化块,开始执行Object类的构造器依次向下执行其父类的初始化块,开始执行其父类的构造器…最后才执行该类的初始化块和构造器,返回该类对象。
静态初始化块
static修饰,也被称为类初始化块,对整个类进行初始化处理。属于类成员,同样需要遵循静态成员不能访问非静态成员的规则。
系统在类初始化阶段执行静态初始化块,而不是在创建对象时才执行,因此静态初始化块总是比普通初始化块先执行。
与普通初始化块类似,系统在类初始化阶段执行静态初始化块,不仅会执行本类的静态初始化块,而且还会一直上溯到java.lang.Object类的静态初始化块(如果它包含静态初始化块),先执行Object类的静态初始化块,然后执行其父类的静态初始化块…最后才执行该类的静态初始化块,经过这个过程,才完成了该类的初始化过程,才可以在系统中使用这个类,包括访问该类的类方法,类变量或者用这个类来创建实例。
java系统加载并初始化某个类时,总是保证该类的所有父类(直接的和间接的)全部加载并初始化。
当JVM第一次主动使用某个类时,系统会在类准备阶段为该类的所有静态成员变量分配内存,在初始化阶段则负责初始化这些静态成员变量,初始化这些静态成员变量就是执行类的类初始化块或者声明该类成员变量时指定的初始值,他们的执行顺序与源代码中的排列顺序相同。
3对象的产生和使用
当一个对象被创建成功了,这个对象将被保存在堆内存中,java不允许直接访问堆内存中的对象,只能通过该对象的引用操作该对象。
如果堆内存里的对象没有任何变量指向该对象,那么程序将无法再访问该对象,这个对象也就变成了垃圾,Java的垃圾回收机制将该对象,释放该对象所占的内存区。
对象的this引用
构造器中引用该构造器正在初始化的对象
在方法中引用调用该方法的对象

this指针最大的作用就是让类中一个方法,访问该类里另一个方法或者实例变量
this可以代表任何对象,当this出现在某个方法体中时,它代表的对象是不确定的,但它代表的类型是确定的:它所代表的只能是当前类的实例:只有当调用这个方法时,它所代表的对象才能被确定下来:谁在调用这个方法,this就代表谁。
java允许对象的一个成员直接调用另一个成员,可以省略this前缀。
省略this只是一种假象,虽然程序员省略了this,但实际上它还是存在的。
对于static修饰的方法而言,则可以直接实用类来调用该方法,如果在static修饰的方法中使用this关键字,则这个关键字就无法指定合适的对象。所以,static修饰的方法中不能使用this引用,所以静态成员不能直接访问非静态成员。如果确实需要在静态方法中访问另一个普通方法,则只能重新建一个对象。
注意:如果方法里有局部变量和成员变量同名,但程序又需要在该方法中访问这个被覆盖的成员变量(根据被覆盖改的是类变量还是实例变量),这必须使用this. 或者 类名.
如果构造器里有局部变量和成员变量同名,但程序又需要在该构造器中访问这个被覆盖的成员变量,这必须使用this.(这里不包含被覆盖的是类变量的情况,构造器是与对象相关的)
当this作为引用使用时,程序可以像访问普通引用变量一样来访问这个this引用,甚至可以把this当作普通变量当作普通方法的返回值。

public class ReturnThis
{
   public int age;
   public ReturnThis grow()
   {
      age++;
      // return this返回调用该方法的对象
         return this;
   }
   public static void main(String[] args)
   {
      ReturnThis rt = new ReturnThis();
      // 可以连续调用一个方法
      rt.grow()
         .grow()
         .grow();
      System.out.println("rt的age成员变量值是:" + rt.age);
   }
}

如果在某个方法中用this作为返回值,这可以连续调用同一个方法,但可能造成实际意义的模糊。

猜你喜欢

转载自blog.csdn.net/qq_43215734/article/details/85106554