构造方法重载
含参不含参
public class Point {
double x,y;
Point(double _x,double _y){
x=_x;
y=_y;
}
Point(){
}
}
Java虚拟机内存模型
虚拟机的内存可以分为三个区域:栈stack、堆heap、方法区method area
栈:
栈里放的是要执行,或者正在执行的方法
- 虚拟机会为每一个进入栈的方法分配一个栈帧
- 虚拟机为每一个线程创建一个栈,用于存放该方法的信息(局部变量、实际参数)
- 栈属于线程私有,不能实现线程之间共享
- 栈的存储特性:“先进后出,后进先出”
- 栈是由系统自动分配,速度快,栈是一个连续的内存空间
堆:
堆里放的是创建好的对象和数组(数组也是对象)
- 虚拟机只有一个堆,被所有线程共享
- 堆在内存的存储方式是不连续的,所以分配灵活,速度慢
- 堆被所有线程共享,被创建很多个对象,垃圾回收器会做进一步规划,把长时间不用的对象回收,就被划分为年轻代、老年代
方法区:
方法区里放着的是唯一的实体代码,也就是各种蓝图(类)、常量池、静态的类、方法
- 方法区是javaJVM的规范,可以有不同的实现
- JDK7以前是“永久代”
- JDK7部分去除“永久代”,静态变量、字符串常量池都挪到了堆内存中了
- JDK8是“元数据空间”和堆结合起来,但依然存在
- JVM只有一个方法区,被所有栈共享
- 方法区实际也是堆,只存储类、常量相关的信息
- 存放永远不变的内容,类信息、静态变量、字符串、常量等
- 常量池中主要存放:字符串、final常量值
垃圾回收机制
Java引入垃圾回收机制,就是为了提高开发效率,程序员不需要过多的注重内存管理机制
内存管理
内存管理很大程度就是:堆中对象的管理,包括对象空间的分配和释放
对象空间的分配:使用new关键字创建对象
释放:把对象赋值null即可
垃圾回收过程
任何垃圾回收算法一般做两个事:
- 发现无用的对象
- 回收无用对象占用的空间
发现是由java的垃圾回收器通过相关算法发现无用对象、进行清除整理。
垃圾回收相关算法
- 引用计数算法
- 引用可达法(根搜索算法):也就是从一个节点GC ROOT(当前时刻存活的对象)开始,找对应的引用节点,然后在找到的这个节点上再找引用节点,直到所有节点都没引用了,其他的节点就被视为无用节点。
大概说一下引用计数算法
就是创建的每个对象都有一个引用计数,每有一个变量引用了该对象,引用数加1,取消引用了(null),引用数-1
特殊情况:这种垃圾无法识别
对象AB互相引用,即使外面ObjA、B停止引用了,但他俩换在互相引用,识别不了
通用的分带垃圾机制
这是在堆里面的东西,现在Edem区存放对象,执行一次Minor GC,清理年轻代,然后Edem区的无用对象会被清理,有用对象会到下一个survivor区,然后在1区,再执行Minor GC,清除无用对象转至2区,然后再转回1区,连续15次以上,就会被转入年老代,通过Major GC清理
Full GC清理年轻代、年老代、和永久代(里面存着类信息,静态区等等)
内存泄露
指堆内存中由于某种原因程序未释放,造成内存浪费,导致运行速度减慢甚至系统崩溃
原因
1.创建大量无用对象
2.静态集合类的使用
就是大量使用static标签,这些对象或者方法属性长时间不会被释放
3.各种连接对象(IO流对象、数据库连接对象、网络连接对象)未关闭
4.监听器的使用不当
其他要点
- 程序员无权调用垃圾回收器
- 程序员可以调用System.gc(),该方法只是通知JVM,并不是运行垃圾回收期(Full GC)。尽量少用,会申请Full GC,成本高,影响系统性能
- Object对象的finalize方法,是Java提供给程序员用来释放对象或资源的方法,但尽量少用
this
在每一个对象里都有一个this,他存储着自身对象的地址,调用this.属性就是调用自身,这在方法中会使用,传入的参数复制给this.属性
static
带有static标签的属性和方法属于类,属性不会随着对象的创建而创建,在程序的开始会自动创建类信息里面会带着static的属性、方法
静态初始块
public class TestStatic {
int id;
String name;
static String company = "北京尚学堂";
static {
//通过static{}来对静态属性初始化赋值
System.out.println("执行类的初始化工作");
company="腾讯山西太原分部";
printCompany();
}
public TestStatic(int id,String name){
this.id=id;
this.name=name;
}
public void login(){
System.out.println(name);
}
public static void printCompany(){
//login();
System.out.println(company);
}
public static void main(String[] args) {
TestStatic u = new TestStatic(101,"张小八");
TestStatic.printCompany();
TestStatic.company="北京腾讯分部";
TestStatic.printCompany();
}
}
变量的分类和作用域
类型 | 声明位置 | 从属于 | 声明周期(作用域) |
---|---|---|---|
局部变量 | 方法或语句块内部 | 方法/语句块 | 方法调用结束 |
成员变量 (实例变量) |
类内部、方法外部 | 对象 | 对象创建,成员变量随之创建 对象消失,成员变量随之消失 |
静态变量 (类变量) |
类内部、static修饰 | 类 | 类被加载,静态变量就有效 |
包机制
就是文件夹,用于管理类、解决重名问题
package point;
final关键词
认识Object.toString()、重写
public class TestObject extends Object{
String name;
String pwd;
@Override
public String toString() {
return "name='" + name +", pwd='" + pwd ;
}
public static void main(String[] args) {
TestObject a = new TestObject();
System.out.println(a);
}
}
==和Object.equals()
"=="代表双方是否相同,如果是基本类型就是值相等,如果是引用类型就是地址相等,就是表示是同一对象。
equals()默认和==是一样的,但是对这个方法进行重写,比如比较两个对象的所有属性是否相同,是就说这两个对象是相等的。
关键字super
.
先调用了父类子类的static();
访问权限修饰符
接口
jdk8以后,接口允许默认方法,静态方法
默认方法
public interface TestDefault {
void printInfo();
default void more(){
System.out.println("more,测试默认方法");
}
}
class TestDefault1 implements TestDefault{
@Override
public void printInfo() {
System.out.println("通过接口实现的方法");
}
@Override
public void more() {
System.out.println("我重写了more默认方法");
}
}