初学者笔记-面向对象编程
1.面向对象与面向过程
面向对象(OOP)的概念是相对于面向过程(POP)而言;
面向对象的思维更强调人在日常思维逻辑中采用的思想方法和原则,如抽象、分类、继承、聚合、多态等;
面向对象的三个基本特征:
- 封装(Encapsulation)
- 继承(Inheritance)
- 多态(Polymorphism)
面向对象思想"落地"法则:
- 1.关注于类的设计, 即设计类的成员: 属性、方法
- 2.类的实例化, 即创建类的对象
- 3.通过"对象.属性"、"对象.方法"执行
2.java语言的基本元素:类和对象
面向对象程序设计的重点是类的设计
定义类其实是定义类中的成员(成员变量和成员方法)
类的语法格式:
修饰符 class 类名{
属性声明;
方法声明;
}
创建java自定义类:
- 定义类(考虑修饰符、类名)
- 编写类的属性(考虑修饰符、属性类型、属性名、初始化值)
- 编写类的方法(考虑修饰符、返回值类型、方法名、形参等)
3.类的成员之一:属 性
语法格式:
修饰符 类型 属性名 = 初值;
private int age = 50 ;
说明:
修饰符:private: 该属性只能由该类的方法访问
修饰符:public: 该属性可以被该类以外的方法访问
类型: 任何基本类型, 如int ,boolean或任何其他类
补充:变量类型:
- 在方法体外,类体内声明的变量称为成员变量
- 在方法体内部声明的变量称为局部变量
成员变量和局部变量区别:
-
成员变量(属性):
定义在类中,在整个类中都可以被访问
成员变量存在于堆存中
成员变量有默认初始化值
成员变量的权限修饰符可以根据需要,任意选择一个 -
局部变量:
局部变量只存在于局部范围内,如:方法内,代码块内等
局部变量存在于栈内存中,作用结束,变量空间会自动释放
局部变量没有默认初始化值,每次必须显示初始化
局部变量声明时不指定权限修饰符
实例变量和类变量区别:
-
实例变量(不以static修饰)
在类被实例化成对象后才能访问。
实例变量属于某一个对象。实例化后才能被访问。 -
类变量(也称静态域,以static修饰)
不需要实例化就可以被访问。
类变量属于某一个类,一个类下实例多个对象也会有一个相同的类变量。
静态常量 如果一个域被定义为static final,则这个域就是一个静态常量。不能省略任何一个关键字,若是少了static,则该域变成了一个实例域,需要由类对象对其进行访问。若是省略了final,则该域变成了静态域,静态方法可以对其进行修改。
静态方法
静态方法是一种不能向对象实施操作的方法。Math的pow方法就是一个静态方法,在运算时,不使用任何Math对象,换句话说,没有隐式的参数this。因为静态方法不能操作对象,所以不能在静态方法中访问实例域,但是静态方法可以访问自身类中的静态域。
可以使用对象调用静态方法,但是这样容易引起混淆,因为计算的结果与对象毫无关系,建议还是使用类名,而不是类对象调用静态方法。
但是,如果去掉其中的关键字static,它就成了非静态方法,但是也可以访问类中的静态域,这时就需要由该类的对象来调用该函数。
在下面两种情况下使用静态方法:
1.一个方法不需要访问对象的状态,其所需的参数都是通过显式的提供
2.一个方法只需访问类的静态域
4.类的成员之二:方 法
方法的定义(函数):
方法是类或对象行为特征的抽象
java中的方法不能独立存在,必须定义在类里
语法格式:
修饰符 返回值类型 方法名(参数类型 形参1,参数类型 形参2,...){
//方法采用驼峰命名法
代码;
代码;
return 返回值;
}
形式参数: 在方法被调用时用于接收外部传入的数据的变量
返回值: 方法在执行完毕后返还给调用它的程序的数据
返回值类型: 方法要返回的结果的数据类型
实参: 调用方法时实际传给函数形参的数据
1.无返回值的方法(返回值类型用void表示)//无返回值,最后的"return;"被省略
public viod outPut{
}
2.有返回值的方法
//方法体最后一行返回相应数据,使用return,返回数据类型与方法定义的一致
public int getAge{
return age;
}
3.方法的形参
public void showIofo{String name,int age,height,weight
}
定义方法时,方法的结果应该返回给调用者,由调用者处理
方法中只能调用方法,不能在方法中定义方法
5.对象的创建和使用
java类的实例化,即创建类的对象
用 “new + 构造器” 创建一个新的对象
用 “对象名.对象成员” 的方式访问对象成员(属性和方法)
1.声明一个对象
public calss Test01{
public static void main{
Person person01 = new Person();
//声明一个Person的对象,对象名person01
//new person()实例化Person类
}
}
2.匿名对象
如果对一个对象只需要一次方法调用,可以使用匿名对象
常将匿名对象作为一个实参传递给一个方法调用
public calss Test01{
public static void main{
new Person().showName();
//声明一个Person的匿名对象
//匿名对象调用showName()方法
}
}
3.示例:
创建一个Person的类
public class Person {
String name;
int age;
public void showName() { //无返回值的方法
System.out.println("我的名字是"+name);
}
--------------------------------------------------------------------
public String getName() { //有返回值的方法
System.out.println("我改名叫"+name);
return name;
}
-------------------------------------------------------------------
public void eatFood(String food) { //有形参的方法
//(String food为形参)
System.out.println(name+"开始吃"+food+"了");
}
--------------------------------------------------------------------
}
实例化一个Person类的对象,操作其变量,调用类的方法
public static void main(String[] args) {
/*方法
* 面向对象的编程练习
*/
Person player01= new Person(); //初始化一个对象
player01.name = "李白"; //操作对象的name参数
player01.showName(); //调用showName()方法
player01.name = "张三";
player01.showName();
String temp = player01.getName();//有返回值的方法,调用后会有一个值,即return的部分
System.out.println(temp); //这个返回值可以赋值给同类型变量
player01.eatFood("大西瓜"); //有参数的方法,需要填写对应类型的参数
//player01.eatFood(); //报错,有参数的方法,需要填写
}
类的访问机制:
-
在一个类中的访问机制:
类中的方法可以直接访问类中的成员变量
(但是static方法不能访问非static成员变量) -
在不同类中的访问机制:
先创建要访问的类的对象, 再用对象访问类中定义的成员
6.方法的其他特性
1. 方法的重载(overload):
在同一个类中, 允许存在一个以上的同名方法, 只要他们的参数类型或者参数个数不同 (跟方法类型无关)
调用时,根据输入实参的类型和数量不同执行对应的方法
2. 可变个数的形参:
JDK1.5后出现的新特性
- 可变参数: 方法参数部分指定类型的参数个数是可变多个(参数类型是确定的)
- 声明方式: 修饰符 返回值类型 方法名 (参数的类型…参数名)
- 可变参数方法的使用与方法参数部分使用数组是一致的, 可变参数的底层就是一个长度可变的数组
- 方法的参数部分有可变形参, 需要放在形参声明的最后, 所以可变形参只能有一个.
如: public void test01(int i, String…args){}
/**
* 以数组形参来定义方法
* @param args
*/
public void test(String[] args) {
for(int i = 0; i<args.length; i++) {
System.out.println(args[i]);
}
}
/**
* 以可变个数形参来定义方法
* @param args
*/
public void test01(String...args) {
for(int i = 0; i<args.length; i++) {
System.out.println(args[i]);
}
}
/**
* 以数组形参来定义方法
*/
String args01[] = {"白菜","西瓜","牛奶"};
player01.test(args01);
//形参为数组,则实参为数组
String args02[]={};
player01.test(args02);
//如果没有参数,就定义一个空数组
/**
* 以可变个数形参来定义方法
*/
player01.test01("你好","帅哥","大白菜");
//形参为可变个数形参,实参为可变个数(可多个)string变量
player01.test01();
//如果没有参数,可以直接不填
3. 方法的参数传递
方法必须有其所在的类或对象调用才有意义
若方法含有参数:
形参: 方法声明时的参数
实参: 方法调用时实际传递给形参的参数值
java里参数的传递方式只有一种: 值传递。即将实际参数值的副本 (复制) 传入方法内, 而 参数本身不受影响。
JVM内存模型
基本数据类型的值保存在栈内存
引用对象的地址保存在栈内存, (属性) 值保存在堆内存
引用对象的值传递:
总结:
- 如果方法的形参是基本数据类型, 那么实参 (实际的数据) 向形参传递参数时, 就是直接传递值, 把实参的值复制给形参。
- 如果方法的形参是对象, 那么实参 (实际的对象) , 向形参传递参数时, 也是将值复制给形参, 这个值时实参在栈内存中的值, 也就是引用对象在堆内存中的地址。
7.面向对象的特征之一:封装和隐藏
1.软件包的概念:
- 包帮助管理大型软件系统: 将语义警示的类组织到包中; 解决类命名冲突的问题。
- 包可以包含类和子包。
- package语句作为java源文件的第一条语句, 指明该文件定义的类所在的包
package javatest.test01;
- package语句中, 用"."来指明包的层次
- 包通常用小写单词, 类名字通常大写
2.import语句:
-
为使用定义在不同包中的java类, 需用import语句来引入指定包层次下所需要的类或者全部类(.*)
(默认调用同一个包中的java类, 不用引用)
(编译器默认可获取java.lang包下的类, 不需要再显示声明) -
import语句不是必需的, 可坚持在类里使用其他类的全名(包含路径)
-
import语句出现在package语句之后、类定义之前
-
一个源文件可包含多个import语句
-
可以用import lee.*; 语句, 表明导入lee包下的所有类。
-
而lee包下的sub子包内的类则不会被导入import lee.sub.*;
-
JDK 1.5 加入import static语句
import static java.lang.Math.PI;
静态导入的作用是把Math 类中的PI 常量引入到本类中,这会使程序更简单,更容易阅读,只要看到PI 就知道这是圆周率,不用每次都要把类名写全了。但是,滥用静态导入会使程序更难阅读,更难维护。
3.封装和隐藏
把变量设为私有的(private), 再提供共有的(public)方法:getXxx()和setXxx实现对属性的操作,以实现以下目的:
- 隐藏一个类中不需要对外提供的实现细节
- 使用者只能通过事先制定好的方法来访问数据, 可以方便地加入控制逻辑, 限制对属性的不合理操作
- 便于修改, 增强代码的可维护性
/**
* 封装和隐藏
*/
private int sex; //私有化,隐藏属性
public void inPut(int i) {//设置public的方法输入属性
sex = i;
}
public int getSex() {//设置public的方法取得属性
return sex;
}
public void setSex() {//设置public的方法设置属性
if(sex==0) {
System.out.println("性别为女");
}else if(sex==1) {
System.out.println("性别为男");
}else {
System.out.println("输入的性别不在0和1之内");
}
}
public static void main(String[] args) {
Person player01 = new Person();
player01.inPutSex(0); //通过public类型的getXxx()方法输入属性
player01.setSex(); //通过public类型的setXxx()方法设置属性
int i = player01.getSex(); //通过public类型的setXxx()方法获得属性
System.out.println(i);
}
4.四种访问权限修饰符
java权限修饰符public、protected、private置于类的成员定义之前, 用来限定对象对该类成员的访问权限
修饰符 | 类内部 | 同一个包 | 子类 | 其他任何地方 |
---|---|---|---|---|
private | Yes | / | / | / |
(缺省) | Yes | Yes | / | / |
protected | Yes | Yes | Yes | / |
public | Yes | Yes | Yes | Yes |
对于class的权限修饰只能用public和default(缺省)
- public类可以在任意地方被访问
- default类只能被同一个包内部的类访问
- 在一个java文件中只能有一个public class(且与java文件同名)
*父子类(继承关系):
通过extends可以构成父子类关系
public class PersonChild extends Person{//PersonChild是Person的子类
}
8.类的成员之三:构造(构造方法)
1.构造方法
语法格式:
修饰符 类名(参数列表){
初始化语句;
}
//例:
public class Person{
public Person(){
}
}
根据参数不同, 构造器分为两类:
- 隐式无参构造器(默认)
- 显示定义一个或多个构造器(无参、有参)
注意点:
- java语言中, 每个类至少有一个构造器
- 默认构造器的修饰符与所属类的修饰符一致
- 一旦显示定义了构造器, 则不会有默认构造器
- 一个类可以创建多个重载的构造器
- 父类的构造器不可被子类继承
2.JavaBean
JavaBean是一种Java语言写成的可重用组件
所谓JavaBean, 是指符合如下标准的java类:
- 类是公共的
- 有一个公共的无参的构造器
- 有属性, 属性一般是私有的, 且有对应的get、set方法
用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用java代码创造的对象进行打包,
并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean、appet程序或应用来使用这些属性。用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,
而不用关心任何改改变。
9.几个关键字:this…
1.this
1.this表示当前对象, 可以调用类的属性、方法和构造器
- 在方法内部使用, this表示这个方法所属对象的引用
- 在构造器内部使用, 表示该构造器正在初始化的对象
2.this 表示当前类, 用于调用类的成员变量、成员方法
3.this 在构造器中调用当前类的其他构造器 this();
- 使用this()必须放在构造器的首行
- 使用this调用本类其他构造器, 至少一个构造器是不用this的(不能出现构造器调用自己)
用法:
- 当形参与成员变量重名时, 在方法内部使用成员变量, 必须添加this来表明该成员变量是类成员
int age;
String name;
public Test20210322(int age,String name) {
this.age = age ;
this.name = name ;
- 在任意方法内, 如果使用当前类的成员变量或成员方法可以添加this, 增强程序的阅读性