前言
这是面向对象的第二篇啦!!本博客主要分享下面向对象编程中第一个重要的知识点——类与对象。众所周知,类和对象几乎可以说是面向对象编程的核心部分,没有类和对象就无法写一个程序,因此其重要性无需多言,接下来,let‘s go!
在这里先把其他几篇的链接放在这边,大家有需要的可以自行查看哦。
1.面向对象<一>思想篇
2.面向对象<二>类与对象(就是这篇咯)
3.面向对象<三>三大特性
4.面向对象<四>关键字(也没写了)
一、Java类
类是对一类事物的描述,是抽象的、概念上的定义。
首先给大家看一下类的代码是怎样的,具体如何来写,后面也会写。
//首先,声明要写的类名,在这里就是Person类
class Person{
//类的属性,也即成员变量
String name;
int age=10;
Boolean isMarried;
//构造器,用来初始化对象
//括号中的name,age,isMarried称为形参
public Person(String name, int age, Boolean isMarried) {
this.name = name;
this.age = age;
this.isMarried = isMarried;
}
//类的方法,创造出的对象就能执行这些方法,
//大括号之间的内容称为方法体
public void run(){
System.out.println("人会跑!");
}
public void eat(){
System.out.println("人会吃!");
}
}
以上就是一个基本类的构成了,接下来对其写法进行具体的说明。
类的语法格式如下图所示:
修饰符有四种,按照其可访问范围的大小排序为:
public>protected>缺省(就是空着,啥都不写)>private
类名:就是自己起的名字,当然要合规范,最好是可以多看看代码规范
属性和方法在下面会细说,有的朋友就要说了:怎么没有构造器呢,之前的例子里是有的吖,是的,这里没有显式声明构造器,但是IDEA会默认产生空参构造器(就是没有参数的构造器,,),可以直接实例化。
1.1、属性
属性,就是写在每个类中,开始的地方声明的变量,如前文的Person
类中的name
,age
和isMarried
就是Person
类的属性。
在类中的变量分为两种:一是成员变量,也就是属性,是在方法体外,类体内声明的变量;另一种是局部变量,也就是在方法体内部声明的变量。
两者的区别从下表可以清晰地看出:
在这里简单描述一下两个变量在内存中的加载位置,成员变量加载在堆中(非静态属性)或是静态域内(静态属性),而局部变量统一加载在栈空间。举一段代码段的例子如下:
class Person{
//类的属性,也即成员变量
String name;
int age=10;
Boolean isMarried;
//类的方法,创造出的对象就能执行这些方法,
//大括号之间的内容称为方法体
public void eat(String food){
String kind;
kind = "油炸";
System.out.println("人吃!"+food+",它是"+kind+"的。");
}
}
//测试类
class PersonTest{
public static void main(String[] args){
Person p = new Person();
p.eat("汉堡");
}
}
在Person
类中,name
,age
,isMarried
为属性,而在eat()
方法中,food
,kind
均为局部变量,测试类中的p
即为实例化的对象。依照内存解析我们可以画出此时的内存解析图,如下图:
大家可以根据Java不同数据类型的存放位置,对内存存放机制进行学习,加深理解。
1.2、方法
方法是类或对象行为特征的抽象,用来完成某个功能操作。将功能封装为方法,可以实现代码的重用及简化。Java方法不能独立存在,必须定义在类里才可以,不可以在方法内定义方法。方法只有被调用才会执行,通过方法名进行调用。
方法的声明格式如下图:
方法重载
在同一个类中,允许存在一个以上同名的方法,只要参数格式或者参数类型不同即可。
使用重载可以为编程带来很大的便利。
与void show(int a,char b,double c){}构成重载的有:
a) int show(int a,double c,char b){} // yes
b) void show(int a,double c,char b){} // yes
c) boolean show(int c,char b){} // yes
d) void show(double c){} // yes
e) double show(int x,char y,double z){} // no
f) void shows(){double c} // no
g) void show(int x,char y,double z){} // no
值得注意的是一下这种情况,使用Varargs机制,允许直接定义未知个数的形参与实参相匹配,是一种简便方式来传递个数可变的实参。例如:
public static void test(int a ,String…books);
//这里面String类型的books变量的数量不定,0个到多个,此时与同名方法构成重载
//可变形参一个方法只能有一个,且必须放在方法声明的最后位置
值传递机制
Java的实参值是如何传入方法呢?
当形参是基本数据类型时,会将实参基本数据类型变量的“数据值”传递给形参;
那么此时在方法中改变形参的数值,则实参的数值不会改变。
当形参是引用数据类型时,会将实参引用数据类型变量的“地址值”传递给形参。
那么此时在方法中改变形参的数值,则实参的数值会发生改变。
大体道理是这样,但是具体情况还是需要大家去根据实际情况去判断。
1.3、构造器
构造器具有2个作用:一是创建对象;二是初始化对象的信息。
其实说白了就是在实例化对象的时候用来给其赋值。语法格式如下:
构造器可以分为2种:
1.隐式无参构造器;
2.显式定义一个或多个构造器。
当没有显式声明构造器时,系统自动创建无参的构造器,一旦显式定义了构造器后,系统将不再提供默认的空参构造器,使用时会报错。每个类可以创建多个重载的构造器。
二、类的对象
在前文已经创建好类后,那么该如何应用呐,这个时候就该实例化对象了,用对象去调用所写的方法,以实现相应功能。
对象是实际存在的某类事物的每个个体,也被称为实例。
2.1、对象创建和使用
1、创建对象的语法:
类名 对象名 = new 类名();
2、使用对象名.对象成员
的方式访问对象成员(包括属性和方法)
public class Zoo {
public static void main(String args[]) {
Animal xb = new Animal();//实例化对象
xb.legs = 4;//给对象属性赋值
System.out.println(xb.legs); // 4
}
}
class Animal{
int leg;//类属性
public void Animal(){}//空参构造器,可以省略
}
2.2、对象的内存解析
堆(Heap),此内存区域的唯一目的 就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在 Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。
通常所说的栈(Stack),是指虚拟机栈。虚拟机栈用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、 char 、 short 、 int 、 float 、 long 、double)、对象引用(reference类型, 它不等同于对象本身,是对象在堆内 存的首地址)。 方法执行完,自动释放。
方法区(Method Area),用于存储已被虚拟机加载的类信息、常量、静态 变量、即时编译器编译后的代码等数据。
接下来,举个实际的例子,代码已经放在图中,简要的画了下其内存存放,方便大家理解。