面向对象
1.简介:
面向对象由面向对象分析(OOA),面向对象设计(OOD),面向对象编程(OOP)三部分组成;
基本思想是使用类,对象,继承,封装,消息等进行程序设计。从现实世界中客观存在的事物出发来构造软件系统,在系统构造中尽可能的运用人类的自然段思维方法,强调直接以现实世界中的事物为中心来思考问题,认识问题。并根据这些事物的本质特点,把他们抽象地表示为系统中的类,作为系统的基本构成单元,使得软件系统的组件可以直接映射现实世界,并保持客观世界事务及其相互关系的本来面貌。
2.面向对象的类
在面向对象设计中类是最小的程序单元,类可以生成系统中的多个对象。这些对象直接映射成客观世界的各种事物(实例)。
3.类与对象
1)类的定义语法:
[访问权限修饰词] class 类名{
成员变量 / 属性 / 字段 / field;
方法;
}
1.访问权限修饰词:
- 在一个.java源文件里定义的普通类,修饰词只能是public或者默认的
2.类名:
- 大驼峰命名法
3.成员变量:
- 用来描述对象的共同特征,也就是状态数据
- 格式,即变量的声明
4. 成员方法:
- 用来描述对象的共同的行为, 或者用来操作状态数据
- 指的都是不带static修饰的方法
2)属性/成员变量/字段
1.从概念或叫法上看:成员变量 = 属性 = 字段(field),即成员变量是用来表示属性的。
2.属性是类的一个组成部分,一般是基本数据类型,也可是引用类型(对象,数组)。比如我们定义猫类的 int age 就是属性。
3)注意事项和细节说明
1) 属性的定义语法同变量,示例:访问修饰符 属性类型 属性名;
控制属性的访问范围
有四种访问修饰符 public, proctected, 默认, private ,后面我会详细介绍
2) 属性的定义类型可以为任意类型,包含基本类型或引用类型
3) 属性如果不赋值,有默认值,规则和数组一致。具体说: int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000, boolean false ,String null
4)类与对象的关系:
1) 类是抽象的,概念的,代表一类事物, 比如人类,猫类.., 即它是数据类型.
2) 对象是具体的,实际的,代表一个具体事物, 即 是实例.
3) 类是对象的模板,对象是类的一个个体,对应一个实例
4)创建对象的过程通常称之为实例化
构造方法
1.与普通方法的区别
语法不同:
1、构造方法没有返回值,因为构造函数的作用是初试化对象,而不是返回一个值,如果在构造器前面加上返回值类型,那么该函数就会变为一个普通函数。
2.构造方法的名字必须要和类名相同;
3.构造方法不能使用static修饰词修饰。
2.执行时机不同:
普通的方法可以随时调用,构造方法是在实例化对象的时候调用执行的。
即 new 关键词调用
3.构造方法可以重载
构造方法重载时只需使参数类型列表不同即可;
如果程序员在定义类时不提供任何构造器,则系统会自动生成一个无参构造器;
如果程序员定义了构造器则,系统不在提供,想要使用无参构造器的话程序员可以自己定义无参构造器。
4.定义类:
该类提供了一个无参构造器和带两个参数的构造器
5.构造器的调用:
public class test0804 { public static void main(String[] args) { // 实例化对象,调用无参构造器 PersonTest2 personTest2 = new PersonTest2(); System.out.println(personTest2.name); System.out.println(personTest2.age); // 实例化对象,调用有参构造器 PersonTest2 personTest21 = new PersonTest2("张三",20); System.out.println(personTest21.name); System.out.println(personTest21.age); } } class PersonTest2{ public String name; public int age; public PersonTest2(){ System.out.println("无参构造器被调用"); } public PersonTest2(String name,int age){ this.name = name; this.age = age; } }
不给成员变量赋值时,使用的是默认值,如上所示;
6.构造器中调用其他构造器:
可以用this关键字调用同一类中,其他的构造器,优点就是能少一点代码量;
注意:1.使用this关键字调用构造方法的时候,this()必须写在首行首句,前面不能有任何内容;
2.在进行构造方法的调用时,不能出现循环调用,递归也不行。
public class test0804 {
public static void main(String[] args) {
// 实例化对象,调用无参构造器
PersonTest2 personTest2 = new PersonTest2();
System.out.println(personTest2.name);
System.out.println(personTest2.age);
// 实例化对象,调用有参构造器
PersonTest2 personTest21 = new PersonTest2("张三",20);
System.out.println(personTest21.name);
System.out.println(personTest21.age);
}
}
class PersonTest2{
public String name;
public int age;
public String gander;
public PersonTest2(){
System.out.println("无参构造器被调用");
}
public PersonTest2(String name,int age){
this.name = name;
this.age = age;
}
public PersonTest2(String name,int age,String gender){
// 使用关键字this调用上面两个参数的构造器,
// 只能是在形参多的构造里调用形参少的
this(name,age);
this.gander = gender;
}
}
实例练习:
public class A0804_2 { public static void main(String[] args) { User user = new User("张三","11111","12313@yc.com"); // 有参传参,没参不要乱传参 user.showInfo(); User user1 = new User("李四","123456"); user1.showInfo(); } } class User { public String name; public String password; public String email; public User(String name,String password){ this.name = name; this.password = password; this.email = "用户名@yc.com"; } public User(String name, String password,String email){ this(name, password); // 不传值时使用的是默认值 this.email = email; } public void showInfo(){ System.out.println("name:" + name); System.out.println("password:" + password); System.out.println("email:" + email); } }
代码块:
静态代码块:
语法:
static {
方法体;
};
static {
System.out.println("静态代码块");
System.out.println("----太帅了----");
}
与构造器并列
特点:静态代码块只执行一次;
静态代码块中的代码不需要实例化就能够被调用;
静态代码块无论在哪都是被第一个调用的;多个静态类会根据顺序依次调用;
方法体中不能定义任何静态代码块;
静态代码块常用来执行类属性的初始化;
静态代码块不能访问普通变量。
作用:一般用于加载静态资源到内存中,或者,统计一个类型创建了多少个对象。
非静态代码块、普通代码块:
{
代码片段;
};
{
System.out.println("小胖太帅了");
System.out.println("樊振东太帅了");
System.out.println("动态代码块被调用");
}
封号“;” 可写可不写
动态代码块:当构造器执行一次,动态代码块就被调用一次,可用于计算构造器被执行的次数等。
代码示例:
public class Test_3 { int a; int b; int c; { System.out.println("小胖太帅了"); System.out.println("樊振东太帅了"); System.out.println("动态代码块被调用"); } static { System.out.println("静态代码块"); System.out.println("----太帅了----"); } public Test_3(){ System.out.println("无参构造器"); } public Test_3(int a,int b,int c){ this.a = a; this.b = b; this.c = c; System.out.println("有参构造器"); } public String toString(){ return "a=" + a + " b=" + b + " c=" + c; } public static void main(String[] args) { Test_3 test3 = new Test_3(1,2,4); System.out.println(test3);//默认调用toString方法 Test_3 test1 = new Test_3(2,3,4); System.out.println(test1);//默认调用toString方法 } }
JVM内存管理机制
在JVM(java虚拟机)中,每个应用程序拥有一个独立的JVM实例,每个JVM实例都是一个独立的进程,拥有自己的内存空间、线程和资源。这意味着每个应用程序的JVM都是相互隔离的,他们之间不会相互干扰。
每个线程都有属于自己唯一的栈区,一个栈区代表一个线程。
虚拟机栈
栈帧:先进后出,后进先出
1.栈帧是支持虚拟机进行方法调用和方法执行的数据结构,他是虚拟机运行时虚拟机栈的栈元素。
2.JVM的栈由许多的栈帧组成,每调用一个方法(main方法或其他方法),JVM就压入一个新的栈帧到栈中;
3.存储方法:当变量为基本数据类型时,直接存储值,当变量为引用类型时,存储的是指向具体对象的引用(指的是在堆中的地址)。
4.当方法返回时,这个栈帧就会从栈中弹出。
堆
1.堆是用来存储对象本身和数组的,在JVM中只有一个堆,因此,堆是被所有线程共享的。
此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。
2.数组在堆中存储的是数组对象,并将其数组元素存放在数组对象的空间中,并返回数组的首地址给栈中的数组变量;
3.类在堆中存储的是实例化对象,并将其成员变量,构造方法,成员方法存放在实例化对象的空间中,且有一一对应的堆地址,并返回其堆地址给栈区的对象变量。
4.对象在堆中存储模式为:在堆中开辟一个空间存储对象,且对应一个堆地址,并将其对象的信息存储在这个开辟的空间中,且每一条信息在开辟的空间中对应一个地址
5.堆中的垃圾来源:当程序运行在栈中的引用变量作用域之外时,引用变量在栈中会被释放,但是引用变量在堆中对应的对象或数组占用的空间并不会释放,当没有引用变量指向堆中的对象或数组时,这时候就成了堆中的垃圾,且不能使用,但是占堆中的内存,当然,在后面会被垃圾回收期释放掉,但是其时间不确定,这也是Java比较占内存的原因。
6.从jdk1.7开始,字符串常量池在堆中
方法区
方法区是一块所有线程共享的内存逻辑区域,在JVM中只有一个方法区,用来存储一些线程可共享的内容,它是线程安全的,多个线程同时访问方法区中同一个内容时,只能有一个线程装载该数据,其它线程只能等待。
方法区可存储的内容有:类的全路径名、类的直接超类的权全限定名、类的访问修饰符、类的类型(类或接口)、类的直接接口全限定名的有序列表、运行时常量池(字段,方法信息,静态变量,类型引用(class))等。
加载类信息:将程序所有的类(main类或其它的类)的信息(类的属性信息,方法信息)加载进方法区的加载类信息的内存区域中
值传递和地址传递
基本数据类型,值传递: 就是把字面量传给对方;
引用数据类型,地址传递:就是把声明的对象的地址,或引用对象的在堆中地址传给对方;