面向对象的两个要素:
-
类:对一类事物的描述,是抽象的、概念上的定义
-
类的成员:
-
属 性:对应类中的成员变量
-
行为:对应类中的成员方法
-
Field = 属性 = 成员变量, Method =( 成员 )方法 = 函数
-
-
对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)
可以理解为: 类 = 抽象概念的人; 对象 = 实
面向对象程序设计的重点是类的设计
设计类,就是设计类的成员。
类的语法格式:
修饰符 class 类名 {
属性声明 ;
方法声明 ;
}
//说明: 修饰符 public :类可以被任意访问
//类的正文要用 { } 括起来
类和对象的使用
-
创建类,设计类的成员
-
定义类(考虑修饰符、类名)
-
编写类的属性 (考虑修饰符、属性 类型、属性名 、初始化值)
-
编写类的方法 (考虑修饰符、返回值类型,方法名,形参等)
class Person{
//属性
String name;
int age = 1;
boolean isMale;
//方法
public void eat(){
System.out.println("人可以吃饭");
}
public void sleep(){
System.out.println("人可以睡觉");
}
public void talk(String language){
System.out.println("人可以说话,使用的是:" + language);
}
}
2. 创建类的对象(java类的实例化)
public static void main(String[] args) {
//创建Person类的对象
Person p1 = new Person();
//Scanner scanner = new Scanner(System.in);也是创建类的对象,System.in是参数
}
3. 通过“对象.属性”或“对象.方法”调用对象的结构
public static void main(String[] args) {
//创建Person类的对象
Person p1 = new Person();
//Scanner scanner = new Scanner(System.in);也是创建类的对象,System.in是参数
//调用对象的结构:属性、方法
//调用属性:“对象.属性”
p1.name = "Tom";
p1.isMale = true;
System.out.println(p1.name);
//调用方法:“对象.方法”
p1.eat();
p1.sleep();
p1.talk("Chinese");//Chinese为参数
//创建第二个对象
Person p2 = new Person();
System.out.println(p2.name);//null
System.out.println(p2.isMale);
//*******************************
//将p1变量保存的对象地址值赋给p3,导致p1和p3指向了堆空间中的同一个对象实体。
Person p3 = p1;
System.out.println(p3.name);//Tom
p3.age = 10;
System.out.println(p1.age);//10
}
类的访问机制:
-
在一个类中的访问机制:类中的方法可以直接访问成员变量 。
(例外: static方法访问非 static,编译不通过 。)
-
在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中定义的成员 。
对象的内存解析
堆(HeapHeap ),此内存区域的唯一目的就是存放对象实例,几 乎所有的对象,实例都在这里分配内存, 这一点在 Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配 。
通常所说的栈(StackStackStack ),是指虚拟机栈。虚拟机栈用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本数据类型 (boolean 、byte、 char 、 short 、 int,float、 long、 double)、对象引用(reference 类型 ,它不等同于对象本身,是对象在堆内存的首地址 )。方法执行完自动释放。
方法区 (Method Area),用于 存储已被虚拟机加载的类信息 、常量 、静态变量 、即时编译器后的代码等数据。
Person p1 = new Person();
p1.name = "Tom";
p1.isMale = true;
Person p2 = new Person();
System.out.println(p2.name);//null
Person p3 = p1;
p3.age = 10;
Person p1 = new Person();
只要是new的对象,都会在堆空间造一个对象实体,这个实体就会有地址值0X12ab,是这个对象的首地址值,因为有赋值操作,而且在main方法中,所以要在栈空间中生成局部变量p1,把堆空间中新造的对象的首地址值赋值给p1,栈空间中的p1就指向堆空间中的p1对象。在堆空间中通过Person类创建p1对象的的时候,Person类中属性name,isMale,age也会产生并初始化,属性name是字符串,初始化值为null;属性isMale是boolean类型,初始化值是false; 属性age在初始化的时候被赋值,所以属性age的值为1;这些属性都存在于堆空间中的p1对象中。
p1.name = "Tom";
p1.isMale = true;
赋值语句,运行之后属性name的值为Tom;属性isMale的值是true; 属性age的值为1;
Person p2 = new Person();
只要是new的对象,都会在堆空间造一个对象实体,这个实体就会有地址值0X17788,是这个对象的首地址值,因为有赋值操作,而且在main方法中,所以要在栈空间中生成局部变量p2,把堆空间中新造的对象的首地址值赋值给p2,栈空间中的p2就指向堆空间中的p2对象。在堆空间中通过Person类创建p2对象的的时候,Person类中属性name,isMale,age也会产生并初始化,属性name是字符串,初始化值为null;属性isMale是boolean类型,初始化值是false; 属性age在初始化的时候被赋值,所以属性age的值为1;这些属性都存在于堆空间中的p2对象中。
System.out.println(p2.name);//null
p2对象里属性name初始值为null
Person p3 = p1;
赋值操作,而且在main方法中,所以要在栈空间中生成局部变量p3,把p1的地址值赋值给栈中局部变量p3,栈空间中的p3就指向堆空间中的p1对象。此时栈中有两个局部变量指堆空间中的p1对象,也叫p3对象。
p3.age = 10;
通过栈空间中p3所指堆空间的对象找到里面的age属性,找到属性值,输出。
成员变量和局部变量
属性成员变量(属性) vs 局部变量
相同点:
-
定义变量的格式:数据类型 变量名 = 变量值
-
先声明,后使用
-
变量都有其对应的作用域
不同点:
-
在类中声明的位置的不同
-
属性:直接定义在类的{}内
-
局部变量:声明在方法内,方法形参,代码块内,构造器形参,构造器内的变量.
-
-
关于权限修饰符的不同
-
属性:可以在声明属性时,指明其权限,使用权限修饰符。
-
常用的权限修饰符:private、public、缺省、protected --->封装性
-
权限修饰符的作用:体现这个属性被调用的时候可见性的大小,
-
例如public int age; 属性age在类里面和类外面都能被调用
-
private int age; 属性age只能在类里面调用
-
-
目前,大家声明属性时,都使用缺省就可以了。
-
-
局部变量:不可以使用权限修饰符。
-
-
默认初始化值的情况
-
属性:类的属性,根据其类型,都有默认初始化值。
-
整型(byte、short、int、long):0
-
浮点型(float、double):0.0
-
字符型(char):ASCII码值为 0的 char型元素,或'\u0000',而非数字"0"
-
布尔型(boolean):false
-
引用数据类型(类、数组、接口):null
-
-
局部变量:没有默认初始化值。
-
意味着,我们在调用局部变量之前,一定要显式赋值
-
特别地:形参在调用时,我们赋值即可。
-
-
-
在内存中加载的位置
-
属性:加载到堆空间中 (非static)
-
局部变量:加载到栈空间
-
类中方法的声明与使用
方法:描述类应该具有的功能。
比如:
-
Math类:开方sqrt()\随机数random() ...
-
Scanner类:nextXxx() ...与键盘交互获取数据
-
Arrays类:对数组进行排序sort() \ 数组二分查找binarySearch() \ 输出数组toString() \ 判断数组是否相同equals() \ ...
方法的声明:
权限修饰符 返回值类型 方法名(形参列表){
方法体
}
举例:
-
public void eat(){} //方法 public void eat(){ System.out.println("客户吃饭"); return;//通常void函数不需要返回值也不需要return,也可以写"return;"但是void函数里的return的作用是结束方法 //return后不可以声明表达式 // System.out.println("hello"); }
public void sleep(int hour){}
public void sleep(int hour){
System.out.println("休息了" + hour + "个小时");
eat();//方法的使用中,可以调用当前类的属性或方法
//sleep(10);
}
public String getName(){}
public String getName(){
if(age > 18){
return name;
}else{
return "Tom";
}
}
public String getNation(String nation){}
public String getNation(String nation){
String info = "我的国籍是:" + nation;
return info;
}
关于方法元素的说明:
-
关于权限修饰符:默认方法的权限修饰符先都使用public
Java规定的4种权限修饰符:private、public、缺省、protected -->封装性再细说
-
返回值类型: 有返回值 vs 没有返回值
-
如果方法有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,需要使用return关键字来返回指定类型的变量或常量:“return 数据”。
-
如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法中,就不需要使用return.但是,如果使用的话,只能“return;”表示结束此方法的意思。
-
我们定义方法该不该有返回值?
-
题目要求
-
凭经验:具体问题具体分析
-
3. 方法名:属于标识符,遵循标识符的规则和规范,“见名知意”
首字母小写和驼峰原则:run(),runRun()
4.形参列表:方法可以声明0个,1个,或多个形参。
-
格式:数据类型1 形参1,数据类型2 形参2,...
-
我们定义方法时,该不该定义形参?
-
题目要求
-
凭经验:具体问题具体分析
-
5.方法体:方法功能的体现。
return关键字的使用:
-
使用范围:使用在方法体中
-
作用:
-
结束方法
-
针对于有返回值类型的方法,使用"return 数据"方法返回所要的数据。
-
-
注意点:return关键字后面不可以声明执行语句。
方法的使用:
-
方法的使用中,可以调用当前类的属性或方法
-
特殊的:方法A中又调用了方法A:递归方法。
-
方法中,不可以定义方法。