Java面向对象重要知识总结
方法及其调用方式
-
通常情况下,方法通过对象或类名使用"."操作符进行调用,也可能不用"."直接调用
比如Math类。
-
通 过对象调用。
创建对象:类名 对象名 = new 类名();
-
在同一个类中,方法A调用方法B。
方法的分类及其总结
-
无参数无返回值
-
有参数无返回值
-
无参数有返回值
-
有参数有返回值
总结:
- 无返回值的方法,返回值部分要写成void
有返回值的方法,方法体中必须要写上return,且要在return后写上对应返回值类型的数据
-
没有返回值的方法体中,也可以使用return关键字,但后面不能有值。只要出现return关键字,就不再执行后续代码
-
有返回值的方法在调用时,需要接收返回的数据才能使用该数据
-
方法定义时的参数称为形式参数,简称为形参,方便在方法体中使用。方法调用时传递的值称为实际参数,简称为实参,只需要保证满足形参的数据类型即可,与形参名无关
两种编程思想
分别是面向对象和面向过程
类和对象
类class
具有相同属性和行为的对象的集合,称为"一类"。可以理解为模板。
属性:描述对象的特征,在程序中,通过定义变量的形式表现属性。
定义类
[修饰符] class 类名{
//属性(变量)
//行为(方法)
}
对象的概念
对象是类的一个实例,是类的具体表现。
对象的创建方式
类名 对象名 = new 构造方法([参数]);
创建的对象,通过"."操作符访问类中的非私有属性和方法。
类和对象的关系
对象是类的具体表现,类是对象的集合(模板)。
成员变量
定义在类中的变量,称为成员变量,拥有默认值
局部变量
定义在方法中的变量,称为局部变量。默认有默认值,赋值后才能使用
构造方法
概念
构造方法是一个特殊的方法,没有返回值,方法名和类名一致。
每个类在定义时,都有一个默认隐藏的无参数的构造方法,在创建对象时调用。
构造方法通常用于初始化成员变量。
特点
-
构造方法没有返回值(没有返回值这一部分,不是void),构造方法名必须和类名相同
-
每个类默认有一个隐藏无参数的构造方法,方法体中没有内容,用于创建无参数的对象
-
如果自己写了有参数的构造方法,默认无参数的构造方法就会失效。如果想要同时拥有带参数和不带参数的构造方法,就需要把它们都写出来
-
构造方法可以限制创建对象时的参数
-
构造方法不能通过“.”操作符访问,只能通过new关键字创建对象时自动调用,所以构造方法通常用于初始化成员变量
面向对象的三大特性之封装
概念
使用private关键字对属性进行修饰。再对外提供一组公开的get/set方法用于对该属性读取或赋值。
可以防止除自身类之外的地方对该属性就行访问。
这样做可以保护关键属性,隐藏类内部的实现细节
步骤
-
创建类,编写成员变量,给成员变量添加private修饰符
-
给所有成员变量添加setXXX方法,用于给私有的成员变量赋值
-
给所有成员变量添加getXXX方法,用于读取私有的成员变量
-
这是创建对象后,无法通过.访问属性,只能通过get/set方法
面向对象的三大特性之继承
概念
类A可以通过extends关键字继承类B。
语法:class 类A extends 类B{}
类A称为子类、派生类、衍生类、subClass
类B称为父类、根类、超类、superClass
继承后,子类可以访问父类中非私有(没有被private修饰的内容)的属性和方法。
特点
-
如果多个类之中有相同或类似的代码,可以将这些代码提取出来定义在一个公共的类中,这个类就是父类。再让那些类就继承这个父类,那些类就是子类,这样就能减少子类中的重复代码
-
子类可以对父类中的方法进行扩展或覆盖,这称为方法重写。重写后,子类对象再调用该方法时,执行的是重写后的内容
-
Java中是单继承。一个子类只能extends一个父类,一个父类可以有很多个子类
-
Java中可以多重继承。类A可以继承类B,类B可以继承类C,这时类A既是类B的子类,也可以称为类C的子类,可以访问类B与类C中非私有的成员
-
任何类都是Object类的子类
-
在创建子类对象时,会先执行父类中相应的构造方法
方法的重写
当子类继承父类后,可以对父类中非私有的方法进行扩展或覆盖,这个过程称为方法重写。
方法重写要求:
-
方法名、参数列表、返回值必须和父类一致
-
访问权限不能比父类更严格(访问修饰符的范围要么一致要么更大)
-
不能抛出比父类更大的异常
方法的重载
在一个类中,如果多个方法的方法名相同,参数列表不同时,这些方法称为重载的方法。
同名不同参。
方法重载要求:
-
方法名相同
-
参数列表(参数类型和数量)不同
-
与返回值无关
this和super
当对象使用
用法:“this.属性”或“this.方法”或“super.属性”或“super.方法”
此时的this或super表示“当前类”或"父类对象"。
当构造方法使用
用法:"this([参数])或super([参数])"
此时的this([参数])或super([参数])表示当前类或当前类的父类的某个构造方法。
final关键字
-
当final修饰属性时,该属性的值不可更改。定义属性时,在属性前加上final,这时的属性称为常量。常量命名时,所有字母都大写,多个单词之间用_隔开。
-
修饰方法:当final修饰方式时,该方法不能被重写。定义方法时,在返回值前加上final。
-
修饰类:当final修饰类时,该类不能被继承。定义类时,在class前加上final。
Object类
是Java中所有类的父类。每个类都是这个类的子类,但没有用extends体现出来。
该类中定义了很多方法,通常需要进行重写。
向上/向下转型
向下转型:
父类对象转换为子类对象的过程,称为向下转型。(强制转换)
向上转型:
子类对象转换为父类对象的过程,称为向上转型。(自动转换)
面向对象三大特性之多态
概念
多态就是子类的对象指向父类的引用(子类对象使用父类变量接收,即向上转型)。
父类 变量 = new 子类();
多态的实现条件
-
在继承关系中
-
子类需要重写父类中的方法
-
父类的引用指向子类的对象(向上转型)
抽象abstract
-
修饰方法
使用: 访问修饰符 abstract 返回值类型 方法名(参数类型 形参名称);
如果一个方法的方法体无法描述,是由其子类进行重写,可以将该方法定义为抽象方法。
该抽象方法所在的类,也必须用abstract修饰,让其成为一个抽象类。
-
修饰类
使用: 访问修饰符 abstract class 类名{}
如果一个类中有抽象方法,这个类必须也是一个抽象类。
抽象类不能被实例化(不能创建对象)。
抽象类中,可以存在非抽象方法,如getter/setter或构造方法。
当抽象类的构造方法执行时,不会创建对象。
当一个类不希望创建它本身对象或在它其中有抽象方法时,就将该类定义为抽象类。
接口interface
在Java中,数据类型分为基本类型和引用类型。
引用类型包含:数组、类和接口。
所以接口是一种数据类型,类似于类,在定义接口的时候,用interface替换class。
接口的特点
-
接口中的属性默认被public static final修饰,表示公共的静态常量,需要赋值。使用时直接通过类名访问。
-
接口中的方法默认被public abstract修饰,表示公共的抽象方法,没有方法体。
-
JDK1.8后,接口中可以存在两种特殊的方法,都有方法体
-
被default修饰的默认方法
-
被static修饰的静态方法
-
-
接口中没有构造方法,不能创建对象。
-
接口通常需要子类实现,实现后必须重写其中的所有抽象方法。
static静态的
-
static是一个修饰符,可以修饰属性、方法、代码块。被static修饰的内容,称为静态成员。静态成员在类加载的时候,就会保存到内存中,可以脱离对象存在。所以访问静态成员时,可以不用创建对象,直接通过类名访问。如Math中的属性和方法都是静态的,所以直接通过Math访问。
-
直接通过类名就能访问静态成员。也可以通过对象访问。
-
static修饰属性时,通常和final一起使用,表示静态常量
java面向对象应用案例
案例:使用面向对象实现三个游戏的运行
创建game类
他是其他三个游戏的父类
代码如下:
package game;
public class game {
private String name;
public void playGame(){};
public game(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
创建game1类
他实现的是石头剪刀布游戏
代码如下:
package game;
import java.util.Random;
import java.util.Scanner;
public class game1 extends game{
@Override
public void playGame() {
System.out.println("0表示石头");
System.out.println("1表示剪刀");
System.out.println("2表示布");
System.out.println("请输入一个数字");
Scanner as =new Scanner(System.in);
int num=0;int num1=0;
for (int i = 0; i < 3; i++) {
int input=as.nextInt();
Random rd=new Random();
int res=rd.nextInt(2);
if ((input==0&&res==1)||(input==1&&res==2)||
(input==2&&res==0)){
System.out.println("本次你赢了");
num++;
if (num==2){
System.out.println("恭喜你赢了整场游戏");
}
}
else if(input==res){
System.out.println("本次平局");
}
else {
System.out.println("这次你输了");
num1++;
if(num1==2){
System.out.println("这场游戏你输了");
return;
}
}
}
}
public game1(String name) {
super(name);
}
}
创建game2类
实现猜数游戏
代码如下:
package game;
import java.util.Random;
import java.util.Scanner;
public class game2 extends game{
@Override
public void playGame() {
System.out.println("请选择难度");
System.out.println("1:简单");
System.out.println("2:困难");
System.out.println("3:地狱");
Scanner as=new Scanner(System.in);
int num=as.nextInt();
int all=0;
int num2=0;
if(num==1){num2=10;}
else if(num==2){num2=100;}
else if(num==3){num2=1000;}
else {
System.out.println("输入错误");
}
Random rd= new Random();
int res = rd.nextInt(num2);
System.out.println("请输入1到"+num2+" 的其中一个数");
for (int i = 0; i < num2; i++) {
int num1=as.nextInt();
all++;
if(num1==res){
System.out.println("恭喜猜对,游戏结束");
if(all==1){
System.out.println("恭喜获得一等奖");
break;
}else if(all>1&&all<3){
System.out.println("恭喜获得二等奖");
break;
}else {
System.out.println("谢谢惠顾");
break;
}
}
else if(num1<res){
System.out.println("猜小了");
}else{
System.out.println("猜大了");
}
all++;
}
}
public game2(String name) {
super(name);
}
}
创建game3类
实现双色球模拟抽奖
package game;
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
public class game3 extends game{
@Override
public void playGame() {
Random rd=new Random();
int [] red=new int[6];
for(int i=0;i<red.length;i++){
red[i]=rd.nextInt(33)+1;
for(int j=0;j<i;j++){
if (red[i]==red[j]){
i--;
}
}
}
Arrays.sort(red);
int blue=rd.nextInt(16)+1;
Scanner as=new Scanner(System.in);
System.out.println("请输入6个红色号码球的号码:范围是1到32");
int [] red1=new int[6];
for (int i = 0; i < 6; i++) {
red1[i]=as.nextInt();
}
System.out.println("请输入1个蓝色号码球的号码:范围是1到16");
int blue1=as.nextInt();
int num=0;int num1=0;
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 6; j++) {
if(red[i]==red1[j]){
num++;
}
}
}
if(blue==blue1){
num1=1;
}
//结果公布环节
if(num==6&&num1==1){
System.out.println("恭喜您中了一等奖");
}else if(num==6&&num1==0){
System.out.println("恭喜您中了二等奖");
}else if(num==5&&num1==1){
System.out.println("恭喜您中了三等奖");
}else if((num==5&&num1==0)||(num==4&&num1==1)){
System.out.println("恭喜您中了四等奖");
}else if((num==4&&num1==0)||(num==3&&num1==1)){
System.out.println("恭喜您中了五等奖");
}else if((num==2&&num1==1)||(num==1&&num1==1)||(num==0&&num1==1))
{
System.out.println("恭喜您中了六等奖");
}
else {
System.out.println("您未中奖,欢迎下次购买");
}
}
public game3(String name) {
super(name);
}
}
创建play类
该类用于编写main类,使项目能够运行
代码如下
package game;
import java.util.Scanner;
public class play {
public static void main(String[] args) {
System.out.println("欢迎进入,请输入你的账号和密码");
Scanner as=new Scanner(System.in);
for (int i = 0; i < 3; i++) {
String username=as.next();
int password=as.nextInt();
if("username".equals(username)&&password==123456){
System.out.println("账号密码正确,登陆成功");
System.out.println("请根据提示选择你想要玩的游戏");
System.out.println("编号\t游戏名称");
System.out.println("1\t石头剪刀布游戏");
System.out.println("2\t猜数游戏");
System.out.println("3\t双色球模拟游戏");
System.out.println("0:退出游戏");
System.out.println("请输入你想要玩的游戏的编号");
while (true){
switch (as.nextInt()){
case 1:
game1 game=new game1("石头剪刀布游戏");
game.playGame();
System.out.println("这个小游戏已经结束。请选择游戏或者退出");
break;
case 2:
game2 game5=new game2("猜数游戏");
game5.playGame();
System.out.println("这个小游戏已经结束。请选择游戏或者退出");
break;
case 3:
game3 game6=new game3("双色球模拟游戏");
game6.playGame();
System.out.println("这个小游戏已经结束。请选择游戏或者退出");
break;
case 0:
System.out.println("游戏即将退出");return;
default:
System.out.println("不能存在该游戏,请重新输入");
}
}
}else {
System.out.println("账号或密码错误,请重新输入");
}
if(i==2){
System.out.println("输入次数已达上限,程序即将退出");
}
}
}
}
项目运行的一些截图
整个项目主要设计思路
-
三个游戏都有一些相同的属性及方法,就能够使用一个game类作为父类,将这些共同的方法:public void playGame(){};写入进去。
-
三个游戏都是game类的子类,继承game类的属性及方法。但是每个游戏的play方式不同,就需要重写public void playGame(){};方法。
-
play类用于编写mian方法。实现通过账号密码登录,进入页面后根据提示,选择合适的编号选择想要玩的游戏或者退出。
学习总结
对于面向对象部分的内容,个人感觉是比较抽象的。他是将完成整个项目的所有方法分离出来,当有需要的时候再去调用。特别是对于继承这块,父类和子类之间的关系更为抽象,还有就是抽象方法,构造函数机器重载,重写。而面向过程只是根据完成事件的过程依次编写程序。但是,面向对象确是主流的编程思想,他可以实现复杂的,过程繁琐的项目,根据定义一系列的类和方法,通过适当的时候进调用,从而完成整个项目。面向过程对于这类情况难度很大,代码重复率高,效果不好。个人认为,这部分内容比较注重理解,需要记住的知识点和内容远不如java基础。