Java 第二周学习总结

这篇博客总结了Java学习的第二周内容,主要包括数组的声明、初始化和操作,以及面向对象的基础,如类、对象、属性、方法、构造器、继承和访问修饰符。还介绍了多维数组、排序算法、递归、动态数组和二维数组的概念。此外,文章讨论了面向对象编程中的封装、信息隐藏、构造器和类之间的关系。
摘要由CSDN通过智能技术生成

Java 第二周学习总结

一、数组

数组即一组用于存储相同数据类型的数据结构;数组是一种典型的线性结构(连续)。比如将一些商品数据呈现到页面中,此时可以将所有商品存储到数组中进行传递。数组是一种引用数据类型。数组中的每一个值都称之为元素

数组的声明和初始化

java中对输入的声明语法如下:

数据类型[] 数组名;
数据类型 数组名[];
//推荐
int[] i;
//不推荐
int j[];

double[] d;
boolean[] b;
char[] c;
String[] s;

数组初始化

动态初始化即,在声明数组时只指定数组的容量,不为数组中指定位置赋值

//声明一个长度(容量)为5的数组
int[] arr = new int[5];
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;

arr[4] = 60;

System.out.println(arr[4]);

操作数组

组中每一个元素都有一个独一无二的索引(下标),通过语法数组名[索引]可以获取数组中指定位置的元素;数组的索引从0开始;比如一个数组中有10个元素则索引从0~9;任何一个数组都包含一个length属性用于获取数组中元素的个数;

int[] arr = {10,20,30,40};
//获取数组中第4个元素
int i = arr[3];

注意事项:
在对数组操作时如果下标(索引)使用不当 ,则会导致一个异常出现:
java.lang.ArrayIndexOutOfBoundsException

增强for循环-forEach
语法:

for(数据类型 变量名:数组名){
    //循环体
}

以上循环中的数据类型表示的数组中每个元素对应的数据类型

int[] arr = {1,4,5,7,9,11,13,19};
//增强for循环(forEach:迭代器-Iterator)
for(int n:arr) {
    System.out.println(n); 
}


String[] names = {"德玛西亚","瑞兹","易大师","墨菲特"};
for(String name:names) {
    System.out.println(name);
}

多维数组(二维数组)

**多维数组即数组中的数组。**在实际的应用中多维数组的使用也很常见(比如二维数组),电影院座位布局,教室座位布局,游戏开发中游戏元素的坐标。

声明语法

数据类型[][] 数组名
数据类型 数组名[][]
int[][] i;
//不推荐
int i[][];

二维数组即数组中的数组,一个数组中的每一个元素还是一个数组

int[][] i = {
    {1,3,5},
    {2,4,6},
    {8,9}
};
	
//		System.out.println(i[1][1]); 
//		System.out.println(i[2][1]); 	

//二维数组的遍历
//行
for(int m = 0; m < i.length;m++) {
    //列
    for(int n = 0;n < i[m].length; n++) {
        int e = i[m][n];
        System.out.print(e+" ");
    }
    System.out.println();
}
System.out.println("=================");
//1. 使用forEach对以上二维数组遍历
for(int[] m:i) {
    for(int n:m) {
        System.out.print(n+" ");
    }
    System.out.println();
}

数组复习

  1. 数组时一种只能够存储相同数据类型的数组结构
  2. 数组中每一个元素都有一个索引
  3. 数组中的索引从0开始
  4. 任何数组都存在length属性
  5. 数组的长度一旦定义则无法改变
  6. 数组动态初始化必须要指定长度(对于二维数必须要指定行数)

数组常见练习

去零问题
  1. 有一个数组{19,0,7,5,0,2,0,11,22,32,0},将数组中非0的数存储到一个新数组中
int[] i = {19,0,7,5,0,2,0,11,22,32,0};
//1.统计不为0的数总数
int count = 0;
for(int n:i) {
    if(n != 0) {
        count++;
    }
}

//2.根据不为0的数个数创建对应容量的新数组
int[] j =  new int[count];

//3.将原数组中不为0的数存储到新数组
for(int m = 0,n = 0;m < i.length; m++) {
    if(i[m] != 0) {
        j[n++] = i[m];
    }
}

//输出新数组的元素
for(int n:j) {
    System.out.println(n);
}

排序

冒泡排序

每两个相邻的数比较

/**
 * 冒泡排序
 * @author mrchai
 *
 */
public class Exp02 {

	public static void main(String[] args) {
		
		int[] a = {9,5,4,8,7,6,3,18,2,1,11,12};
		
		for(int i = 0;i < a.length;i++) {
			//初始临时变量
			int t = 0;
			for(int j = 0;j < a.length - 1;j++) {
				//判断左边的数是否大于右边的数
				if(a[j] > a[j + 1]) {
					t = a[j];
					a[j] = a[j + 1];
					a[j + 1] = t;
				}
			}
			//输出第n趟排序
			System.out.print("第"+(i+1)+"趟:");
			for(int n:a) {
				System.out.print(n+" ");
			}
			System.out.println();
		}
		
	}

}
选择排序

从第一个数开始依次跟之后的每一个数比较

public class Exp03 {

	public static void main(String[] args) {
		
		
		int[] a = {9,5,4,8,7,6,3,18,2,1,11,12};
		
		for(int i = 0;i < a.length; i++) {
			//声明临时变量
			int t = 0;
			for(int j = i + 1;j < a.length; j++) {
				if(a[i] > a[j]) {
					t = a[i];
					a[i] = a[j];
					a[j] = t;
				}
			}
			//输出第n趟排序
			System.out.print("第"+(i+1)+"趟:");
			for(int n:a) {
				System.out.print(n+" ");
			}
			System.out.println();
		}
	}
}
折半查找(二分法)

折半查找也叫二分法,或者二分查找;从一组已经排好序的数组中搜索目标数的为止,思路:

  1. 先从数组中找到中间数
public class Exp05 {

	public static void main(String[] args) {
		//原数组
		int[] a = {1,2,3,4,5,6,7,8,9,11,12,18,22,30,45};
		//目标数
		int target = 22;

		//初始开始搜索位置
		int start = 0;
		//初始终止搜索位置
		int end = a.length-1;
		
		//初始目标数位置
		int index = -1;
		
		//统计搜索次数
		int count = 0;
		//当起始的搜索位置小于等于结束的搜索位置时执行比较
		while(start <= end) {
			//搜索次数递增
			count++;
			//获取中间数位置
			int mid = (start + end) / 2;
			//判断中间数和目标数的大小
			if(target > a[mid]) {
				//如果目标数大于了中间数,则搜索的起始位置设置到中间数位置+1
				start = mid + 1;
			}else if(target < a[mid]) {
				//如果目标数小于中间数,则搜索的结束位置设置到中间数位置-1
				end = mid - 1;
			}else {
				//找到目标数
				index = mid;
				break;
			}
		}	
		System.out.println("搜索次数"+count+"目标数位置:"+index);	
	}
}
约瑟夫环
/**
 * 约瑟夫环
 * 有500个人围城一个圈,依次报数,每数到3的倍数的人离开圈,数完一圈后继续从1开始数,
 * 直到圈中剩下最后一个人,求剩下的人原来在圈中的位置(约瑟夫环问题)
 * @author mrchai
 *
 */
public class Exp07 {

    public static void main(String[] args) {
        //初始一个长度未500的布尔数组,表示所有人是否在圈中
        boolean[] b = new boolean[500];
        //初始所有人都在圈中
        for(int i = 0;i < b.length;i++) {
            b[i] = true;
        }

        //当前遍历到的索引
        int index = 0;
        //计数器(统计目前数到几)
        int count = 0;
        //初始总人数
        int len = b.length;

        //只要总人数超过1个就循环报数
        while(len > 1) {
            //判断当前报数的人是否在圈中
            if(b[index]) {
                //计数器递增
                count++;
                //判断是否到达3
                if(count == 3) {
                    //如果到达3则当前位置的人从圈中离开
                    b[index] = false;
                    //人数减少一个
                    len--;
                    //计数器归零
                    count = 0;
                }
            }
            index++;
            //判断是否已经数完一圈
            if(index == b.length) {
                index = 0;
            }
        }

        //对数组遍历
        for(int i = 0;i<b.length;i++) {
            //获取每一个位的结果
            if(b[i]) {
                //如果其中有一个元素为true,则表示剩下的最后一个人
                System.out.println("最后剩下的人原来在圈中的位置:"+i);
                break;
            }
        }

    }

}
数组拷贝

System类中提供了arraycopy方法用于实现数组拷贝功能,该方法包含5个参数:

/*
* 参数1:需要被拷贝的原始数组
* 参数2:原数组的起始拷贝位置
* 参数3:目标数组
* 参数4:目标数组的存储起始位置
* 参数5:需要从参数1数组中拷贝元素个数
*/
int i = 100;
int[] a = {12,22,11,10,10};

int[] b = new int[a.length << 1];

//数组拷贝
/*
* 参数1:需要被拷贝的原始数组
* 参数2:原数组的起始拷贝位置
* 参数3:目标数组
* 参数4:目标数组的存储起始位置
* 参数5:需要从参数1数组中拷贝元素个数
*/
System.arraycopy(a, 0, b, 0, a.length); 
b[a.length] = i;

for(int n:b) {
    System.out.println(n);
}
动态数组

由于Java中的数组的长度一旦定义则无法改变,但是可以通过数组拷贝的方式实现数组容量扩充(创建新数组,将原来数组中的内容拷贝到新数组中);因此,Java中提供一个集合工具类:java.util.ArrayList可以用于存储任意类型的元素,并且,容量可以自动扩充;一旦ArrayList的容量超出,在下一次加入元素时会自动创建一个容量为原来数组1.5倍的新数组。
ArrayList基本使用:

public class ArrayListDemo {

    public static void main(String[] args) {
        //动态数组(长度可变(逻辑)的数组) 多态
        //实现原理即:数组  + 数据拷贝
        ArrayList list = new ArrayList();  //创建一个长度为0的空数组

        list.add(10);
        list.add(20);
        list.add(30);
        list.add(40);
        list.add(50);
        list.add(60);
        list.add(70);
        list.add(80);
        list.add(true);
        list.add("hello");
        list.add(3.14);

        System.out.println(list);
        System.out.println(list.size()); 
        System.out.println(list.get(7)); 

        //创建一个只能存放整数类型的动态数组
        ArrayList<Integer> list2 = new ArrayList<>(); 
        list2.add(10);
        list2.add(5);

    }

}
二维数组

二位数组即数组中的数组,一个数组中的每一个元素还是一个数组

int[][] i = {
    {1,3,5},
    {2,4,6},
    {8,9}
};
	
//		System.out.println(i[1][1]); 
//		System.out.println(i[2][1]); 	

//二维数组的遍历
//行
for(int m = 0; m < i.length;m++) {
    //列
    for(int n = 0;n < i[m].length; n++) {
        int e = i[m][n];
        System.out.print(e+" ");
    }
    System.out.println();
}
System.out.println("=================");
//1. 使用forEach对以上二维数组遍历
for(int[] m:i) {
    for(int n:m) {
        System.out.print(n+" ");
    }
    System.out.println();
}

二、面向对象入门

面向对象程序设计概述

程序设计语言发展史

在这里插入图片描述

面向对象程序

Java中万事万物皆对象,面向对象编程即:将现实生活的事物以计算机的语言进行描述

类和对象

面向对象中的两个核心概念:

  1. 类:对一类具备相同特征(属性行为)事物的抽象描述;例如:学生类
  2. 对象:类的一个实例;例如:学号时123的学生
类的成分

由于类中包含一类事物的属性和行为,因此类的成主要由属性和行为构成,对于以上两个特征Java中以如下的方式呈现:
属性---->变量
行为---->方法(函数)

类的声明语法:
[<修饰符>] class 类名称 {
    //属性的定义
    //行为的定义
}

例如:

public class Student {

	//属性:成员变量、全局变量、实例(对象)变量 
	String sno;
	String sname;
	int age;
	char sex;
	/**学分*/
	double score;
	/**学校*/
	String school = "**大学";
	/**专业*/
	String major;
	
	//行为:方法(函数 function)  f(x)
	public void study() {
		System.out.println("good good study,day day up!!!"); 
	}
	
	public void play() {
		System.out.println("一起来玩有游戏吧!!");
	}
	
}
属性

属性用于描述类的静态信息,表示类的数据;语法

[<修饰符>] 数据类型 变量名 = [<默认值>]

例如:

String sno;
String sname;
int age;
char sex;
/**学分*/
double score;
/**学校*/
String school = "**大学";
方法

类中另一个组成部分称之为行为,行为在java中的呈现方式以方法(函数)的形式存在,语法:

[<修饰符>] 返回值类型 方法名([<参数列表>]) {
    //执行体
}

例如:

public void study(String kecheng,int hours) {
    System.out.println("good good study,day day up!!!"); 
}

public void play() {
    System.out.println("一起来玩有游戏吧!!");
}
对象创建与使用

对象即对类的具象化,即类的一个实例

构造器

方法详解

方法(Method)是由一些表达式组成的代码片段,通常用于完成某些特定的功能,实际开发中可以将一些反复需要使用到的代码编写到方法中,只需要对方法进行调用,即可执行这些代码片段,从而提高的代码的可复用性。

方法的分类

根据方法的声明语法:

[<修饰符>] 返回值类型 方法名([<参数列表>]) {

}

由于方法结构中包含返回值类型参数成分,根据这两个成分的组合,方法可以分为4中类别:

  • 无参数无返回值
  • 无参数有返回值
  • 有参数无返回值
  • 有参数有返回值
	public class Tools {

    /**
	 * 有参有返回值
	 * @param a  数值1
	 * @param b  数值2
	 * @return 返回两个数值中较大的一个
	 */
    public int max(int a,int b) {
        return a > b ? a : b;
    }

    /**
	 * 无参有返回值
	 * 返回字符串时间
	 * @return
	 */
    public String nowTime() {
        return  "2020年11月3日 10:46:22";
    }

    /**
	 * 有参无返回值
	 * 打印输出参数内容
	 * @param msg
	 */
    public void log(String msg) {
        System.out.println(msg);
    }

    /**
	 * 无参无返回值
	 */
    public void tips() {
        System.out.println("天气冷了,多穿衣服,多喝开水!");
    }

    public static voi	d main(String[] args) {
        Tools t = new Tools();
        //调用包含返回值的方法,并且使用对应的数据类型变量接收返回值
        int i = t.max(10, 15);
        System.out.println(i);

        String time = t.nowTime();
        System.out.println(time);

        t.log("helloworld,你好,世界"); 

        t.tips();

        // 创建一个方法,要求提供一个年份,返回该年份是否是闰年
    }
}

参数(Parameter):在执行方法时需要传递到方法中使用的一些数据,参数的类型可以是任意的,数量可以是任意多个,参数顺序也可以任意的,在声明方法时定义的参数,称之形式参数(形参);在对象方法进行调用时传入的参数称之实际参数(实参)。
返回值(returns):在方法执行完毕之后,传递到方法之外的数据;返回值的类型可以是任意,返回的具体值(或者变量)必须要跟方法定义的返回类型匹配。

方法调用

java中方法的调用需要通过对象完成,语法如下:

引用对象.方法名(实参)
//对象创建(实例化对象)
Student stu = new Student();
//调用方法
stu.play();

值传递问题

基本类型传递问题

观察以下代码,给出程序运行结果:

public class Test {

	public void change(int i) {
		i = 10;
		System.out.println("change--->" + i); // 10;
	}
	
	
	public static void main(String[] args) {
		
		int a = 5;
		System.out.println("change前:" + a); //5
		Test t = new Test();
		t.change(a);
		System.out.println("change后:" + a); // ?
	}
}

结果:

change前:5
change--->10
change后:5

分析以上程序,可以看出java中参数的传递为值传递,不存在引用传递的问题,change方法中改变的只是内部定义的局部变量i,不会影响main方法中的局部变量,内存模型如下:
在这里插入图片描述
注意事项:
java中局部变量的存储位置位于方法帧栈中,成员变量的存储位于堆内存中

引用类型参数传递问题

以上实例修改之后,观察执行结果

public class TestDog {
	
	public void change(Dog d) {
		System.out.println("change:"+d);
		d.nickname = "旺财";
	}

	public static void main(String[] args) {
		
		Dog d = new Dog();
		System.out.println(d);
		d.nickname = "来福";
		System.out.println("change前:" + d.nickname);
		TestDog td = new TestDog();
		td.change(d);
		System.out.println("change后:" + d.nickname);
		
	}
}

class Dog{
    String nickname;
}

以上程序执行的内存模型:
在这里插入图片描述

递归(Recursion)

递归即在一个方法内部对方法自身调用,递归可以以简单的代码解决复杂的算法问题,对文件夹的遍历,树形菜单遍历等等;递归操作不当将会导致栈溢出错误StackOverflowError
递归实例:

//5!
public int m(int n) {
    if(n == 1) {
        return 1;
    }else {
        return n * m(n - 1);
    }
}

//1+2+...+100
public int add(int n) {
    if(n == 1) {
        return 1;
    }else {
        return n + add(n - 1);
    }
}

//斐波拉契数列
public int fib(int n) {
    if(n == 1 || n == 2) {
        return 1;
    }else {
        return fib(n - 1) + fib(n - 2);
    }
}

类的成分

一个类属性和行为构成:
属性:描述指定类型的数据(名词)
行为:描述指定类型的一种动作(动词)

属性详解(Field)

属性用于描述类的一些静态信息(数据),属性在代码中的呈现方式为变量,java中的变量根据出现的位置不同,又分为两种:

  • 全局变量(global variable)
    也称之成员变量,实践(对象)变量;直接在类结构中定义与方法同一级别,成员变量可以出现在类中的任意非静态方法中,成员变量在类加载时编译器会自动为期设置初始值(即便不手动赋值都存在默认值)
    案例:
public class People {

	// 成员变量
	String name;
	int age;
	String sex;
	double height;
    
}

各种类型成员变量的默认值

  byte     0
  short    0
  int      0
  long     0
  float    0.0
  double   0.0
  char     <空格>
  boolean  false
  
  引用类型   null
  • 局部变量(local variable)
    也称之为临时变量;局部变量一般位于方法内部声明,方法的参数也是局部变量,局部变量的作用范围仅限于声明的区域;局部变量没有初始化前不能使用
    案例:
public void speak(String s) {
    int i = 10;
    System.out.println(name + "说:" + s);
}

if(true){
    int i = 10;
}

{
    int i = 10;
}

static{
    int i = 10;
}

构造器详解

构造器也称之为构造方法,构造函数,构建器;作用于对象创建时完成对于对象的相关属性初始化操作,减少方法对于参数依赖,可以直接在方法中使用由构造器赋值的成员变量;构造器是一种特殊的方法,语法规范:

[<修饰符>] 类名称([<参数列表>]){
   //执行体
}

案例:

public Goods(){
    
}

public People(){
    
}
构造器的定义范围
  1. 构造器的名称必须跟类名称一致
  2. 构造器不能包含类型的返回值(包括void)
构造器注意事项
  1. 任何一个Java类存在一个默认的无参构造器(编译器自动添加)
  2. 如果一旦定义自定义的构造器,则默认无参构造器会被覆盖
  3. 一个类可以存在多个构造器,但是构造器中的参数个数,类型,顺序任意有一项不一致(方法的重载)
构造器使用

构造器的调用一般通过new关键字进行调用,一旦执行,就完成了对象的创建以及初始化。

new 构造器();

案例:

People p = new People();
Goods g = new Goods();
访问修饰符

Java中的访问修饰符分为4个

  • defualt(空白)
    不使用任何访问修饰符时,目标元素只能在同一个类或者同一个包的其他类被访问
  • private
    被private修饰的元素,只能够在当前类中被访问
  • protected
    被protected修饰的元素,只能在同一个包中,或者跨包的子类中被访问
  • public
    被public修饰的元素可以在同一个项目中的任意包被访问
    在这里插入图片描述
    各种访问修饰符的访问范围图
    在这里插入图片描述

使用原则:
类一般使用public修饰(普通的类无法使用private和protected修饰)
属性一般使用private修饰
方法一般使用public

封装

面向对象语言包含三大核心特征:

  • 封装
  • 继承
  • 多态
信息隐藏

信息隐藏是java中对类的一种保护机制,将一个类的具体实现细节隐藏起来,隐藏通常指的是使用private修饰符对属性或者方法修饰,使得外界无法随意访问该类中的成分。

对于一些属性来说,如果对外公开,则外界一旦获取到该类的实例(对象),即可对该公开的属性进行随意访问甚至修改,从而会造成一些不要的安全问题。

Setter & Getter方法

将类中的属性设置为private之后,外界无法访问,但是可以通过提供公开的方法对这些私有的属性进行访问。让外界访问方法的可控性要远远高于直接让外界访问属性;对于上述的操作,Java中提供了两种用于对属性操作的方法:

  • setter
  • getter
public class People {

	private String idCard;
	private String name;
	private int age;
	private String sex;
	private boolean marry;
	
	public String getIdCard() {
		return idCard;
	}
	public void setIdCard(String idCard) {
		this.idCard = idCard;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		if(age > 18) {
			age = 18;
		}
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	/**
	 * boolean类型属性的get方法叫isXXX
	 * @return
	 */
	public boolean isMarry() {
		return marry;
	}
	public void setMarry(boolean marry) {
		this.marry = marry;
	}
	
}
this关键字

this关键字在一个类中用于表示"当前对象”;this一般用于一个类的成员方法、构造器或者游离块中,作用于调用当前类的构造器,属性和其他方法

public class Dog {

	private int id;
	private String name;
	
	public Dog() {
        //		构造器中如果调用了其他构造器,则调用代码必须位于最前端
		//		System.out.println("---");
		//调用包含String类型参数的构造器
		this("来福");
	}
	
	public Dog(String name) {
		System.out.println("执行带参数构造器。。。。");
		this.name = name;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public void eat() {
		System.out.println(name+"吃肉肉");
	}
	
	public void drink() {
		System.out.println(name+"和奶茶");
	}
	
	public void sleep() {
		System.out.println(name+"碎觉觉");
	}
	
	public void oneDay() {
		System.out.println(this);
		this.eat();
		this.drink();
		this.sleep();
	}
	
	
	public static void main(String[] args) {
		Dog d = new Dog();
		System.out.println("$$$$"+d);
		d.oneDay();

	}
}

在这里插入图片描述

类之间关系(软件工厂与统一建模语言UML)

面向对象设计语言中,类和类之间是存在一定关系的,从关系角度考虑,分为两种:

  • 横向关系(平级)
  • 纵向关系(上下级)
横向关系

横向关系一般表示为多个类之间是同一级别,横向关系又分为以下几类

  1. 依赖关系
    依赖关系表示为一个类的方法中需要另一个类型对象作为参数
public class Cat{
   
    //依赖关系的代码表现方式
    public boolean catchMouse(Mouse m) {
    
       return false;
    }
}
  1. 关联关系
  2. 聚合关系
  3. 组合关系
    关联,聚合,组合三种关系在代码的表现形式上是相同,只是存在语义上的区别,主要区别为类和类之间的紧密程度;代码层面的表现方式是在一个类中将另一个类型对象作为属性定义。
public class Dept{
    
    private int dno;
    private String dname;
    private String tel;
    
    //setter/getter ...
}
public class Emp{
    
    private int eno;
    private String ename;
    private double sal;
    //员工关联部门
    private Dept dept;
    
    //setter/getter ...
}
典型的关联关系实例:
  • 学生选课系统类设计
    在这里插入图片描述
纵向关系

纵向关系是一种上下级的关系,表现方式在Java中通常以以下两种形式呈现:

  1. 继承(extends)
  2. 实现
继承(extends)

继承是面向对象程序设计中另一个重要的特征,继承即由一个类从另一个通过extends关键字继承,被继承的类称之为父类(也叫超类),继承的类称之为子类(扩展类);继承可以使得类的扩展性提高,减少重复代码的编写。
语法:

[<修饰符>] class 子类 extends 父类 {
    
}

实例:
父类Father:

public class Son extends Father{

	//通过代码表现:动物 猫 老鼠之间的关系
	public static void main(String[] args) {
		Son s = new Son();
		s.name = "张三";
		s.coding();
		s.love();
	}
}
继承优点
  • 子类可以直接通过对象调用父类中的非私有元素
  • 子类还可以在父类的基础上扩展新的功能
继承注意事项
  • 子类只能继承父类的属性和方法,不能继承构造器
  • 子类对象构造之前会先执行父类的构造器(如果存在多重继承,则从最顶层父类构造器开始执行)
  • 一个父类可以存在多个子类,但是一个子类只能存在一个父类
  • Java不允许多继承,但是支持多重继承
  • 被protected修饰的元素可以在子类中被访问(即便父类和子类不在同一个包)
super关键字

super关键字用于在子类中调用父类的元素:

  • 构造器
  • 属性
  • 方法
    使用案例:
public class Animal {

    String name = "旺财";
    double weight = 10 ;

    public Animal(String name) {
        //		this.name = name;
    }

    public void eat() {
        System.out.println("动物进食");
    }

    public void bark() {
        System.out.println("咆哮");
    }
}
public class Dog extends Animal{

    public Dog(String name) {
        //调用父类构造器
        super(name);
    }

    public void play() {
        //调用父类方法
        super.eat();
        super.bark();
		//调用父类属性
        System.out.println("我叫:" + super.name);
    }

    public static void main(String[] args) {
        Dog d = new Dog("来福");
        d.play();
    }

}

练习

  1. 模拟地下城与勇士(DNF)的装备强化过程:
    提示1:
  • DNF装备强化在+1~+3 不会失败;
  • +4~+7,失败后物品原有强化等级降低1级;
  • +8~+10,失败后掉3级;
  • 10上11或以上就爆了。

提示2:

  • DNF装备强化1~3级,成功率100%
  • DNF装备强化3~4级,成功率95%
  • DNF装备强化4~5级,成功率90%
  • DNF装备强化5~6级,成功率80%
  • DNF装备强化6~7级,成功率75%
  • DNF装备强化7~8级,成功率62.1%
  • DNF装备强化8~9级,成功率53.7%
  • DNF装备强化9~10级,成功率41.4%
  • DNF装备强化10~11级,成功率33.9%
  • DNF装备强化11~12级,成功率28%
  • DNF装备强化12~13级,成功率20.7%
  • DNF装备强化13~14级,成功率17.3%
  • DNF装备强化14~15级,成功率13.6%
  • DNF装备强化15~16级,成功率10.1%

实现流程:
要求输入装备的原始等级,输入1执行强化,根据原始等级以及强化的成功率,显示装备的强化结果

public void qianghua(int initLevel,int targetLevel) {
		
		int count = 0;
		do {
			count++;
			switch (initLevel) {
			case 0:
			case 1:
			case 2:
				//强化1-3级
				initLevel = q1_3(initLevel);
				break;
			case 3:
			case 4:
			case 5:
			case 6:
				//强化4-7级
				initLevel = q4_7(initLevel);
				break;
			case 7:
			case 8:
			case 9:
				//强化8-10级
				initLevel = q8_10(initLevel);
				break;
	
			default:
				//强化10级以上
				initLevel = q10(initLevel);
				break;
			}
		} while (initLevel < targetLevel && initLevel != -1);
		System.out.println("强化次数:"+count);
	}
	
	/**
	 * 强化1~3级
	 * @param level
	 * @return
	 */
	public int q1_3(int level) {
		System.out.println("强化成功,当前等级为:" + level);
		return ++level;
	}
	
	/**
	 * 随机一个浮点数表示成功率
	 * @return
	 */
	public double d() {
		return Math.random();
	}
	
	/**
	 * 强化4~7级
	 * @param level
	 * @return
	 */
	public int q4_7(int level) {
		int i = level;
		switch (level) {
		case 3:
			i =  d() < 0.95 ? level+1 : level-1;
			break;
		case 4:
			i =  d() < 0.9 ? level+1 : level-1;
			break;
		case 5:
			i =  d() < 0.8 ? level+1 : level-1;
			break;
		case 6:
			i =  d() < 0.75 ? level+1 : level-1;
			break;
		}
		if (i > level) {
			System.out.println("强化成功,当前等级为:" + i);
		}else {
			System.out.println("强化失败,当前等级为:" + i);
		}
		return i;
	}
	
	/**
	 * 强化8~10级
	 * @param level
	 * @return
	 */
	public int q8_10(int level) {
		int i = level;
		switch (level) {
		case 7:
			i =  d() < 0.621 ? level+1 : level-3;
			break;
		case 8:
			i =  d() < 0.537 ? level+1 : level-3;
			break;
		case 9:
			i =  d() < 0.414 ? level+1 : level-3;
			break;
		}
		if (i > level) {
			System.out.println("强化成功,当前等级为:" + i);
		}else {
			System.out.println("强化失败,当前等级为:" + i);
		}
		return i;
	}
	
	/**
	 * 强化10级以上
	 * @param level
	 * @return
	 */
	public int q10(int level) {
		int i = level;
		switch (level) {
		case 10:
			i =  d() < 0.339 ? level+1 : -1;
			break;
		case 11:
			i =  d() < 0.28 ? level+1 : -1;
			break;
		case 12:
			i =  d() < 0.207 ? level+1 : -1;
			break;
		case 13:
			i =  d() < 0.1731 ? level+1 : -1;
			break;
		case 14:
			i =  d() < 0.136 ? level+1 : -1;
			break;
		case 15:
			i =  d() < 0.101 ? level+1 : -1;
			break;
		}
		if (i > level) {
			System.out.println("强化成功,当前等级为:" + i);
		}else {
			System.out.println("强化失败,装备已损坏!");
		}
		return i;
	}
	
	
	public static void main(String[] args) {
		DNF d = new DNF();
		d.qianghua(0,15);

	}
  1. 打印万年历
public class MyCalendar {

	int year;
	int month;
	
	public MyCalendar(int _year,int _month) {
		year = _year;
		month = _month;
	}
	
	/**
	 * 判断指定的年份是否是闰年
	 * 
	 * @param year
	 * @return
	 */
	public boolean isLeapYear(int year) {
		return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
	}

	/**
	 * 根据提供的年份月份,返回当前月的总天数
	 * 
	 * @param y
	 * @param m
	 * @return
	 */
	public int getDaysOfMonth(int y, int m) {
		switch (m) {
		case 4:
		case 6:
		case 9:
		case 11:
			return 30;
		case 2:
			return isLeapYear(y) ? 29 : 28;
		default:
			return 31;
		}
	}

	/**
	 * 计算从1900年1月份到目标的年份月份上一个月的总天
	 * 
	 * @param y
	 * @param m
	 * @return
	 */
	public int getTotalDaysFrom1900() {
		// 局部变量使用前必须先初始化
		int days = 0;
		// 计算整年的总天数1900~(y-1)
		for (int i = 1900; i < year; i++) {
			days += isLeapYear(i) ? 366 : 365; // days = days + 366/365
		}
		// 计算从1-(m-1)月的总天数 1 2 3 4 5 .. 10
		for (int i = 1; i < month; i++) {
			days += getDaysOfMonth(year, i);  // days = days + 28/29/30/31
		}
		return days;
	}

	/**
	 * 打印日历
	 * 
	 * @param y
	 * @param m
	 */
	public void printCalendar() {

		// 获取打印日历之前需要预留的空格数
		int space = getTotalDaysFrom1900() % 7;

		// 获取目标年份月份的总天数
		int days = getDaysOfMonth(year, month);

		System.out.println("============SOFTEEM万年历 【" + year + "】年【" + month + "】月=============");
		System.out.println("一\t二\t三\t四\t五\t六\t日");
		System.out.println("====================================================");
		
		int count = 0;
		//打印空格
		for (int i = 0; i < space; i++) {
			System.out.print("\t");
			count++;
		}
		//打印日期
		for (int i = 1; i <= days; i++) {
			count++;
			System.out.print(i + "\t");
			//是否达到周天
			if(count == 7) {
				System.out.println();
				//计数器归零
				count = 0;
			}
		}
		
	}

	public static void main(String[] args) {
		MyCalendar mc = new MyCalendar(2020,11);
		mc.printCalendar();
	}
}
  1. 基于面向对象实现:猫抓老鼠小游戏有一只猫和一只老鼠,当猫的体重是小老鼠体重的5倍时,猫可以抓到老鼠,猫每吃掉一只老鼠,体重增加老鼠的体重的0.5倍,但是当猫的体重超过了老鼠体重的5倍,猫无法抓到老鼠,老鼠逃脱并对猫发出嘲讽。
public class Cat {
	private String name;
	private double weight;
	
	public Cat() {
		
	}

	public Cat(String name, double weight) {
		this.name = name;
		this.weight = weight;
	}
	
	/**猫抓老鼠*/
	public boolean catchMouse(Mouse m) {
		//判断猫的体重是否小于老鼠体重的5倍
		if (this.weight < m.getWeight() * 5) {
			//猫抓住老鼠,体重增加
			this.weight += m.getWeight() / 2;
			System.out.println(name+"抓住了"+m.getName()+",当前体重:"+this.weight);
			return true;
		}
		m.runaway();
		this.weight -= m.getWeight()/4;
		System.out.println("老鼠"+m.getName()+",成功逃脱,"+this.name+"体重减少,当前体重:"+this.weight);
		return false;
		
		
		
	}
	

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getWeight() {
		return weight;
	}

	public void setWeight(double weight) {
		this.weight = weight;
	}
}
public class Mouse {
	private String name;
	private double weight;
	
	public Mouse() {
		
	}

	public Mouse(String name, double weight) {
		this.name = name;
		this.weight = weight;
	}
	
	public void runaway() {
		System.out.println("大笨猫,来抓我呀....");
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getWeight() {
		return weight;
	}

	public void setWeight(double weight) {
		this.weight = weight;
	}
}
public class TomAndJerry {
	public static void main(String[] args) {
		
		//初始化猫对象
		Cat c = new Cat("Tom",3);
		System.out.println("游戏开始....");
		Scanner sc = new Scanner(System.in);
		while (true) {
			//接收输入:老鼠体重
			System.out.println("请输入老鼠的体重:");
			int w = sc.nextInt();
			//创建老鼠对象
			Mouse m = new Mouse("Jerry",w);
			//判断是否抓住老鼠
//			if (!c.catchMouse(m)) {
//				//一旦老鼠逃脱则游戏结束
//				System.out.println("游戏结束!");
//				break;
//			}
			c.catchMouse(m);
		}
	}

}
  1. 根据LOL,创建一个英雄类(Hero),包含以下属性:

    • 编号(int)
    • 昵称(String)
    • 名称(String)
    • 类型(法师,射手,战士,坦克,辅助,打野)
    • 攻击力(int)
    • 防御力(int)
    • 血量(int)
    • 魔法值(int)

    英雄包含两个构造方法

    1. 无参数
    2. 所有参数

    英雄包含三个方法:

    1. 攻击attack(Hero h)
    2. 死亡
    3. 重生
    4. 移动

    要求完成如下功能:

    1. 分别创建两个不同类型的英雄
    2. 实现攻击的功能(轮流攻击)
    3. 血量先归零的英雄死亡
public class Hero {
	
	/**编号*/
	private int number;
	/**昵称*/
	private String nickname;
	/**真是名称*/
	private String realname;
	/**类型*/
	private String type;
	/**攻击力*/
	private int atk;
	/**防御力*/
	private int defense;
	/**血量*/
	private int hp;
	/**魔法值*/
	private int mp;

	public Hero() {
		
	}

	public Hero(int number, String nickname, String realname, String type, int atk, int defense, int hp, int mp) {
		this.number = number;
		this.nickname = nickname;
		this.realname = realname;
		this.type = type;
		this.atk = atk;
		this.defense = defense;
		this.hp = hp;
		this.mp = mp;
	}

	/**攻击*/
	public void attack(Hero h) {
		//减少被攻击的英雄血量
		h.hp = (int) (h.hp-Math.random() * this.atk)+h.defense/10;
		System.out.println(this.realname+"正在攻击"+h.realname+",血量剩余:"+h.hp);
		System.out.println(h.realname+"英雄防御,血量减少:"+h.defense/10);
		//判断英雄是否死亡
		if (h.hp <= 0) {
			h.die();
		}else {
			h.attack(this);
		}
		
	}
	
	/**移动*/
	public void move() {
		System.out.println("前进10步");
	}
	
	/**复活*/
	public void reLife() {
		System.out.println("我胡汉三有回来了....");
	}
	
	/**死亡*/
	public void die() {
		System.out.println(nickname+"-"+realname+"死亡,10秒之后又是一条好汉!");
	}
}

public class TestHero {

	public static void main(String[] args) {
		
		Hero h1 = new Hero(1,"德玛西亚","盖伦","战士",80,120,800,0);
		
		Hero h2 = new Hero(2,"无极剑圣","易大师","刺客",120,90,600,0);
		
		h1.attack(h2);
	}
}
  1. 基于数组+面向对象完成一个学生信息管理系统,初始化一个长度为100的学生数组,学生信息包含如下:

    • 学号(int)
    • 姓名(String)
    • 性别(String)
    • 年龄(int)
    • 专业(String)
    • 学分(double)

    要求实现以下功能

    1. 完成学生添加的功能呢
    2. 根据指定的学号,删除学生
    3. 根据学号,修改指定学生的学分
    4. 显示所有学生的信息
    5. 查询所有学分超过80的学生信息

    创建两个类:

    1. 学生类(属性,setter/getter,构造器)
    2. 学生管理类(对学生操作的所有方法)
public class Student {
	
	private int sno;
	private String name;
	private String sex;
	private int age;
	/**专业*/
	private String major;
	/**学分*/
	private double score;
	
	public Student() {
		
	}

	public Student(int sno, String name, String sex, int age, String major, double score) {
		this.sno = sno;
		this.name = name;
		this.sex = sex;
		this.age = age;
		this.major = major;
		this.score = score;
	}

	public int getSno() {
		return sno;
	}

	public void setSno(int sno) {
		this.sno = sno;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getMajor() {
		return major;
	}

	public void setMajor(String major) {
		this.major = major;
	}

	public double getScore() {
		return score;
	}

	public void setScore(double score) {
		this.score = score;
	}
	
	/**
	 * 显示当前所有学生的信息
	 */
	public void details() {
		System.out.println(sno+"\t"+name+"\t"+sex+"\t"+age+"\t"+major+"\t"+score);
	}
}
public class StudentManager {
	
	/**声明一个学生数组,用于存储所有的学生对象*/
	private Student[] list;
	/**声明一个索引,用来表示目前数组中元素存储的位置*/
	private int index;
	
	/**对象构造时,初始数组的容量为100*/
	public StudentManager() {
		list = new Student[100];
	}
	
	/**
	 * 添加学生
	 * @param s 学生
	 */
	public void add(Student s) {
		list[index++] = s;
	}
	
	/**
	 * 根据提供的学号删除学生
	 * @param sno 
	 */
	public void del(int sno) {
		//先循环遍历数组中的元素
		int i = findBySno(sno);
		//一旦返回索引为-1则说明指定学号的学生不存在
		if (i==-1) {
			System.out.println("未找到指定学号的学生!");
		}else {
			//逻辑删除
			list[i] = null;
		}
		
//		for(int i=0;i<list.length;i++) {
//			//获取遍历到的一个学生对象
//			Student s = list[i];
//			//判断当前遍历到的学生的学号是否等于需要删除的学生学号
//			if (s.getSno() == sno) {
//				//逻辑删除
//				list[i] = null;
//				System.out.println("删除成功!");
//				return;
//			}
//		}
		
	}	
	
	/**
	 * 根据提供的学号将学生的学分改成指定的学分
	 * @param sno 
	 * @param score
	 */
	public void update(int sno,double score) {
		int i = findBySno(sno);
		if (i == -1) {
			System.out.println("未找到指定学号的学生");
		}else {
			list[i].setScore(score);
			System.out.println("修改成功!");
		}
	}
	
	/**
	 * 根据提供的学号查询学生对象
	 * @param sno
	 * @return
	 */
	private int findBySno(int sno) {
		for(int i=0;i<list.length;i++) {
			Student s = list[i];
			//判断目标位置的学生是否存在,以及学号是否与参数一致
			if (s != null && s.getSno() == sno) {
				//当遍历到的对象存在(即不为null) 且学号等于参数值时,返回学生所在的位置
				return i;
			}
		}
		return -1;
	}
	
	/**
	 * 显示所有的学生信息
	 */
	public void showAll() {
		for(int i=0;i<list.length;i++) {
			Student s = list[i];
			if (s!=null) {
				//显示学生详情
				s.details();
			}
		}
	}
	
	/**
	 * 显示超过指定学分的学生
	 * @param score
	 */
	public void showHighScoreStus(double score) {
		for(int i=0;i<list.length;i++) {
			Student s = list[i];
			if (s!=null && s.getScore() >= score) {
				//显示学生详情
				s.details();
			}
		}
	}	
}
public static void main(String[] args) {
		
		StudentManager sm = new StudentManager();
		
		//添加学生
		sm.add(new Student(1001,"孙悟空","男",500,"散打",99));
		sm.add(new Student(1002,"金角大王","男",499,"挨打",79));
		sm.add(new Student(1003,"白骨精","女",1000,"挨打",69));
		sm.add(new Student(1004,"牛魔王","男",800,"散打",89));
		sm.add(new Student(1005,"白龙马","男",400,"运输",99));
		sm.add(new Student(1006,"沙和尚","男",600,"烹饪",99));
		
		sm.showAll();
		System.out.println("================================");
		sm.del(1004);
		sm.update(1006, 50);
		System.out.println("================================");
		sm.showAll();
		System.out.println("================================");
		sm.showHighScoreStus(70);

	}
}
  1. (1)创建一个叫做机动车的类:
    属性:车牌号(String),车速(int),载重量(double)
    功能:加速(车速自增)、减速(车速自减)、修改车牌号,查询车的载重量。
    编写两个构造方法:一个没有形参,在方法中将车牌号设置“XX1234”,速
    度设置为100,载重量设置为100;另一个能为对象的所有属性赋值;
    (2)创建主类:
    在主类中创建两个机动车对象。
    创建第一个时调用无参数的构造方法,调用成员方法使其车牌为“辽A9752”,并让其加速。
    创建第二个时调用有参数的构造方法,使其车牌为“辽B5086”,车速为150,
    载重为200,并让其减速。
    输出两辆车的所有信息
public class Car {
	
	String card;
	int speed;
	double storage;
	
	//构造器方法
	public Car() {
		card = "xx1234";
		speed = 100;
		storage = 100;
	}
	
	public Car(String $card,int $speed,double $storage) {
		card = $card;
		speed = $speed;
		storage = $storage;
	}
	
	
	public void addSpeed() {
		speed++;
	}
	
	public void minusSpeed() {
		speed--;
	}
	
	public void modifyCard(String $card) {
		card = $card;
	}
	
	public double getStorage() {
		return storage;
	}
	
	/**
	 * 显示当前对象的详细信息
	 */
	public void showInfo() {
		System.out.println("车牌:"+card+",车速:"+speed+",载重量:"+storage);
	}

}
public class TestCar {

	public static void main(String[] args) {
		
		Car c = new Car();
		c.modifyCard("鄂ACM124");
		c.addSpeed();
		c.showInfo();
		
		Car c2 = new Car("琼BMM123",150,200);
		c2.minusSpeed();
		c2.showInfo();
		
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值