类和对象基础笔记
面向对象的程序设计思想
一切都是对象
就是要使用对象进行程序设计,对象有自己独特的特性、状态和行为。
对象的状态
- 由具有当前值的数据域,又称为属性,的集合构成。
- 状态定义对象是什么
对象的行为
- 由方法的集合定义的。
- 行为定义对象做什么
对象存储到什么地方
- 寄存器:这是最快的存储区,位于处理器内部。但是数量有限,根据需求分配,不能控制。
- 堆栈:位于通用RAM(随机访问存储器) 中,通过上下移动指针分配或释放内存,创建程序时要知道堆栈内所有项的确切生命周期,限制了灵活性,一般是对象引用存储于堆栈中。
- 堆:通用的内存池,也位于RAM区,用于存放所有的Java对象。灵活性很大,需要对象时只需要new一个,执行时会自动在堆里分配存储空间,所以分配和清理需要的时间更多。
- 常量存储:常量直接存放在代码内部,很安全,因为永远不会被改变。如果常量本身会和其他变量隔离开,可以选择将其存放在ROM(只读存储器)中。
- 非RAM存储:如果数据完全存活于程序之外,那么将不受程序的任何控制,程序没有运行也可以存在。比如流对象和持久化对象。
【流对象:对象转换成字节流被发送给另一台机器。持久化对象:对象被存放于磁盘上】。
----这种一般在需要的时候再恢复成常规的,基于RAM的对象。
永远不需要销毁对象
大多数过程型语言都有作用域(scope)的概念。比如在c和c++中,作用域由花括号决定。
而Java对象不具备和基本类型一样的生命周期。当new创建一个Java对象时,它可以存活于作用域之外,而且这个对象会一直保留下去。这时候,Java有一个垃圾回收器,用来监视用new创建的所有对象,并辨别那些不会被引用的对象,释放这些对象的内存空间。
类和对象的不同
类是对象的蓝本。
对象是类的实例。
//Circle类
class Circle{
//数据域(属性)
//若成员是基本数据类型,即使没有进行初始化,Java也会保存他的一个默认值,但不适应于“局部”变量(非字段)
double radius=1.0;
//无参构造方法
Circle(){
}
//有参构造方法
Circle(double newRadius){
radius=newRadius;
}
//方法
double findArea(){
return radius*radius*3.1415;
}
}
初始化
构造方法
构造方法分为有参构造方法和无参构造方法,无疑这两种的差别就是一个有参数一个没有。
构造方法主要作用是完成对象的初始化化工作,能够把定义对象时的参数传给对象的域。
特点
- 方法名必须与所在的类同名
- 没有返回值,void也没有
- 它在一个对象被创建使用new时调用
- 一个类可以有多个构造方法,如果在定义类时没有定义构造方法,则编译系统会自动插入一个无参数的默认构造器,这个构造器不执行任何代码。
- 构造方法可以重载,以参数的个数、类型、顺序。
无参构造方法
class Cilcle(){
Cilcle(){
System.out.println("call no para constructor");
}
}
有参构造方法
class Cilcle{
Circle(double newRadius){
radius=newRadius;
System.out.println("call constructor:radius="+radius);
}
}
调用构造方法
- 在类的内部可以直接使用this.构造方法名()调用构造方法
- 在子类中可以通过super.父类构造方法名()调用构造方法
- 反射机制对于任意一个类都能够知道这个类的所有属性和方法,包括类的构造方法。
默认构造器
如果类中没有构造器,则编译器会自动帮你创建一个默认构造器。没有它的话就没有方法可调用,就无法创建对象。但是如果已经定义了一个构造器,无论是否含有参数,编译器都不会帮你自动创建默认构造器了。
父类构造器与子类的关系
java的初始化顺序是先初始化父类再初始化子类。在调用子类构造器之前,会先调用父类构造器。当子类构造器中没有使用super指定调用父类构造器,则是代表默认调用了父类的无参构造器。但是如果父类包含有参构造器,则在子类构造器中一定要使用super指定调用父类的有参构造。否则会编译错误。
static关键字
当声明一个事物是static时,就意味着这个域或这个方法不会与包含它的那个类的任何对象实例关联在一起, 即使从未创建某个类的任何对象,也可以调用其static方法或访问其static域。
class StaticTest{
static int i=47;
}
public static void main(String[] args) {
// write your code here
StaticTest st1 =new StaticTest();
StaticTest st2 = new StaticTest();
System.out.println(st1.i);//47
StaticTest.i++;
System.out.println(st2.i);//48
}
- 可以看到即使创建了两个StaticTest对象,StaticTest.i也只有一份存储空间,两个对象共用一个i。
- 引用static变量的两种方法:
1、通过一个对象去定位它,比如说说st1.i;
2、通过类名直接引用,比如StaticTest.i;但是这个对非静态成员是不行的,仅适合静态成员,并且是引用static变量的首选方式,它不仅强调了变量的static结构,而且在某些情况下还为编译器进行优化提供了更好的机会。
类似的逻辑也应用于静态方法,通过ClassName.method()对静态方法加以引用。 - static作用于某字段时,肯定会改变数据创建的方式。因为字段对每个类来说都只有一份存储空间,而非static字段则是对每个对象都有一个存储空间
- static作用于某个方法时,一个重要的用法就是在不创建任何对象的前提下就可以调用它。
构造块
构造块分为两种,静态构造块和实例构造块。
静态构造块
在使用类之前实行
static {
...
}
实例构造块
若果在构造方法中,没有this(…)时,插入构造方法前
{
...
}
构造方法与构造块的关系
package consclock;
public class blockInsta {
static {
System.out.print1n("call static block");
}
{
System.out.println("call instance block");
}
public blockInsta(){
System.out.println("call no para constructor");
}
public blockInsta(String m){
System.out.print1n("ca1l constructor:"+m);
}
}
package consclock;
public class blockMain{
public static void main(String[] args) {
blockInsta a=new blockInsta();
//单独运行结果
/*call static block
*call instance block
*call no para constructor
*/
//先调用静态块,然后实例块,最后无参构造
System.out.println();
blockInsta b = new blockInsta("java 有参")
//和上面一起运行结果
/*call instance block
*call constructor:java 有参
*/
//可以看到第二次创建对象是没有调用静态块,但还是调用了实例块,这就是两者区别。
//静态块只会在第一次创建对象(切记一定要使用了new)时调用
//第二个对象和第一个共用同一个内存空间
}
}
如果只是定义,无创建,也是不会调用的
package consclock;
public class blockMain{
public static void main(String[] args) {
blockInsta a;//=new blockInsta();
//这里并没有创建对象,仅仅定义了一下,所以不会有构造方法也不会调用构造块
System.out.println();
blockInsta b= new blockInsta("java 有参")
//和上面一起运行结果
/*
*call static block
*call instance block
*call constructor:java 有参
*/
}
}
属性初始化
- 类的成员变量有默认初始值
- 类的局部变量没有默认初始值
如果类的成员是基本数据类型,即使没有进行初始化,Java也会确保它获得一个默认值,但不适用于局部变量;
- 引用型数据:null
- 数值型:0
- 布尔型:false
- 字符型:’\u0000’
java中没有给方法中的局部变量赋予默认值,如果局部变量没有手动赋值,则会报错