面向对象的三大特征

封装
继承
多态
所有面向对象的编程语言都有这三大特征

采用面向对象的方式开发一个软件,生命周期当中:【整个生命周期中贯穿使用OO面向对象方式】
面向对象的分析:OOA
面向对象的设计:OOD
面向对象的编程:OOP

类和对象的概念

什么是类?
类在现实世界中是不存在的,是一个模板,是一个概念,是人类大脑思考抽象的结果。
类代表了一类事物
在现实世界中,对象A与对象B之间具有共同特征,进行抽象总结出一个模板,这个模板被称为类。
什么是对象?
对象是实际存在的个体。现实世界当中实际存在。

描述一下整个软件开发的过程:
程序员先观察现实世界,从现实世界中寻找对象

寻找了N多个对象之后,发现所有的对象都有共同特征

程序员在大脑中形成了一个模板【类】

Java程序中有了类的定义

然后通过类就可以创建对象

有了对象之后,可以让对象直接协作起来形成一个系统

类—【实例化】---->对象

对象又被称为实例/instance

对象–【抽象】----->类

重点:
类描述的是对象的共同特征。
共同特征例如:身高特征
这个身高特征在访问的时候,必须先创建对象,通过这个对象去访问这个特征。
因为这个特征具体到某个对象上之后,值不同。有的对象身高1.80,有的对象身高2.80.

一个类主要描述什么信息呢?
一个类主要描述的是 状态 + 动作
状态信息:名字、身高、性别、年龄
动作信息:吃、唱歌、跳舞、学习

状态—>一个类的属性
动作—>一个类的方法

类{
属性;//描述对象的状态信息
方法;//描述对象的动作信息
}

注意 :
状态和动作当具体到某个对象上之后,发现最终的结果可能不一样
对象和对象之间有共同特征,但是具体到对象之后有数据的差异。

类的定义【从这这里开始编写代码】
语法结构:

[修饰符列表] class 类名{
属性;
方法;

}

学生类,描述所有学生对象的共同特征:
学生对象有哪些状态信息:
* 学号【int】
* 名字【String】
* 性别【boolean】
* 年龄【int】【年龄是一个属性,年龄是一个数据,是数据就应该有数据类型】
* 住址【String】

学生对象有哪些动作信息:
* 吃饭
* 睡觉
* 学习
* 玩
* 唱歌
* 跳舞

重点:属性通常是采用一个变量的形式来完成定义的。
int no;
int age;
String name;
String address;
boolean sex;

  • java语言中包括两种数据类型:
  • 基本数据类型
    byte
    short
    int
    long
    float
    double
    boolean
    char

  • 引用数据类型
    String.class SUN提供的
    System.class SUN提供的

    Student.class 程序员自定义的
    User.class 程序员自定义的
    Product.class 程序员自定义的
    Customer.class 程序员自定义的

  • java语言中所有的class都属于引用数据类型。

//学生类
//学生类是一个模板
//描述了所有学生的共同特征【状态+行为/动作】
//当前类只描述学生的状态信息【属性】
//Student是类,是引用数据类型,类型名:Student
public class Student{
	
	//类体=属性+方法
	
	//属性【存储数据采用变量的形式】
	//由于变量定义在类体之内,方法体之外,所以这种变量被称为“成员变量”
	//所有学生都有学号信息
	//但是每一个学生的学号信息是不同的
	//所以,要访问这个学号,就必须创建一个对象,通过对象来访问学号这个信息
	//学号信息不能通过“类”直接去访问,所以,这种成员变量又被称为“实例变量”
	//对象又被称为实例,实例变量又被称为对象变量。【对象级别的变量】
    //不创建对象,这个no变量的内存空间是不存在的,只有创建了对象,这个no变量的内存空间才会被创建
	
	int no;
	
	
	String name;
	

	boolean sex;
	

	int age;
	

	String addr;
	
	
	
	
}

/*
	成员变量未赋值,系统会给默认值

	数据类型				默认值
	--------------------------------
	byte short int long 	  0
	float double              0.0
	boolean                  false
    char                     \u0000
	引用数据类型             null空值

*/




对象的创建和使用

public class OOTest01{
	
	public static void main(String[] args){
		
		int i=10;
		//int是基本数据类型
		//i是变量名
		//10是一个int类型的字面值
		
		
		//通过一个类可以实例化N个对象
		//实例化对象的语法: new 类名();
		//new是java语言中的一个运算符
		//new运算符的作用是创建对象,在JVM中的堆内存开辟新的内存空间
		//方法区内存:在类加载的时候,class字节码代码片段被加载到该内存空间中
		//栈内存(局部变量):方法代码片段执行时,会给该方法分配内存空间,在栈内存中压栈
		//堆内存:new的对象在堆内存中存储
		
		//new Student();
		//Student是一个引用数据类型
		//s是变量名,
		//new Student()是一个学生对象
		//s是一个局部变量,【在栈内存中存储】
		//什么是对象?new运算符在堆内存中开辟的内存空间就是对象
		//什么是引用?引用是一个变量,只不过这个变量中保存的是另一个java对象的内存地址
		//对于java语言,程序员不能直接操作堆内存,java中没有指针,不像C语言
		//对于java语言,程序员只能通过“引用”来访问堆内存中对象内部里的实例变量
		
		Student s=new Student();
		
		
		//访问实例变量的语法格式:
		//读取: 引用.变量名
		//修改: 引用.变量名=值
		
		/*
		int stuNo=s.no;
		String stuName=s.name;
		int stuAge=s.age;
		boolean stuSex=s.sex;
		String stuAddr=s.addr;
		
		System.out.println("学号 ="+stuNo);
		System.out.println("姓名 ="+stuName);
		System.out.println("年龄 ="+stuAge);
		System.out.println("性别 ="+stuSex);
		System.out.println("住址 ="+stuAddr);
		
		输出默认值
		学号 =0
		姓名 =null
		年龄 =0
		性别 =false
		住址 =null
		*/
		
		System.out.println(s.no);
		System.out.println(s.name);
		System.out.println(s.age);
		System.out.println(s.sex);
		System.out.println(s.addr);
		
		System.out.println("------------------------------------");
		
		s.no=10;
		s.name="jack";
		s.age=20;
		s.sex=true;
		s.addr="北京";
		
		System.out.println(s.no);
		System.out.println(s.name);
		System.out.println(s.age);
		System.out.println(s.sex);
		System.out.println(s.addr);
		
		//再次实例一个全新的对象,
		//stu是一个引用
		//stu同时也是一个局部变量
		//Student是变量数据类型
		Student stu=new Student();
		
		System.out.println(stu.no);
		System.out.println(stu.name);
		System.out.println(stu.age);
		System.out.println(stu.sex);
		System.out.println(stu.addr);
		
		
		//编译报错,no是实例变量,不能直接采用“类名”的方式访问
		//因为no是实例变量,对象级别的变量,变量存储在java对象中,
		//只有先有对象,通过对象才能访问no这个实例变量,不能直接通过“类名”来访问
		//创建对象-用引用来赋值-访问引用
		//System.out.println(Student.no);
	}
	
}

/*
	局部变量在栈中存储,
	成员变量中的实例变量在堆内存的java对象内部存储

	实例变量是一个对象一份,100个对象就有100份
*/

以上程序执行的内存分析图
在这里插入图片描述


//家庭住址类
public class Address{
	
	//属性【成员变量之实例变量】
	
	//城市
	//String是一种引用数据类型,city是一个变量名,属于实例变量
	//city是一个引用:保存内存地址的一个变量,这个变量保存内存地址指向了堆内存当中的对象
	String city;
	
	//街道
	String street;
	
	//邮编
	String zipcode;
	
}

//用户类
public class User{
	
	//属性【以下都是成员变量之实例变量】
	
	//用户编号
	//int是基本数据类型:整数型
	//no是一个实例变量
	int no;
	
	//用户名
	//String是引用数据类型:代表字符串
	//name是一个实例变量
	//name是一个引用
	String name;
	
	//家庭住址
	//Address是引用数据类型:代表家庭住址
	//addr是一个实例变量
	//addr是一个引用
	Address addr;
	

}

//测试类
public class OOTest02{
	
	public static void main(String[] args){
		
		//创建一个User对象
		//u是一个局部变量
		//u是一个引用
		//u是保存内存地址指向堆内存的User对象
		User u=new User();
		
		//输出User变量内部实例变量的值
		System.out.println(u.no);//0
		System.out.println(u.name);//null
		System.out.println(u.addr);//null
		
		//对User对象内的实例变量值进行修改
		u.no=110;
		u.name="jack";//注意:"jack"实际上是一个java对象,是String对象
		
		u.addr=new Address();
		//在此注意:addr它是一个Address类型的变量。不是什么字符串之类的。
		//只能用创建对象的方式来进而访问它。
		//String比较特殊,直接加字符串就行,但是本质上还是在堆内存中创建了一个String对象
		
		//单独对u的addr进行输出。
		//addr这个实例变量会创建一个Address对象,详见图。
		//在main方法中,我只能看见一个引用“u”。
		System.out.println(u.name+"居住的城市是:"+u.addr.city);
		System.out.println(u.name+"居住的街道是:"+u.addr.street);
		System.out.println(u.name+"邮编:"+u.addr.zipcode);
		
		//改变具体的addr内容。
		//只要把整个儿的复制过来修改就行
		u.addr.city="北京";
		u.addr.street="朝阳";
		u.addr.zipcode="111111";
		
		System.out.println("---------------------------------------");
		
		System.out.println(u.name+"居住的城市是:"+u.addr.city);
		System.out.println(u.name+"居住的街道是:"+u.addr.street);
		System.out.println(u.name+"邮编:"+u.addr.zipcode);
		
	}
	
	
}

//引用,它既可以是局部变量,也可以是成员变量。
//引用数据类型后的变量,都能看成引用。
//引用数据类型后都是指向一个对象的内存地址。
//不能直接操作堆内存,只能通过引用,一步一步的进行访问。
//所以,u.addr这个它也是一个引用。u.addr.city

以上程序执行的内存分析图
在这里插入图片描述


public class OOTest03{
	
	public static void main(String[] args){
		
		//u是引用
		//u是局部变量
		User u=new User();
		
		//在OOTest02.java中编写的代码
		//u.addr=new Address();
		
		//换一种写法
		
		//a是引用
		//a是局部变量
		Address a=new Address();
		u.addr=a;
		
		System.out.println(u.addr.city);//null
		
		a.city="天津";
		
		System.out.println(u.addr.city);//天津
			
		
	}
}

画图,一步步按照顺序来,一定可以弄懂原理。
在这里插入图片描述


public class OOTest04{
	
	public static void main(String[] args){
		
		//创建一个丈夫对象
		Husband huangxiaoming=new Husband();
		huangxiaoming.name="黄晓明";
		
		//创建一个妻子对象
		Wife baby=new Wife();
		baby.name="baby";
		
		//结婚【能通过丈夫找到妻子,同时通过妻子也能找到丈夫】
		huangxiaoming.w=baby;
		baby.h=huangxiaoming;
		
		//得到以上“黄晓明”的妻子的名字
		
		System.out.println(huangxiaoming.name+"的妻子名字叫:"+baby.name);
		//直接把baby的name给访问出来,体现不出来他俩是夫妻关系
		System.out.println(huangxiaoming.name+"的妻子名字叫:"+huangxiaoming.w.name);

		
	}
}

//妻子类
public class Wife{
	
	//名字
	String name;
	
	//妻子对象中含有丈夫引用
	Husband h;
}

//丈夫类
public class Husband{
	
	//名字
	String name;
	
	//丈夫对象中含有妻子引用
	Wife w;
}

与内存图结合,一步步来,
总之,引用数据存储的都是内存地址,在赋值的时候,都是赋内存地址的。
内存地址指向这个对象,实际上,可以直接在堆内存里进行指向。
在这里插入图片描述
空指针异常


//测试程序
public class OOTest05{
	
	public static void main(String[] args){
		
		Customer c=new Customer();
		System.out.println(c.id);//0
		
		c=null;
		
		//以下程序编译通过,运行出错
		//出现错误:java.lang.NullPointerException
		//空指针异常
		//出现情况:空引用访问“实例”相关的数据
		System.out.println(c.id);
		
	
		
	}
}

//“实例”相关的数据表示:这个数据访问的时候必须要有对象的参与。这就是实例相关的数据

//顾客类
public class Customer{
	
	int id;
}

需求:

	定义一个计算机类【电脑/笔记本】,计算机类的属性:
		*品牌
		*型号
		*颜色

	定义一个学生类,学生类的属性:
		*学号
		*姓名
		*学生有一台笔记本电脑

	请编写程序表示以上的类,然后分别将类创建成对象,
	对象数量不限,然后让其中一个学生去使用其中一台笔记本电脑
	
	编译并运行,并且将整个的执行过程采用画图方式描述出来
	
	所有的代码写到这里来。

public class OOTest06{
	
	public static void main(String[] args){
		
		Computer computer1=new Computer();
		
		Computer computer2=new Computer();
		
		computer1.brand="asus";
		computer1.type='A';
		computer1.color="red";
		
		computer2.brand="lenevo";
		computer2.type='B';
		computer2.color="black";
		
		Student student1=new Student();
		
		student1.no=110;
		student1.name="jack";
		student1.c=computer1;
		
		System.out.println(student1.no);
		System.out.println(student1.name);
		System.out.println(student1.c.brand);
		System.out.println(student1.c.type);
		System.out.println(student1.c.color);
		
		//注意,直接访问student1.c它实际上是一个内存地址的。
		
		//当然,也可以直接student1.c=new Computer();这个学生直接换了一台新的电脑
		
	}
}

class Computer{
	
	String brand;
	
	char type;
	
	String color;
}

class Student{
	
	int no;
	
	String name;
	
	Computer c;

}

//关联关系,通过A对象,能够找到B对象。A中含有B的引用


以上程序执行的内存分析图
在这里插入图片描述

关于JVM内存管理

在这里插入图片描述

  • JVM(Java虚拟机)主要包括三块内存空间,分别是:栈内存、堆内存、方法区内存。

  • 堆内存和方法区内存各有1个,一个线程一个栈内存

  • 方法调用的时候,该方法所需要的内存空间在栈内存中分配,称为压栈。方法执行结束之后,该方法所属的内存空间释放,称为弹栈

  • 栈中主要存储的是方法体当中的局部变量

  • 方法的代码片段以及整个类的代码片段都被存储到方法区内存当中,在类加载的时候这些代码片段会载入

  • 在程序执行过程中使用new运算符创建的Java对象,存储在堆内存当中,对象内部有实例变量,所以实例变量存储在堆内存当中

  • 变量分类:
    局部变量【方法体中声明】
    成员变量【方法体外声明】
    实例变量【前边修饰符没有static】
    静态变量【前边修饰符中有static】

  • 静态变量存储在方法区内存当中【先背会】

  • 三块内存当中变化最频繁的是栈内存,最先有数据的是方法区内存,垃圾回收器主要针对的是堆内存

  • 垃圾回收器【自动垃圾回收机制、GC机制】

    什么时候会考虑将某个Java对象的内存回收呢?
    当堆内存当中的java对象成为垃圾数据的时候,会被垃圾回收器回收

    什么时候堆内存中的java对象会变成垃圾呢?
    没有更多的引用指向它的时候
    这个对象无法被访问,因为访问对象只能通过引用的方式访问

下一篇: 构造方法

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐