面向过程 :是一种以过程为中心的编程思想,实现功能的每一步,都是自己实现的
面向对象 :是一种以对象为中心的编程思想,通过指挥对象实现具体的功能
public class Student { //定义一个公共类,都可以访问调用该类
// 属性 : 姓名, 年龄
// 成员变量: 跟之前定义变量的格式一样, 只不过位置发生了改变, 类中方法外
String name;
int age;
// 行为 : 学习
// 成员方法: 跟之前定义方法的格式一样, 只不过去掉了static关键字.
public void study(){
System.out.println("学习");
}
}
对于一个类来说,有三种成员:属性 field、方法 method、构造器 constructor。
属性用于定义该类或该类对象包含的数据或者说静态特征。属性作用范围是整个类体。
在定义成员变量时可以对其初始化,如果不对其初始化,Java 使用默认的值对其初始化。
数据类型 | 默认值 |
整型 | 0 |
浮点型 | 0.0 |
字符型 | '\u0000' |
布尔型 | false |
所有引用类型 | null |
属性定义格式:
[修饰符] 属性类型 属性名 = [默认值] ;
方法用于定义该类或该类实例的行为特征和功能实现。方法是类和对象行为特征的抽象。面向对象中,整个程序的基本单位是类,方法是从属于类和对象的。
[修饰符] 方法返回值类型 方法名(形参列表) {
// n 条语句
}
构造器用于对象的初始化
声明格式:
[修饰符] 类名(形参列表){
//n 条语句
}
构造器 4 个要点:
/*
定义一个“点”(Point)类用来表示二维空间中的点(有两个坐标)。要求如下:
可以生成具有特定坐标的点对象。
提供可以计算该“点”距另外一点距离的方法。
*/
class Point { // 定义一个类
double x, y; // 属性
public Point(double _x, double _y) { // 有参构造方法
x = _x;
y = _y;
}
public double getDistance(Point p) { //一个成员方法,返回类型为double
return Math.sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
}
public static void main(String[] args) { // 入口
Point p1 = new Point(3.0, 4.0);
Point origin = new Point(0.0, 0.0);
System.out.println(p1.getDistance(origin));
}
}
构造方法重载(创建不同用户对象)
public class User {
int id; // id
String name; // 账户名
String pwd; // 密码
public User() {
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
public User(int id, String name, String pwd) { // 构造方法重载
this.id = id;
this.name = name;
this.pwd = pwd;
}
public static void main(String[] args) {
User u1 = new User();
User u2 = new User(101, "小七"); // 使用的是有两个参数的构造方法
User u3 = new User(100, "张三", "123456"); // 使用的是三个参数的构造方法
}
}
特点:
类名 对象名 = new 类名();
对象名.成员变量
对象名.成员方法();
示例代码 :
public class TestStudent {
/*
创建对象的格式:
类名 对象名 = new 类名();
调用成员变量的格式:
对象名.变量名
调用成员方法的格式:
对象名.方法名();
*/
public static void main(String[] args) {
// 类名 对象名 = new 类名();
Student stu = new Student();
// 对象名.变量名
// 默认初始化值
System.out.println(stu.name); // null
System.out.println(stu.age); // 0
stu.name = "张三";
stu.age = 23;
System.out.println(stu.name); // 张三
System.out.println(stu.age); // 23
// 对象名.方法名();
stu.study();
// com.itheima.object1.Student@b4c966a
// 全类名(包名 + 类名)
System.out.println(stu);
}
}
总结:
多个对象在堆内存中,都有不同的内存划分,成员变量存储在各自的内存区域中,成员方法多个对象共用的一份
1. 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)
2. JVM 为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)
3. 栈属于线程私有,不能实现线程间的共享!
4. 栈的存储特性是“先进后出,后进先出”
5. 栈是由系统自动分配,速度快!栈是一个连续的内存空间!
1. 堆用于存储创建好的对象和数组(数组也是对象)
2. JVM 只有一个堆,被所有线程共享
3. 堆是一个不连续的内存空间,分配灵活,速度慢!
4. 堆被所有的线程所共享,在堆上的区域,会被垃圾回收器做进一步划分,例如新生代、老年代的划分。
1. 方法区是 JAVA 虚拟机规范,可以有不同的实现。
i. JDK7 以前是“永久代”
ii. JDK7 部分去除“永久代”,静态变量、字符串常量池都挪到了堆内存中
iii. JDK8 是“元数据空间”和堆结合起来。
2. JVM 只有一个方法区,被所有线程共享!
3. 方法区实际也是堆,只是用于存储类、常量相关的信息!
4. 用来存放程序中永远是不变或唯一的内容。(类信息【Class 对象,反射机制中会重点讲授】、静态变量、字符串常量等)
5. 常量池主要存放常量:如文本字符串、final 常量值。
总结 :
当多个对象的引用指向同一个内存空间(变量所记录的地址值是一样的)
只要有任何一个对象修改了内存中的数据,随后,无论使用哪一个对象进行数据获取,都是修改后的数据。
Java 的内存管理很大程度就是:堆中对象的管理,其中包括对象空间的分配和释放。
对象空间的分配:使用 new 关键字创建对象即可
对象空间的释放:将对象赋值 null 即可
任何一种垃圾回收算法一般要做两件基本事情:
1. 发现无用的对象
2. 回收无用对象占用的内存空间。
垃圾回收机制保证可以将“无用的对象”进行回收。
无用的对象指的就是没有任何变量引用该对象。Java 的垃圾回收器通过相关算法发现无用对象,并进行清除和整理。
引用计数法
堆中的每个对象都对应一个引用计数器,当有引用指向这个对象时,引用计数器加1,而当指向该对象的引用失效时(引用变为 null),引用计数器减 1,最后如果该对象的引用计算器的值为 0 时,则 Java 垃圾回收器会认为该对象是
无用对象并对其进行回收。优点是算法简单,缺点是“循环引用的无用对象”无法别识别。
普通方法中,this 总是指向调用该方法的对象。
构造方法中,this 总是指向正要初始化的对象。
this()调用重载的构造方法,避免相同的初始化代码。但只能在构造方法中用,并且必须位于构造方法的第一句。
this 不能用于 static 方法中。
this 是作为普通方法的“隐式参数”,由系统传入到方法中。
public class TestThis {
int a, b, c;
TestThis() {
System.out.println("正要初始化一个Hello对象");
}
TestThis(int a, int b) {
// TestThis(); //这样是无法调用构造方法的!
this(); // 调用无参的构造方法,并且必须位于第一行!
a = a;// 这里都是指的局部变量而不是成员变量
// 这样就区分了成员变量和局部变量. 这种情况占了this使用情况大多数!
this.a = a;
this.b = b;
}
TestThis(int a, int b, int c) {
this(a, b); // 调用带参的构造方法,并且必须位于第一行!
this.c = c;
}
void sing() {
}
void eat() {
this.sing(); // 调用本类中的sing();
System.out.println("你妈妈喊你回家吃饭!");
}
public static void main(String[] args) {
TestThis hi = new TestThis(2, 3);
hi.eat();
}
}
注意 : this代表当前调用方法的引用,哪个对象调用的方法,this就代表哪一个对象
静态变量/静态方法生命周期和类相同,在整个程序执行期间都有效。它有如下特点:
为该类的公用变量,属于类,被该类的所有实例共享,在类载入时被初始化。
static 变量只有一份。
一般用“类名.类变量/方法”来调用。
在 static 方法中不可直接访问非 static 的成员。
public class TestStatic {
int id; // id
String name; // 账户名
String pwd; // 密码
static String company = "北京xxx"; // 公司名称
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, "高xx");
TestStatic.printCompany();
TestStatic.company = "北京阿里";
TestStatic.printCompany();
}
}
构造方法用于对象的普通属性初始化。
静态初始化块,用于类的初始化操作,初始化静态属性。
在静态初始化块中不能直接访问非 static 成员。
public class TestStatic2 {
static String company; // 公司名称
static {
System.out.println("执行类的初始化工作");
company = "北京xxx";
printCompany();
}
public static void printCompany() {
System.out.println(company);
}
public static void main(String[] args) {
}
}
包(package)相当于文件夹对于文件的作用。用于管理类、用于解决类的重名问题。
1. 通常是类的第一句非注释性语句。
2. 包名:域名倒着写即可,便于内部管理类。
com.oracle.test;
com.itbaizhan.gao.test;
com.itbaizhan.gao.view;
如果要使用其他包的类,需使用 import,从而在本类中直接通过类名来调用,否则就需要书写类的完整包名和类名。
Java 会默认导入 java.lang 包下所有的类,因此这些类我们可以直接使用。
如果导入两个同名的类,只能用包名+类名来显示调用相关类:
java.util.Date date = new java.util.Date()
静态导入(static import): 其作用是用于导入指定类的静态属性和静态方法,这样我们可以直接使用静态属性和静态方法。
package com.itbaizhan;
import static java.lang.Math.*;//导入Math类的所有静态属性
import static java.lang.Math.PI;//导入Math类的PI属性
public class Test2 {
public static void main(String[] args) {
System.out.println(PI);
System.out.println(random());
}
}