Java中一切皆是对象!
注意:8种基本数据类型不支持面向对象的编程机制,基本数据类型的数据也不具备“对象”的特性:没有成员变量、方法可以被调用。
为解决8种基本数据类型不能当成Object类型(所有类的父类)变量使用的问题,Java提供了包装类的概念,为8种基本数据类型分别定义了相应的引用类型,例如:int的包装类是Integer,包装类可以把8种基本数据类型的值包装成对象使用。包装类是java自带类,位于java.lang包下。
Integer i = new Integer(10);
上面例子中,i 只是一个对象的引用,存放在栈中,而实际的数值10则是放在堆里。
对象和构造器:
构造器:
用于创建对象时执行初始化。当创建一个对象时eg:new Person();系统为这个对象的实例变量进行默认初始化。PS:类变量在类创建时就进行默认初始化,故此变量称为类变量,成员变量分为类变量和实例变量。
构造器是创建Java对象的重要途径,通过new关键字调用构造器时,构造器返回了该类的对象(可见构造器实际上是有返回值)。
对象的产生:
创建对象的根本途径是构造器。通过new关键字来调用某个类的构造器(系统默认提供一个无参构造器)即可创建这个类的实例(对象)。
Person p = new Person(); //通过new关键字调用Person类的构造器,返回(创建)一个Person实例(对象),将该Person实例(对象)赋给p变量。
对象作用:访问对象的实际变量、调用对象的方法。
对象 & 实例:可以把new出来的对象叫做实例,大白话说就是这个new出来的“东西”,叫它对象也可以,叫它实例也可以,对象和实例在这个角度上来讲是等价的。
对象的实例化:
例如,String a = "abc"; 当你声明String a 的时候,jvm(java虚拟机)就帮你在堆中开辟一块内存空间,用来存放a的数据"abc",这里的a叫作引用,"abc"则为实例!
其实 String a = "abc" 完整的写法是String a = new String("abc") ,String是Java的自带类,位于java.lang包下,所以可以不new。
数组是对象:
Java是面向对象语言(Java中除了8种基本数据类型,全是对象),数据的定义也可以看做是实例化的过程,因此我们在定义数组变量时也可以看做是实例化数组对象的过程。
Object是一切引用类型的父类,所有能被Object接收的均为对象。简言之,所有可以new出来的不管是类也好,接口也好,都可以看做为对象。并且都能被Object接收。
它们的异同之处就在于,对象是一个抽象的概念,而数组是对象,但是它有具体的实例。
int[] temp = {1,3,5} //也可以写作 int[] temp = new int[]{1,3,5}
this和super:
对象的this引用:
Java提供了一this关键字,this关键字总是指向调用该方法的对象。根据this出现的位置的不同,this作为对象的默认引用有2种情形:
1.构造器中引用(指向)该构造器正在初始化的对象;
2.在方法中引用(指向)调用该方法的的对象。
this最大的作用就是让一个类中的一个方法,访问该类里的另一个方法或者实例变量,示例:
public void run() { this.jump(); //jump()为另一个类的方法 }
this还可以,通过this调用另一个重载的构造器的初始化代码,this(parameter1,parameter2); 示例:
public Apple(){} public Apple(String name,String color) { this.name = name; this.coloe = color; } public Apple(String name,String color,double weight) { //通过this调用另一个重载的构造器的初始化代码 this(name,color); this.weight = weight; }
this可以代表任何对象,谁调用this所在方法,this就代表谁。Java允许对象的一个成员直接调用另一个成员,可以省略this前缀,但是,如果方法里有个局部变量和成员变量同名,要在该方法里访问这个被覆盖的成员变量,必须使用this前缀。
super:
当子类覆盖(重写)了父类方法后,子类的对象将无法访问父类中被覆盖的方法,但使用super关键字可以在子类中调用父类中被覆盖的方法。
如果子类定义了和父类同名的实例变量,则会发生子类实例变量隐藏(不是覆盖)父类实例变量的情形,可以在子类定义的实例方法中通过super关键字访问父类中被隐藏的实例变量。
注意:
this、super在调用构造器方面:this调用的是同一个类中重构的构造器,super调用的是父类的构造器。另外:不管是否使用super调用来执行父类构造器的初始化代码,子类构造器总会默认调用父类构造器一次。
Java内存:
栈区:
1.每个线程包含一个栈区,栈中只保存基本数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中。
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息(class的目的是得到操作指令)。
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身。
方法区:
在java的虚拟机中有一块专门用来存放已经加载的类信息、常量、静态变量以及方法代码的内存区域。常量池是方法区的一部分,主要用来存放常量和类中的符号引用等信息。
1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量(使用static修饰的成员变量)。
面向对象的三大特性:
封装:
将对象的状态信息(eg:Person对象的age变量)隐藏在对象内部,外部程序只能通过该类提供的方法来实现对内部信息的操作和访问。
继承:
继承就是子类继承父类的特征和行为,使得子类具有父类的各种属性和方法(重用父类代码)。
多态(难点):
Java引用变量,编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定(即子类对象赋给父类变量),如果编译时类型和运行时类型不一致,就可能出现多态。
1.多态定义:相同类型的(引用)变量,调用同一个方法(父类和子类都有的同名方法)时呈现出多种不同的行为特征。
当引用变量polymophicBc编译时类型为BaseClass类型,而运行时类型为SubClass类型,运行时调用该引用变量的方法时,其方法行为总是表现出子类SubClass方法的行为特征,而不是父类BaseClass方法的行为特征。
BaseClass polymophicBc = new SubClass();
2.多态的条件:有继承关系;子类重写父类方法;父类引用变量指向子类对象。
3.优点:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。当一个新的情景出现时,无须对现有的代码进行改动,而只需要增加一个新的类和新的同名方法。
类的生命周期:
java源文件编译成的class字节码文件,在java虚拟机中运行,java类的生命周期就是指一个class文件从加载到卸载的全过程。
![](http://images2015.cnblogs.com/blog/1067864/201611/1067864-20161122190932550-518245916.png)
1.加载:找到需要加载的类并把类的信息加载到jvm的方法区中,然后在堆区中实例化一个java.lang.Class对象,作为方法区中这个类的信息的入口。Ps:日常我们说的类加载——指的是类的生命周期中加载、连接、初始化三个阶段。
2.连接:连接阶段比较复杂,一般会跟加载阶段和初始化阶段交叉进行,这个阶段的主要任务就是做一些加载后的验证工作以及一些初始化前的准备工作。
3.类的初始化:按照顺序自上而下运行类的变量赋值语句和静态语句。而没有static修饰的赋值语句和执行语句在实例化对象的时候才会运行。
所以,java的静态变量也叫做类变量,它开始于类的创建,结束于类的消亡。非静态变量叫做实例变量,它开始于类的实例的创建,结束语类的实例的消亡。
4.使用:当初始化完成之后,java虚拟机就可以执行Class的业务逻辑指令,通过堆中java.lang.Class对象的入口地址,调用方法区的方法逻辑,最后将方法的运算结果通过方法返回地址存放到方法区或堆中。
类的使用包括主动引用和被动引用。主动引用会引起类的初始化eg:通过new关键字实例化对象、读取或设置类的静态变量。被动引用不会引起类的初始化eg:定义类数组、引用类的常量。
5.卸载:当对象不再被使用时,java虚拟机的垃圾收集器将会回收堆中的对象,方法区中不再被使用的Class也要被卸载,否则方法区(Sun HotSpot永久代)会内存溢出。类的卸载过程其实就是在方法区中清空类信息。