Java面向对象
1.对象Tips
(1)对象是一种特定类型的数据;
(2)属性:对象所具有的各种静态特征;对象有什么~;
(3)方法:对象具有的各种动态行为;对象能做什么~;
2.类的成员属性,即使没有初始化,其也是有初始值的;
(1)即对于一般的方法中定义的变量,如果没有初始化便打印,其会报错的:
(2)但对于类的成员属性,即使没有初始化也是可以打印的:
可见,即使没有初始化,int类型的类成员属性默认初始值为0;同理,String类型的默认值为null;double类型的默认值为0.0;
3.单一职责原则
SRP(Single Responsibility principle):一个类应该只有一个发生变化的原因。
一个类所包含功能的确立和划分,需要根据具体开发过程中团队的原则和业务需求来确定;自然在这个过程中控也提高单一职责原则的设计能力。
4.new关键字分析
Cat one = new Cat();
实例化对象的过程可以分为两部分:
(1)声明对象:Cat one
(2)实例化对象 new Cat()
声明对象:Cat one是在内存的栈空间中开辟了一块区域,取名叫做one;但在这个时候还不是一个有效的对象,此时one还是个空的,里面什么东西都没有;还不能去使用它
实例化对象:new Cat()是在内存的堆空间中开辟了一块空间,完成了这个对象相关信息的初始化操作;
声明对象实在栈里面,实例化对象是在堆里面,这是两个完全不同的空间。
1)Java的内存分配管理机制是基于JVM来进行的;
2)栈是内存中的一块区域,主要用于保存局部变量的值;(Cat cat 新建的这个对象变量也是一个局部变量,这个局部变量存储的是一个地址,指向在堆中,实际的对象实体)堆是内存中的另一块区域,主要用于存放一些动态产生的数据;
3)无论是通过基本数据类型声明的变量还是通过引用类型声明的,他们都是可以出现在栈中。只是 ,基本数据类型的变量是在栈中直接保存所对应的值;而引用数据类型则是在栈和堆中各占一块内存;
如上:Cat one = new Cat();分别在栈和堆中开辟了两个内存空间,然后,将堆空间里开辟的内存空间的地址,放到栈中开辟的内存空间中;这个是通过“=”赋值符号,将声明的对象指向了实例化的具体空间。
注:在Java中,每次使用 new Cat(),就代表在内存中开辟了一块新的空间。
5.堆和栈简述
(1)Java程序是运行在JVM上的,JVM作为Java程序和操作系统之间的桥梁;Java内存分配是基于JVM进行的;
(2)栈:每个方法在执行时,都会创建一个栈帧,用于存储局部变量表、操作数、动态链接、方法的出口信息等;(我的理解:一个方法可能会涉及到新建对象,使用该对象的类属性,新建局部变量等,这样就会在栈和堆中开辟空间,存储方法所用到的这些东西。。即方法执行时,会创建一个‘临时’的栈帧)。
栈中所存储的多用于保存局部信息的值,譬如:方法体中基本数据类型定义的变量、对象的引用(也称对象变量,Cat cat的这个cat)等。当局部作用范围结束时,栈内信息立即自动释放。 (这两段话,结合下面的实例,辅助理解,还ok)
(3)堆:用来存放动态产生的数据,比如new出来的对象。当对象使用结束,并确定已无实例(比如对象变量)引用指向堆空间时,JVM才会依据相关垃圾回收机制进行资源回收,完成堆内资源释放,也就是说,并不是方法结束,方法内涉及到的堆空间就会立即释放,这与栈的管理方式不同。
注:创建出的对象只包含属于各自的成员变量,并不包含成员方法。因为同一个类(的不同实例对象)拥有各自的成员变量(),(不同的实例对象)存储在堆中不同的位置,但是同一类的不同实例之间共享该类的方法,并不是每创建一个对象就把成员方法复制一次。(这儿理解一下;类加载后的存储位置&成员方法的存储位置?)
下面一个实例:结合这个实例,配合上面的话,整体理解下:
(执行流程第4步和第5步,均体现栈的,当局部作用范围结束时,栈内信息立即自动释放)
注:这个例子没有体现出来,new出来的对象的属性的值,比如上面one.name = “花花”,这个name也是存储在one这个实例对象在堆中的空间中的。
这个实例可以多瞅瞅,自然熟能生巧,加深理解。
6.对象(类)作为引用数据类型,在赋值、更改时的情况
(1)对象是引用数据类型,这区别于基本数据类型
(2)下面的实例中,Cat two = one;后,栈中two变量存储的也是栈中one变量的值(即two指向的也是one在堆中对象实例的内存地址)
7.new Cat.run()省略对象声明的写法;
可以这样写(以目前经验来看,不建议这么些)
8.构造方法Tips,瞅瞅就行
(1)构造方法:又称构造函数、构造器;
(2)构造方法在类外被调用时,需配合new关键字,不能被对象单独调用;
(3)构造方法名与类名相同,且没有返回值,( 不能用int,String等,自然也不能用void )其语句格式如下:
(4)构造方法只能在对象实例化(配合new关键字)的时候调用;
(5)当没有指定(自己写)构造方法时,系统会自动添加无参构造方法;
(6)当指定构造方法,无论是有参、无参的构造方法,都不会自动添加无参的构造方法;
(7)一个类可以有多个构造方法;
(8)通常,通过构造方法来完成类中属性的实例化操作
看下面一个错误的例子:
事实也确实如此:
但对于上面的例子改一下之后,结果却正确赋值了;
其原因是,Java有一个【 就近原则 】,在Cat类的有参构造方法中,两种情况下, i =i和 i=m,红色的i,会寻找最近的i变量作为其指向。
第一情况,其找的是:这个时候,就无法对类中的属性就行实例化操作了
第二种情况,其找的是:
所以, i =i失败了,而 i =m成功了。即改名字,可以成功赋值。
其实,使用this关键字,可以很好地解决这个问题。
9.this关键字
this代表的时当前对象,谁调用了当前对象,谁就是this,即Cat cat = new Cat();中,new Cat()代表当前对象,cat调用了当前对象,所以this就是cat。
this也可以理解为指向当前对象的一个引用;。通过this如下的操作之后,由此引起的变化就会反馈到Cat cat = new Cat();的cat所指向的对象中
注:this还能这么用:这样,对象调用run方法时,this.eat()中的this代表当前对象,即会调用eat中的方法,和cat.eat()效果一样。即this代表当前对象。
10.就近原则实例
这个实例和上面的例子相同,算是重复说明了,看看就行
运行结果:
解决方案:
或:
11.this关键字应用
关于this的一点总结:
(1)访问属性:大部分时候,类的方法访问成员属性时无需使用this,但如果方法里存在局部变量和成员属性同名,但程序又需要在该方法里访问成员属性时,则必须使用this进行调用;
(2)调用方法:大部分时候,类的成员方法访问同类中的其他成员方法时,this关键字可加可不加,效果相同。
(3) 同一个类的构造方法之间,可以通过this();的方式互相调用
注:
1)this()必须放在第一行;
2)通过this调用本类中带参或无参构造方法,调用带参构造方法时,需要按顺序传入设定的参数;
3)在一个构造方法内只能调用一个构造方法;
__疑问:构造方法内调用构造方法,这种技术的应用场景是? __
4)不能在类的普通成员方法内通过this调用构造方法,(因为这看起来了会有点违反原则)