目录
学习面向对象内容的三条主线
1、Java类及类的成员 : 属性、方法、构造器、代码块、内部类
2、面向对象的三大特征:封装性、继承性、多态性(抽象性)
3、其他关键字: this、super、static、final、abstract、interface、package、import等
学习方法:”大处着眼,小处着手“
面向过程(POP)与面向对象(OOP)
-
二者都是一种思想,面向对象是相对于面向过程而言的。
面向过程,强调的是功能行为,以函数为最小单位,考虑怎么做。
面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
-
面向对象更加强调运用人类在日常的思维逻辑中采用的思想方法与原则,如抽象、分类、继承、聚合、多态等。
面向对象的三大特征
-
封装
-
继承
-
多态
面向对象的思想概述
-
程序员从面向过程的 执行者 转化成面向对象的 指挥者
-
面向对象分析方法分析问题的思路和步骤:
-
根据问题需要,选择问题所针对的 现实世界中的实体。
-
从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了 概念世界中的类
-
把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义。 即借助莫种程序语言,把类构造计算机能够识别和处理的数据结构。
-
将 类实例化成计算机世界中的对象 。对象是计算机世界中解决问题的最终工具。
-
类 (Class) 和 对象 (Object) 是面向对象的核心概念。
-
类 :是对象事物的描述,是 抽象的、概念上的定义。
-
对象 :是 实际存在 的该类事物的每个个体,因而也称为实例(instance)
” 万事万物皆对象 “
可以理解为: 类 = 抽象概念的人; 对象 = 实实在在的莫个人;
面向对象程序设计的重点是 类的设计
类的设计,其实就是类的成员的设计
Java类及类的成员
-
现实世界的生物体,大到鲸鱼,小到蚂蚁,都是由基本的细胞构成的,同理,Java代码世界由诸多个不同功能的类构成的。
-
现实生物世界中的细胞又是由什么构成的呢?细胞核、细胞质、...那么
-
Java中用类Class来描述事物也是如此。常见的类的成员有:
-
属性:对应类的成员变量
-
行为:对应类的成员方法
-
Field = 属性 = 成员变量 ,Method = (成员)方法 = 函数
如 :人有身高, 体重等属性 ,有说话, 打球等行为。
/*
* 一、设计类、其实就是设计类的成员
*
* 属性 = 成员变量 = field = 域、字段(外文的书)
* 方法 = 成员方法 = 函数 = method
*
* 创建类的对象 = 类的实例化 = 实例化类
*
* 二、类和对象的使用(面向对象思想落地的实现)
* 1、创建类,设计类的成员
* 2、创建类的对象
* 3、通过"对象.属性"或"对象.方法"调用对象的结构
*
* 三、如果创建了一个类的多个对象,则每个对象都是独立的拥有一套类的属性。(非static的)
* 意味着:如果我们修改一个对象的属性a,z则不影响另外一个对象属性a的值。
*
* 四、对象的内存解析
* 堆(Heap) : 此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中描述是:所有的对象实例以及数组都要在堆上分配。
* 栈(Stack): 是指虚拟机栈。虚拟机栈用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型它不等同于对象本身,是对象在堆内存的首地址)。方法执行完、自动释放。
* 方法区(Method Area) : 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
*/
//测试类
public class PersonTest {
public static void main(String[] args) {
//Person类的对象
Person p1 = new Person();
//调用对象的结构:属性、方法
//调用属性:"对象.属性 "
p1.name = "Tom";
p1.isMale = true;
System.out.println(p1.name);
//调用方法:"对象.方法 "
p1.eat();
p1.sleep();
p1.talk("Chinese");
//************************
Person p2 = new Person();
System.out.println(p2.name); //null
System.out.println(p2.isMale); //false
//*************************
//将p1变量保存的对象地址值赋给p3,导致p1和p3指向了堆空间中的同一个对象实体。
Person p3 = p1;
System.out.println(p3.name); //Tom
p3.age = 10;
System.out.println(p1.age); //10
}
}
// 1、创建类,设计类的成员
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);
}
}
创建的对象和使用:内存解析
-
栈:即为平时提到的栈结构。我们将局部变量存储在栈结构中
-
堆:我们将new出来的结构(比如:数组、对象)加载在堆空间中。对象的属性(非static的)加载在堆空间中。
-
方法区:类的加载信息,常量池,静态域。
类中属性的使用
/*
* 类中属性的使用
*
* 属性(成员变量) vs 局部变量
*
* 1、相同点:
* 1.1定义变量的格式:数据类型 变量名 = 变量值
* 1.2先声明,后使用
* 1.3变量都有其对应的作用域
*
* 2、不同点:
* 2.1在类中声明的位置的不同
* 属性:直接定义在类的一对{}内
* 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
* 2.2关于权限修饰符的不同
* 属性:可以在声明属性时,指明其权限,使用权限修饰符。
* 常用的权限修饰符:private、public、缺陷、protected --->封装性
* 目前,大家声明属性时,都使用缺省就可以了。
* 局部变量: 不可以使用权限修饰符。
*
* 2.3默认初始化值的情况:
* 属性: 类的属性,根据其类型,都有默认初始化值。
* 整型(byte、short、int、long): 0
* 浮点型(float、double): 0.0
* 字符型(char): 0 (或'\u0000')
* 布尔型(boolean) : false
*
* 引用数据类型(类、数组、接口) : null
* 局部变量 :没有默认初始化值
* 意味着,我们在调用局部变量,一定要显示赋值。
*
* 2.4在内存中加载的位置:
* 属性:加载到堆空间中(非static)
* 局部变量:加载到栈空间
*/
public class UserTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
class User{
//属性(或成员变量)
public String name;
int age;
public void talk(String language){ //language:形参,也是局部变量
System.out.println("我们使用 " + language + "经行交流");
}
public void eat(){
String food = "包子"; //局部变量
System.out.println("南方人喜欢吃 : " + food);
}
}
类中方法的使用
/*
* 类中方法的声明和使用:
*
* 方法:描述类应该具有的功能。
* 比如:Math类:sqrt()\random()\......
* Scanner类 : nextXxx()......
* Arrays类:sort() \ toString() \ equals() \ ......
*
* 1、举例:
* public void eat(){}
* public void sleep(int hour){}
* public String getName(){}
* public String getNation(String nation){}
*
* 2、方法的声明 : 权限修饰符 返回值类型 方法名(形参列表){
* 方法体
* }
*
* 注意:static 、 final、 abstract 来修饰的方法。
* 3、说明:
* 3.1关于权限修饰符:
* private、public、缺省、protected ---> 封装性
* 3.2返回值类型:有返回值 vs 没有返回值
* 3.2.1如果方法有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,需要使用return关键字来返回指定类型的变量或常量。 如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法中,就不使用return,但是,如果使用,只能“return;”表示结束方法的意思。
* 3.2.2我们定义方法该不该有返回值?
* 1、题目要求
* 2、凭经验
* 3.3方法名:属性标识符,遵循标识符的规则和规范,“见名知意”
* 3.4形参列表:方法可以声明0个,1个,或多个形参。
* 3.4.1 格式:数据类型1 形参1,数据据类型2 形参2,....
* 3.4.2 我们定义方法时,该不该定义形参?
* 1、题目要求
* 2、凭经验
* 3.5方法体:方法功能的体现。
*
* 4、return关键字的作用:
* 1、使用范围:使用在方法体中
* 2、作用:
* 2.1结束方法
* 2.2针对有返回值型的方法,使用"return 数据"方法返回所要的数据。
* 3、注意点:return关键字后面不可以声明执行语句。
*
* 5、方法的使用:可以调用当前类中的属性或方法
* 特殊的:方法A中又调用了方法A:递归方法
* 方法内不可以定义方法
*/
public class CustomerTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
//客户类
class Customer{
//属性
String name;
int age;
boolean isMale;
//方法
public void eat()
{
System.out.println("客户吃饭!");
}
public void sleep(int hour)
{
System.out.println("休息了" + hour + "个小时");
return; //结束方法的作用
//后面语句不执行
}
public String getName(){
return name;
}
public String getNation(String nation){
String info = "我的国籍是:" + nation;
return info;
}
}
小练习:
(1)、谈谈你对面向对象中类和对象的理解,并指出二者的关系?
类:抽象的、概念上的内容
对象:实实在在存在的一个个体。
对象是由类派生出来的。
(2)、面向对象思想的体现一:类和对象的创建和执行操作有哪三步?
1、创建类
2、创建类的对象(类的实例化)
3、调用对象的结构:属性、方法
调用属性:"对象.属性 "
调用方法:"对象.方法 "
(5)、类的方法内是否可以定义变量?是否可以调用属性?是否可以定义方法?是否可以调用方法?
是;是;否;是。
JVM原理
程序完源程序以后,生成一个或多个字节码文件。
我们使用JVM的类的加载器和解释器对生成的字节码文件进行解释运行。意味着,需要将字节码文件对应的类加载到内存中,涉及到内存解析。
《JVM规范》
-
堆(Heap) : 此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在
-
Java虚拟机规范中描述是:所有的对象实例以及数组都要在堆上分配。
-
栈(Stack ) : 是指虚拟机栈。虚拟机栈用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本
-
类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型
-
它不等同于对象本身,是对象在堆内存的首地址)。方法执行完、自动释放。
-
方法区(Method Area) : 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
理解“万事万物皆对象”
一、理解“万事万物皆对象”
1、在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构
Scanner,String 等
文件:File
网络资源:URL
2、涉及到Java语言与前端Html、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类、对象
二、内存解析的说明
1、引用类型的变量,只可能存储两类值:null 或 地址值(含变量的类型)
三、匿名对象的使用
1、理解:我们创建的对象,没有显示的赋给一个变量名。即为匿名对象。 (new Phone.sendEmail(); new Phon().price = 1999;)
2、特征:匿名对象只能调用一次。
3、使用:...(封装性)
方法的重载
重载的概念:
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
重载的特点:
返回值类型无关,只看参数列表,且参数列表必须不同,(参数个数或参数类型)。调用时,根据方法参数列表的不同来区别。
重载示例:
//返回两个整型的和 方法名相同 ,参数不同
int add(int x, int y ) { return x + y; }
//返回三个整数的和
int add(int x, int y ) { return x + y + z; }
//返回两个小数的和
double add(double x, double y) { return x + y; }
“两同一不同”
同一个类,相同方法名
参数列表不同:参数个数不同,参数类型不同。
代码演示:
public class OverLoadTest {
//如下的4个方法构成了重载
public void getSum(int i,int j) {
}
public void getSum(double d1,double d2) {
}
public void getSum(String s1,int i) {
}
public void getSum(int i,String s) {
}
// public int getSum(int i, int j){ //这个不可以
//
// }
// public void getSum(int m,String n) { //这个也不可以
//
// }
// private void getSum(int i,String s) { //这个也不行
//
// }
//总结:判断是否是重载:
//跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系!
//4、在通过对象调用方法时,如何确定莫一个指定的方法:
//方法名 ---> 参数列表
}
可变个数形参的方法:jdk 5.0 新增
允许直接定义和多个实参相匹配的形参,而且,可以用一种更简单的方式,来传递个数可变的实参。
/*
* 可变个数形参的方法
*
* 1、jdk 5.0 新增的内容
* 允许直接定义和多个实参相匹配的形参,而且,可以用一种更简单的方式,来传递个数可变的实参。
* 2、具体使用:
* 2.1 可变个数形参的格式:数据类型 ... 变量名
* 2.2 当调用可变个数形参的方法时,传入的参数个数可以是:0个,1个,2个,...
* 2.3 可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载。
* 2.4 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载。换句话说:两者不能共存
* 2.5 可变个数形参在方法的形参中,必须声明在末尾
* 2.6 可变个数形参在方法的形参中,最多只能声明一个可变形参.
*
* 可用:sql查询不知道多少个id的...(可变个)
*
* //JDK 5.0以前:采用数组形参来定义方法,传入多个同一类型变量
* public static void test(int a,String[] books);
* //JDK 5.0以后:采用可变个数形参来定义方法,传入多个同一类型变量
* public static void test(int a,String ... books);
*/
import javax.swing.plaf.synth.SynthStyle;
public class MathodArgsTest {
public static void main(String[] args) {
MathodArgsTest test = new MathodArgsTest();
test.show(12);
test.show("hello");
test.show("gee","sdh");
test.show();
}
public void show(int i)
{
}
// public void show(String s) //可以重载
// {
// System.out.println("show(String)");
// }
public void show(String ... strs)
{
System.out.println("show(String ... strs)");
for(int i=0;i < strs.length;i++) //与数组调用相同
{
System.out.println(strs[i]);
}
}
// public void show(String ... strs,int i) //不可行 string ... strs 必须放在最后
// {
//
// }
// public void show(String[] strs) //不可重载
// {
// System.out.println("show(String ... strs)");
// }
}
方法参数的传递机制
-
方法,必须由其所在类或对象调用才有意义。若方法含有参数:
-
形参:方法声明时的参数、
-
实参:方法调用时实际传给形参的参数值
Java的参数值如何传入方法的呢?
Java里方法的参数传递方式只有一种:值传递。即将实际参数值的副本(赋值)传入方法内,而参数本身不受影响。
-
形参是基本数据类型:将实参基本数据类型变量的”数据值“传递给形参。
-
形参是引用数据类型:将实参引用数据类型变量的”地址值“传递个形参。
总结:
方法的形参的传递机制:值传递
1、形参:方法定义时,声明的小括号的参数
实参:方法调用时,实际传递给形参的数据
2、值传递机制:
如果参数是基本数据类型,此时实参赋给形参真实存储的数据值
如果参数是引用数据类型,此时实际赋给形参的是实参存储数据的地址值
//错误的:交换数组中指定两个位置元素的值
swap(arr[j],arr[j+1]); //错误的;值传递
public void swap(int i,int j)
{
int temp = i;
i = j;
j = temp;
}
//正确的:交换数组中指定两个位置元素的值
swap(arr,i,j); //正确的
public void swap(int[] arr,int i,int j) //形参中i,j是索引
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
网红题:貌似是考查方法的参数传递
public class Test {
public static void main(String[] args) {
int a = 10;
int b = 10;
method(a,b); //需要在method方法调用之后,仅打印a=100,b=200,请写method方法的代码
System.out.println("a = " + a);
System.out.println("b = " + b);
}
//代码编写:
}
解题:
import java.io.PrintStream;
public class Test {
public static void main(String[] args) {
int a = 10;
int b = 10;
method(a,b); //需要在method方法调用之后,仅打印a=100,b=200,请写method方法的代码
System.out.println("a = " + a);
System.out.println("b = " + b);
}
//代码编写:
//方法一:
public static void method(int a,int b)
{
//在不改变原来题目的前提下,如何写这个函数才能在main函数中输出a=100,b=200?
a = a * 10;
b = b * 20;
System.out.println("a = " + a);
System.out.println("b =" + b);
System.exit(0);
}
//方法二:
//重写打印流
}
System.exit(0)的理解: