面向对象的语言
java是一种典型的面向对象语言,与面向过程将过程一步步拆解不同,它是一种将所有物体拆分成可描述的内容与行为
类是java中一个很重要的概念,而对象就是在类中提取分离出来的,是类的实例化
类中有三个重要特性:
面向对象的语言
java是一种典型的面向对象语言,与面向过程将过程一步步拆解不同,它是一种将所有物体拆分成可描述的内容与行为
类是java中一个很重要的概念,而对象就是在类中提取分离出来的,是类的实例化
类中有三个重要特性:
1.封装:核心思想就是“隐藏细节”、“数据安全”,将对象不需要让外界访问的成员变量和方法私有化,只提供符合开发者意愿的公有方法来访问这些数据和逻辑,保证了数据的安全和程序的稳定。
2.继承:子类可以继承父类的属性和方法,并对其进行拓展。
3.多态:同一种类型的对象执行同一个方法时可以表现出不同的行为特征。通过继承的上下转型、接口的回调以及方法的重写和重载可以实现多态。
构造方法(构造器 constructor)
构造器也叫构造方法(constructor),用于对象的初始化。构造器是一个创建对象时自动调用的特殊方法,母的时对象的初始化。构造器的名称应该与类的名称一致。java通过new关键字来调用构造器,从而返回该类的实例,是一种特殊的方法。
构造器4个要点:
1.构造器通过new关键字调用!
2.构造器虽然有返回值,但是不能定义返回值类型(返回值的类型肯定是本类),不能在构造器里使用return返回某个值。
3.如果我们没有定义构造器,则编译器会自动定义一个无参的构造函数。如果已定义则编译器不会自动添加
4.构造器的名称必须与类名相同。
public class Point {
double x,y;
public Point(double _x,double _y){
x = _x;
y = _y;
}
public double getDistance(Point p){
return Math.sqrt(x - p.x) * (x - p.x) + (y - p.y) * (y - p.y);
}
}
class Test{
public static void main(String[] args){
Point p = new Point(3.0,4.0);
Point origin = new Point(0,0);
System.out.print(p.getDistance(origin));
}
}
方法的重载
先来看下方法重载(Overloading)的定义:如果有两个方法的方法名相同,但参数不一致,哪么可以说一个方法是另一个方法的重载。 具体说明如下:
- 方法名相同
- 方法的参数类型,参数个不一样
- 方法的返回类型可以不相同
- 方法的修饰符可以不相同
- main 方法也可以被重载
class MyClass {
int height;
MyClass() {
System.out.print("无参数构造函数");
height = 4;
}
MyClass(int i) {
System.out.print("房子高度为 " + i + " 米");
height = i;
}
void info() {
System.out.print("房子高度为 " + height + " 米");
}
void info(String s) {
System.out.print(s + ": 房子高度为 " + height + " 米");
}
}
public class MainClass {
public static void main(String[] args) {
MyClass t = new MyClass(3);
t.info();
t.info("重载方法");
//重载构造函数
new MyClass();
}
}
虚拟机栈,堆,方法区的特点
-
虚拟机栈的特点:
- 栈描述的是方法执行的内存模型。每个方法被调用时都会在栈内创建一个栈帧(用来存储局部变量,操作数,方法出口等)
- JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(用户存放实际参数,局部变量等)
- 栈属于线程私有,不能实现线程间的共享!
- 栈的存储特性是“现金后厨,后进先出”
- 栈是有系统自动分配,速度快!栈是一个连续的内存空间
-
堆得特点:
- 堆用于存储创建好的对象和数组(数组也是对象)
- JVM只有一个堆,被所有的线程贡献
- 堆是一个不连续的内存空间,分配灵活,速度慢
-
方法区(又叫静态区,也是堆)特点:
- 方法区是java虚拟机规范,可以有不同的实现
- JVM只有一个方法区,被所有的线程共享
- 3.方法区实际也是堆,只是用于存储类,常量相关的信息!
- 用来存放程序永远是不变或唯一的内容。(类信息,静态变量,字符串常量等)
垃圾回收机制(GC)
主要针对堆内存回收
- 垃圾回收的过程
- 发现无用的对象
- 回收无用对象占用的内存空间
- 垃圾回收相关算法
- 引用计数法
- 引用可达法(根搜索算法)
java分代垃圾回收机制
虚拟机中划分三个代
虚拟机中的共划分为三个代:年轻代(Young Generation)、年老点(Old Generation)和持久代(Permanent Generation)。其中持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系不大。年轻代和年老代的划分是对垃圾收集影响比较大的
- 年轻代:
所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。年轻代分三个区。一个Eden区,两个Survivor区(一般而言)。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。同时,根据程序需要,Survivor区是可以配置为多个的(多于两个),这样可以增加对象在年轻代中的存在时间,减少被放到年老代的可能。
- 年老代:
在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。
- 永久代:
用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些Class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize= < N >进行设置。
GC有两种类型:Scavenge GC 和 Full GC
- Scavenge GC
一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Scavenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。这种方式的GC是对年轻代的Eden区进行,不会影响到年老代。因为大部分对象都是从Eden区开始的,同时Eden区不会分配的很大,所以Eden区的GC会频繁进行。因而,一般在这里需要使用速度快、效率高的算法,使Eden去能尽快空闲出来
- Full GC
对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个对进行回收,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。在对JVM调优的过程中,很大一部分工作就是对于FullGC的调节。有如下原因可能导致Full GC:
- 年老代(Tenured)被写满
- 永久代(Perm)被写满
- System.gc()被显示调用
- 上一次GC之后Heap的各域分配策略动态变化
其他要点
- System.gc() 是想虚拟机提出建议清理内存
- 程序员无权调用垃圾回收器
- 程序员可以调用System.gc(),该方法只是通知JVm,并不是运行垃圾回收器。尽量少用,会申请启动Full GC,成本高,影响系统性能。
- finalize方法,是java提供给程序员用来释放对象或资源的方法,但尽量少用,java语言自动释放
this关键字
对象创建的过程和this的本质
- 构造方法是创建java对象的重要途径,通过new关键字调用构造器时,构造器也确实返回该类的对象,但这个对象并不是完全由构造器负责创建。创建一个对象分为如下四部
- 分配对象空间,并将对象成员变量初始化为0或空
- 执行属性值得显示初始化
- 执行构造方法
- 返回对象的地址给相关的变量
- this的本质就是 “创建好的对象的地址”! 由于在构造方法调用前,对象已经创建。因此,在构造方法中也可以使用this代表“当前对象”。
this最常的用法
- 在程序中产生二义性之处,应使用this来指明当前对象;普通方法中,this总是指向调用该方法的对象。构造方法中,this总是指向正要初始化的对象
- 使用this关键字调用重载的构造方法,避免想用的初始化代码。但只能在构造方法中用,并且必须位于构造方法的第一句
- this不能用于static方法中
static 关键字
在类中,用static声明的成员变量为静态成员变量,也称为类变量。类变量的生命周期和类相同,在整个应用程序执行期间都有效。它有如下特点:
- 为该类的公用对象,属于类,该类的所有实例共享,在类被载入时被显示初始化
- 对于该类的所有对象来说,static成员变量只有一份。被该类的所有对象共享
- 一般用“类名.类属性/方法” 来调用。(也可以通过对象引用或类名(不需要实例化)访问静态变量)
- 在static方法中不可以直接访问非static的成员