Day01~04
## 一、 数据类型和变量
package test;
public class hello {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
语法: 数据类型 标识符 = 变量值;
eg: int i = 0;
### 数据类型:
1个字节占8位:第一个为高位,后面七个为低位;
byte a = -100;
short b = 1000;
int c = 100000;
long d1 = 100;
long d2 = 10000000000l; //太大的数后面要加l,long为8个字节
float e = 3.14f; //不加f默认为double类型
double f = 3.14;
boolean g1 = true; boolean g2 = false;
char h = 'a'; char h2 = '好'; //char只能表示单个字符,占2个字节
数组(Array):
数组是一种引用类型,可以一次性存储多个值,是一块连续的物理空间,且必须有相同的数据类型,且长度固定;
数组通过下表进行访问,数组是引用类型,在堆开辟空间;
数组在堆区分配——eg:图书馆的书架;
一维数组:
char[] x = {'A', 'B', 'C', 'D', 'E'};
int[] x1 = {1, 2, 3, 4, 5};
char[] x2 = new char[10]; //定义个字符数组x2长度为10
System.out.println(x2.length);
out : 10
x2[0] = 'A';
x2[1] = 'B';
System.out.println(x2[0]);
out : A
System.out.println(x2.length-1);
out : 9
char[] x3 = new char[]{'A', 'B', 'C'};
System.out.println(x3);
out:ABC
char[] x = new char[]{'A', 'B', 'C'};
for (int i = 0;i < x.length;i++){
System.out.println(x[i]);
}
out:A
B
C
int i1 = 0;
while(i1 < x.length){
System.out.println(x[i1]);
i1++;
}
out:A
B
C
多维数组:
int[][] a = new int[3][3];
Scanner input = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
a[i][j] = input.nextInt();
}
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.printf("%d", a[i][j]);
}
System.out.printf("\n");
}
out:1 2 3
4 5 6
7 8 9
System.out.println(a.length);
out:3
java垃圾回算法:
-
标记-清除算法:这是最简单的垃圾回收算法,它通过标记不再使用的对象,然后清除它们占用的内存。该算法存在内存碎片问题,因为被清除的对象所占用的空间不能被重用,从而导致内存浪费。
-
复制算法:这种算法将可用内存划分为两个区域,一次只使用其中一个。当一个区域用完时,垃圾回收器会将所有存活的对象从该区域复制到另一个区域中,然后清除原始区域中不再使用的对象。该算法可以解决内存碎片问题,但需要更多的内存用于复制存活对象。
-
标记-整理算法:这种算法与标记-清除算法类似,但在标记不再使用的对象后,它会将所有存活对象移到一端,然后清除剩余空间。该算法可以避免内存碎片问题,但需要更多的时间进行整理。
-
分代算法:该算法将内存分为几个代,每个代使用不同的垃圾回收算法。新创建的对象被放置在第一代中,一段时间后,如果它们仍然存活,则将它们移动到第二代中。如果它们在第二代中存活一段时间,它们将被移动到第三代中。在每个代中,不同的算法被使用,以优化垃圾回收效率。
5.增量式垃圾回收算法:该算法将垃圾回收过程分解成若干小步骤,在每个步骤中只处理一小部分对象,同时允许程 序继续运行。该算法可以减少暂停时间,但需要更多的垃圾回收器代码。
运算符号优先级:
二 、循环和选择
给10位同学的成绩进行分级(0~60为不及格,60~80为及格,80~100为优秀)
package test;
public class chengji {
public static void main(String[] args) {
double[] a ={100, 90.5, 80, 70, 60, 50, 40, 30, 20, 10};
String[] str ={"小王", "小丽", "小王", "小花", "小刘", "小图", "小明", "小敏", "小陈", "小虎"};
for (int i=0;i<10;i++){
if(a[i]>= 0 && a[i] < 60){
System.out.println(str[i] + a[i]+" ~不及格");
}
else if (a[i] >= 60 && a[i] < 80){
System.out.println(str[i] + a[i] + " ~及格");
}
else if (a[i] >= 80 && a[i]<= 100){
System.out.println(str[i] + a[i] + " ~优秀");
}
}
}
}
char [] a = {'A', 'B', 'C'};
for (int i=0;i<a.length;i++){
System.out.println((int) a[i]);
out:65 66 67
System.out.println((float) a[i]);
out:65.0 66.0 67.0
System.out.println((double) a[i]);
out:65.0 66.0 67.0
}
求3*3的二维数组中的最大最小值:
package test;
import java.util.Scanner;
public class test {
public static void main(String[] args) {
double[][] a = new double[3][3];
Scanner input = new Scanner(System.in);
System.out.println("请输入一个3*3的数组:" );
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
a[i][j] = input.nextDouble();
}
}
//求数组a中的最大值
double max = a[0][0];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (max < a[i][j]){
max = a[i][j];
}
}
}
//求数组a中的最小值
double min = a[0][0];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (min > a[i][j]){
min = a[i][j];
}
}
}
System.out.println("最大值为: " + max);
System.out.println("最小值为: " + min);
}
}
三、 课后作业:
1.编写一个控制台版本的九九乘法表;
package test;
public class jiujiu{
public static void main(String[] args) {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j + " × " + i + " = " + (i * j) + "\t");
}
System.out.println();
}
}
}
2.编写函数实现求最大值、最小值和平均值;
package test.maxminjun;
public class MathUtils {
// 求最大值
public static int getMax(int[] arr) {
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
// 求最小值
public static int getMin(int[] arr) {
int min = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
}
}
return min;
}
//求平均值
public static int getjun(int[] arr){
int sum = 0;
for (int i = 1; i < arr.length; i++) {
sum += arr[i];
}
int a = sum/arr.length;
return a;
}
}
package test.maxminjun;
import test.maxminjun.MathUtils;
public class maxandmin {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 5, 7, 8, 10, 15};
int max = MathUtils.getMax(arr);
int min = MathUtils.getMin(arr);
int jun = MathUtils.getjun(arr);
System.out.println("Max: " + max);
System.out.println("Min: " + min);
System.out.println("jun: " + jun);
}
}
3.编圆类,实现求面积、体积和周长;
package test;
import javax.sql.rowset.serial.SQLOutputImpl;
import java.util.Scanner;
public class yuan {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.printf("请输入圆的半径(cm): ");
float r = input.nextInt();
float pi = 3.14f;
//求周长
float c =2 * pi * r;
System.out.println("周长= " + c + "厘米");
//求面积
float s = pi * r *r;
System.out.println("面积= " + s + "平方厘米");
//求体积
float v = 3/4f*pi*r*r*r;
System.out.println("体积= " + v + "立方厘米");
}
}
4.编写冒泡排序法,编写快排序法:
package test;
public class maopao {
public static void main(String[] args) {
int[] arr = {5, 3, 8, 6, 4};
bubbleSort(arr);
for (int i : arr) {
System.out.print(i + " ");
}
}
public static void bubbleSort(int[] arr) {
int len = arr.length;
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
}
package test.maxminjun;
public class kuaipai {
public static void main(String[] args) {
int[] arr = {5, 3, 8, 6, 4};
quickSort(arr, 0, arr.length - 1);
for (int i : arr) {
System.out.print(i + " ");
}
}
public static void quickSort(int[] arr, int left, int right) {
if (left >= right) {
return;
}
int pivot = partition(arr, left, right);
quickSort(arr, left, pivot - 1);
quickSort(arr, pivot + 1, right);
}
public static int partition(int[] arr, int left, int right) {
int pivot = arr[left];
while (left < right) {
while (left < right && arr[right] >= pivot) {
right--;
}
arr[left] = arr[right];
while (left < right && arr[left] <= pivot) {
left++;
}
arr[right] = arr[left];
}
arr[left] = pivot;
return left;
}
}
5.编写一个贪吃蛇游戏(swing界面),俄罗斯方块,坦克大战;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.LinkedList;
public class SnakeGame {
private static final int WIDTH = 600; // 游戏窗口的宽度
private static final int HEIGHT = 600; // 游戏窗口的高度
private static final int SIZE = 30; // 蛇身体每个部分的大小
private JFrame frame;
private SnakePanel snakePanel;
private Timer timer;
private LinkedList<Point> snakeBody;
private Direction direction;
private Point food;
private int score;
private boolean isHardMode;
public SnakeGame() {
frame = new JFrame("贪吃蛇游戏");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(WIDTH, HEIGHT);
frame.setLocationRelativeTo(null); // 将窗口居中显示
snakePanel = new SnakePanel();
frame.add(snakePanel);
frame.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_UP && direction != Direction.DOWN) {
direction = Direction.UP;
} else if (keyCode == KeyEvent.VK_DOWN && direction != Direction.UP) {
direction = Direction.DOWN;
} else if (keyCode == KeyEvent.VK_LEFT && direction != Direction.RIGHT) {
direction = Direction.LEFT;
} else if (keyCode == KeyEvent.VK_RIGHT && direction != Direction.LEFT) {
direction = Direction.RIGHT;
}
}
});
frame.setFocusable(true);
frame.setVisible(true);
timer = new Timer(isHardMode ? 120 : 160, new GameLoop());
timer.setInitialDelay(0);
snakeBody = new LinkedList<>();
snakeBody.add(new Point(WIDTH / 2, HEIGHT / 2));
direction = Direction.RIGHT;
generateFood();
score = 0;
isHardMode = false;
timer.start();
}
private class GameLoop implements ActionListener {
private int delay = isHardMode ? 120 : 160;
private int stepCount = 0;
@Override
public void actionPerformed(ActionEvent e) {
moveSnake();
checkCollision();
snakePanel.repaint();
stepCount++;
if (stepCount >= 10) {
delay -= isHardMode ? 2 : 4;
timer.setDelay(delay);
stepCount = 0;
}
}
}
private class SnakePanel extends JPanel {
private Image backgroundImage;
public SnakePanel() {
backgroundImage = new ImageIcon("background.jpg").getImage();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(backgroundImage, 0, 0, getWidth(), getHeight(), this);
Graphics2D g2d = (Graphics2D) g;
for (int i = 0; i < snakeBody.size(); i++) {
Point bodyPart = snakeBody.get(i);
int x = bodyPart.x;
int y = bodyPart.y;
// 根据索引计算蛇身颜色的渐变
float hue = (float) i / snakeBody.size();
Color bodyColor = Color.getHSBColor(hue, 0.8f, 0.8f);
// 绘制蛇身
g2d.setColor(bodyColor);
g2d.fillRect(x, y, SIZE, SIZE);
// 绘制蛇身边框
g2d.setColor(Color.BLACK);
g2d.drawRect(x, y, SIZE, SIZE);
}
// 绘制食物
g2d.setColor(Color.RED);
g2d.fillRect(food.x, food.y, SIZE, SIZE);
// 绘制得分
g2d.setColor(Color.WHITE);
g2d.setFont(new Font("Arial", Font.BOLD, 20));
g2d.drawString("Score: " + score, 10, 30);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(WIDTH, HEIGHT);
}
}
private void moveSnake() {
Point head = new Point(snakeBody.getFirst()); // 复制蛇头的位置
// 根据当前方向移动蛇头
if (direction == Direction.UP) {
head.y -= SIZE;
} else if (direction == Direction.DOWN) {
head.y += SIZE;
} else if (direction == Direction.LEFT) {
head.x -= SIZE;
} else if (direction == Direction.RIGHT) {
head.x += SIZE;
}
// 将新的蛇头插入到列表的开头
snakeBody.addFirst(head);
// 如果蛇头与食物位置重叠,则吃掉食物并生成新的食物
if (head.equals(food)) {
generateFood();
score++;
} else {
// 移除蛇尾
snakeBody.removeLast();
}
// 如果蛇头与身体的其他部分重叠,则游戏结束
if (head.x < 0 || head.x >= WIDTH || head.y < 0 || head.y >= HEIGHT) {
timer.stop();
JOptionPane.showMessageDialog(frame, "游戏结束,得分:" + score);
}
// 如果蛇头与身体的其他部分重叠,则游戏结束
for (int i = 1; i < snakeBody.size(); i++) {
if (head.equals(snakeBody.get(i))) {
timer.stop();
JOptionPane.showMessageDialog(frame, "游戏结束,得分:" + score);
break;
}
}
}
private void generateFood() {
int x, y;
do {
x = (int) (Math.random() * (WIDTH / SIZE)) * SIZE;
y = (int) (Math.random() * (HEIGHT / SIZE)) * SIZE;
} while (isSnakeOverlap(x, y));
food = new Point(x, y);
}
private boolean isSnakeOverlap(int x, int y) {
for (Point bodyPart : snakeBody) {
if (bodyPart.x == x && bodyPart.y == y) {
return true;
}
}
return false;
}
private void checkCollision() {
// 如果蛇头与食物位置重叠,则吃掉食物并生成新的食物
if (snakeBody.getFirst().equals(food)) {
generateFood();
score++;
}
}
private enum Direction {
UP, DOWN, LEFT, RIGHT
}
public static void main(String[] args) {
SwingUtilities.invokeLater(SnakeGame::new);
}
}
6.编写一个聊天室:
7.实现加减乘除:
package test;
import java.util.Scanner;
public class test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入第一个数:");
double num1 = input.nextDouble();
System.out.print("请输入第二个数:");
double num2 = input.nextDouble();
System.out.println(num1 + " + " + num2 + " = " + add(num1, num2));
System.out.println(num1 + " - " + num2 + " = " + subtract(num1, num2));
System.out.println(num1 + " * " + num2 + " = " + multiply(num1, num2));
System.out.println(num1 + " / " + num2 + " = " + divide(num1, num2));
}
public static double add(double num1, double num2) {
return num1 + num2;
}
public static double subtract(double num1, double num2) {
return num1 - num2;
}
public static double multiply(double num1, double num2) {
return num1 * num2;
}
public static double divide(double num1, double num2) {
if (num2 == 0) {
throw new ArithmeticException("除数不能为零");
}
return num1 / num2;
}
}
package test;
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入第一个数:");
double num1 = input.nextDouble();
System.out.print("请输入第二个数:");
double num2 = input.nextDouble();
System.out.print("请输入运算符(+、-、*、/):");
char operator = input.next().charAt(0);
double result = calculate(num1, num2, operator);
System.out.println(num1 + " " + operator + " " + num2 + " = " + result);
}
public static double calculate(double num1, double num2, char operator) {
double result;
switch (operator) {
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
if (num2 == 0) {
throw new ArithmeticException("除数不能为零");
}
result = num1 / num2;
break;
default:
throw new IllegalArgumentException("不支持的运算符:" + operator);
}
return result;
}
}
Day 05
一、 函数的定义:
函数定义的位置:在一个类的内部,其他函数的外部,与其他函数并列,不能进行嵌套;
public static 数据类型/void 函数名称(返回值A,返回值B){
xxx
return 返回值;
}
函数的调用:
函数名称();
返回值 = 函数名称(实际参数);
double x = doadd(100,20);
重载:在一个类内部,多个函数的名称相同,但参数列表不同的称为重载;
public static double add(double a,double b){
return a+b;
}
public static double add(int a,int b){
return a+b;
}
Day 06~09
一、 类和对象
1、 对象:
1.什么是面向对象(java)? 面向对象(Object Oriented)是软件开发方法,一种编程范式。它以客观世界中的对象为中心,其分析和设计思想符合人们的思维方式,分析和设计结果与客观世界的实际比较解决。
2.什么是面向过程(c)?
面向过程——》面向对象——》面向函数式
2、类:
类的定义:具有相同属性和行为的对象称为类;
3、 类和对象的关系:
类是对象的抽象,对象是类的实例 简历模板 张三的简历
//英雄类
class Here{
double hp = 500; //血量
double level = 100; //等级;
String name; //名字
//移动
public void move(){
xxx
}
//攻击
public void kell(String name){
System.out.println("我是" + this.name + "我要终结你!");
//当局部变量与全局变量冲突时,使用this.变量可调用全局变量
}
}
成员变量(全局变量):在同一个类中,在函数外面的变量,类中每一个函数都能够使用;
局部变量:在函数内定义的变量,之内在函数内使用;
实例化:把抽象的变成实际的(用new开辟一个空间);
4、类和类之间的关系:
1. 泛化(Generalization)继承
【泛化关系】:是一种继承关系, 表示一般与特殊的关系, 它指定了子类如何特化父类的所有特征和行为. 例如:老虎是动物的一种, 即有老虎的特性也有动物的共性。
public class Animal{
}
public class Tiger extends Animal{
//继承Animal类
}
2. 实现(Realization)
【实现关系】:是一种类与接口的关系, 表示类是接口所有特征和行为的实现.
public interface IBrush {
// 声明一个接口(注意:接口不是类)
}
public class PenBrush implements IBrush {
// 实现接口IBrush
}
3. 关联(Association)
【关联关系】:是一种拥有的关系, 它使一个类知道另一个类的属性和方法;如:老师与学生,丈夫与妻子关联可以是双向的,也可以是单向的。双向的关联可以有两个箭头或者没有箭头,单向的关联有一个箭头。
【代码体现】:成员变量。
public class Teacher{
//老师不会只有一个学生,得有多个。
private Lsit<Student> student;
}
public class Student{
//学生不会只有一个老师,得有多个。
private Lsit<Teacher> teacher;
//学生不会只有一门课程,得有多个。
private Lsit<Course> course;
}
public class Course{
}
4.聚合(Aggregation)
【聚合关系】:是整体与部分的关系, 且部分可以离开整体而单独存在. 如车和轮胎是整体和部分的关系, 轮胎离开车仍然可以存在. 聚合关系是关联关系的一种,是强的关联关系;关联和聚合在语法上无法区分,必须考察具体的逻辑关系。
【代码体现】:成员变量。
/**
* 汽车类
*/
public class Car{
//引擎
private Engine engine;
//轮胎
private Tire tire;
}
/**
* 引擎类
*/
public class Engine{
}
/**
* 轮胎类
*/
public class Tire{
}
5.组合(Composition)
【组合关系】:是整体与部分的关系, 但部分不能离开整体而单独存在. 如公司和部门是整体和部分的关系, 没有公司就不存在部门.组合关系是关联关系的一种,是比聚合关系还要强的关系,它要求普通的聚合关系中代表整体的对象负责代表部分的对象的生命周期
【代码体现】:成员变量。
//公司类
public class Company{
//
private Department department;
}
//部门类
public class Department{
}
6. 依赖(Dependency)
【依赖关系】:是一种使用的关系, 即一个类的实现需要另一个类的协助, 所以要尽量不使用双向的互相依赖.
【代码表现】:局部变量、方法的参数或者对静态方法的调用。
//代理人
puvlic class Agent{
//成员变量
private Computer computer;
//方法的参数
public void use(Computer computer){
}
//有返回的方法
public Computer getComputer(){
return new Computer();
}
//静态方法
public static void useComputer(Computer computer){
}
}
//计算机
puvlic class Computer {
}
5、 构造方法:
1.定义:在一个类中,跟类名相同,但没有返回值的函数称为构造函数,也叫构造方法。(调用时使用new开辟一个空间)
public class test {
public static void main(String[] args) {
Here a = new Here();
}
}
class Here{
public Here(){
System.out.println("我是lx他爹");
}
}
out:我是lx他爹
2.构造函数有什么用:构造函数在实例化new的时候自动调用,且只调用一次,可以在构造函数中,对成员变量进行初始化;
儿子一定会调用父亲无参的构造函数(如果父亲没有有参的调用不了);
public class test {
public static void main(String[] args) {
Bird b = new Bird("麻雀",200);
System.out.println(b.name + " " + b.price + "元");
}
}
class Animal{
String name;
double price;
public Animal(){
System.out.println("走过路过,过来瞧,过来看:");
}
}
class Bird extends Animal{
//有参数的构造函数
public Bird(String name,double price){
this.name = name;
this.price = price;
}
}
out:走过路过,过来瞧,过来看:
麻雀 200.0元
6、 练习(类和类之间的关系):
在 LoL 游戏中,英雄可以去武器商店购买武器,一个英雄可以携带左右两把武器,英雄可以通过武器物理攻击怪物,也可以通过魔法技能攻击怪物,一个英雄通常有四种技能,当键盘输入 Q 、 W 、 E 、 R 的时候分别释放四种技能,否则就是物理攻击(左右两把武器各攻击一下)。请根据 OOP 思想,编写和设计相关类和方法。
package test.test;
public class test {
public static void main(String[] args) {
Hero hero = new Hero("亚索");
hero.buyWeapon(new Weapon("无尽之刃", 700));
hero.buyWeapon(new Weapon("饮血剑", 600));
hero.buyWeapon(new Weapon("多兰剑", 60));
hero.setCurrentWeapon(hero.getLeftHand()); // 设置当前武器为左手武器
hero.physicalAttack(); // 物理攻击,使用左手武器
hero.useSkill('Q');
hero.useSkill('E');
hero.useSkill('T'); // 输入错误的技能键,进行物理攻击
}
}
// 武器类
class Weapon {
private String name;
private int damage;
public Weapon(String name, int damage) {
this.name = name;
this.damage = damage;
}
public String getName() {
return name;
}
public int getDamage() {
return damage;
}
}
// 英雄类
class Hero {
private String name;
private Weapon leftHand;
private Weapon rightHand;
private Weapon currentWeapon;
public Hero(String name) {
this.name = name;
}
// 购买武器
public void buyWeapon(Weapon weapon) {
if (leftHand == null) {
leftHand = weapon;
} else if (rightHand == null) {
rightHand = weapon;
} else {
System.out.println("英雄已经携带了两把武器,无法购买更多的武器。");
}
}
// 物理攻击
public void physicalAttack() {
if (leftHand != null && rightHand != null) {
System.out.println("英雄使用 " + leftHand.getName() + " 和 " + rightHand.getName() + " 进行物理攻击,造成 " + (leftHand.getDamage() + rightHand.getDamage()) + " 点伤害。");
} else if (leftHand != null && rightHand == null) {
System.out.println("英雄使用 " + leftHand.getName() + " 进行物理攻击,造成 " + leftHand.getDamage() + " 点伤害。");
}else if (leftHand == null && rightHand != null) {
System.out.println("英雄使用 " + rightHand.getName() + " 进行物理攻击,造成 " + rightHand.getDamage() + " 点伤害。");
}else {
System.out.println("英雄没有武器,无法进行攻击。");
}
}
// 使用技能
public void useSkill(char key) {
switch (key) {
case 'Q':
System.out.println("英雄释放 Q 技能。");
break;
case 'W':
System.out.println("英雄释放 W 技能。");
break;
case 'E':
System.out.println("英雄释放 E 技能。");
break;
case 'R':
System.out.println("英雄释放 R 技能。");
break;
default:
System.out.println("技能错误,进行物理攻击");
physicalAttack();
}
}
public Weapon getLeftHand() {
return leftHand;
}
public Weapon getRightHand() {
return rightHand;
}
public Weapon getCurrentWeapon() {
return currentWeapon;
}
public void setCurrentWeapon(Weapon currentWeapon) {
this.currentWeapon = currentWeapon;
}
}
out:
英雄已经携带了两把武器,无法购买更多的武器。
英雄使用 无尽之刃 和 饮血剑 进行物理攻击,造成 1300 点伤害。
英雄释放 Q 技能。
英雄释放 E 技能。
技能错误,进行物理攻击
英雄使用 无尽之刃 和 饮血剑 进行物理攻击,造成 1300 点伤害。
7、 面向对象的特征
1. 封装:封装是面向对象编程的核心思想,简单点说就是,我把某些东西封装起来,这些关键的核心的东西不能给你看,但是我可以提供给你一些简单使用的方法。(保护属性,隐藏实现的细节,对外提供可以公开的方法的过程)
封装其实是对外隐藏复杂细节,提供简单易用的接口,便于外界调用,从而提高系统的可扩展性、可维护性。在Java中这种隐藏或公开是通过权限修饰符来实现的。
-
通过封装,我们可以保护代码被破坏,提高数据安全性。
使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑限制对属性的不合理操作。
-
通过封装,我们提高了代码的复用性(有些方法、类在很多地方都能多次反复使用)
-
通过封装,带来的高内聚和低耦合,使用不同对象、不同模块之间能更好的协同,同时便于修改,增强代码的可维护性
-
高内聚 :类的内部数据操作细节自己完成,不允许外部干涉;
-
低耦合 :仅对外暴露少量的方法用于使用
public class Student {
//姓名
private String name;
//年龄
private int age;
//get方法获取年龄
public int getAge() {
return age;
}
//set方法修改年龄
public void setAge(int age) {
if(age<0 ||age>100){
return;
}
this.age = age;
}
//get方法获取姓名
public String getName() {
return name;
}
//set方法修改年龄
public void setName(String name) {
this.name = name;
}
}
2. 继承:类和类之间有些也会具有一定的关系。比方说四边形,可以分为正方形、长方形、菱形,他们不但继承了四边形的特征,也具有属于自己的特征,这就是一种继承的关系。
继承原有的功能,增加自己新的功能,实现了拓展和复用。
java规定类只能继承一个类,但是一个类可以被多个类继承(一个子类只能有一个直接父类,一个父类可以有多个子类),类之间可以有多层的继承关系,直接继承的是直接父类,父类的父类就是间接父类,而最上层就是Object。
使用继承时,需要注意继承是受权限修饰符影响的。
-
子类无法继承 private 修饰的属性和方法
-
子类和父类在同一包下,可以继承 default 权限的属性方法
-
子类可以对父类进行扩展,拥有自己的属性和方法
-
子类可以重写父类的方法(前提是可以继承到这个方法)(多态的体现)
3. 多态:多态指同一个实体同时具有多种形式。同字面意思,即一个对象在不同的情况下会有不同的体现。(主要体现在对象和方法上,在子父类中不要定义同名的属性)
public class Test {
public static void main(String[] args) {
Random random = new Random();
int choose = random.nextInt(3);
System.out.println(choose);
//编译期间是不会知道实例化那个对象的,需要在运行期间确定
Animal animal = switch (choose) {
case 1 -> new Animal();
case 2 -> new Dog();
default -> new Cat();
};
//而且传递的是哪个对象就调用那个对象的say方法
animal.say();
}
}
class Animal{
public void say(){
System.out.println("动物的叫声");
}
}
class Dog extends Animal{
@Override
public void say() {
System.out.println("汪汪汪!!!");
}
}
class Cat extends Animal{
@Override
public void say() {
System.out.println("喵喵喵!!!");
}
}
Day 10~11
一、接口:
接口定义用interface,使用用implems 接口内所有方法都是抽象的 接口中的所有属性都是静态的 接口可以继承接口 java不允许多继承,但允许多接口;
interface Pay{
public void paying();
}
class WebQQ implements Pay{
public void paying;
}
interface A{
}
interface B{
}
interface C extends A,B{
}
interface Fly{
void flying();
//默认方法
default void running(){
}
void eating();
}
class Bird implements Fly{
@Override
public void flying() {
}
@Override
public void eating() {
}
}
二、面向对象的设计原则:
1. 单一职责原则(SRP):
每个类应该只负责一项职责,这样可以使类具有高内聚。同时,每个类应该尽可能少地依赖于其他类,这样可以使类之间的耦合度降低。
class Car:
def __init__(self, name, color):
self.name = name
self.color = color
def get_name(self):
return self.name
def get_color(self):
return self.color
class CarSerializer:
def serialize(self, car):
serialized_car = {
'name': car.get_name(),
'color': car.get_color()
}
return serialized_car
在上面的代码中,Car 类只负责表示汽车的名称和颜色,而 CarSerializer 类只负责将 Car 对象序列化为字典。这样,每个类都只有一个职责,使得代码更加可维护和可重用。
2. 开放封闭原则(OCP):
class Car:
def __init__(self, name, color):
self.name = name
self.color = color
def get_name(self):
return self.name
def get_color(self):
return self.color
class CarSerializer:
def serialize(self, car):
serialized_car = {
'name': car.get_name(),
'color': car.get_color()
}
return serialized_car
class CarXMLSerializer(CarSerializer):
def serialize(self, car):
serialized_car = super().serialize(car)
xml = f'<car><name>{serialized_car["name"]}</name><color>{serialized_car["color"]}</color></car>'
return xml
在上面的代码中,CarSerializer 类是一个抽象类,它定义了 serialize 方法,用于将 Car 对象序列化为字典。CarXMLSerializer 类继承自 CarSerializer 类,并重写了 serialize 方法,用于将 Car 对象序列化为 XML。这样,当需要添加新的序列化格式时,只需要创建一个新的子类,而不需要修改现有代码。
3. 里氏替换原则(LSP):
class Car:
def __init__(self, name, color):
self.name = name
self.color = color
def get_name(self):
return self.name
def get_color(self):
return self.color
class ElectricCar(Car):
def __init__(self, name, color, battery_life):
super().__init__(name, color)
self.battery_life = battery_life
def get_battery_life(self):
return self.battery_life
def print_car_info(car):
print(f'Name: {car.get_name()}')
print(f'Color: {car.get_color()}')
car = Car('Toyota', 'Red')
electric_car = ElectricCar('Tesla', 'Black', 100)
print_car_info(car)
print_car_info(electric_car)
在上面的代码中,ElectricCar 类继承自 Car 类,并添加了一个新的属性 batterylife 和一个新的方法 getbatterylife。然而,ElectricCar 类的实例可以替换 Car 类的实例,并且可以在 printcar_info 函数中正常工作,因为它遵循了 Car 类的约束和行为。
4. 接口隔离原则(ISP):
将接口分离成更小的和更具体的接口,以便客户端只需要实现它们需要的接口,这样可以使类之间的耦合度降低。
class Car:
def __init__(self, name, color):
self.name = name
self.color = color
def get_name(self):
return self.name
class CarColor:
def get_color(self):
pass
class RedCar(Car, CarColor):
def __init__(self, name):
super().__init__(name, 'Red')
def get_color(self):
return 'Red'
class BlueCar(Car, CarColor):
def __init__(self, name):
super().__init__(name, 'Blue')
def get_color(self):
return 'Blue'
def print_car_info(car):
print(f'Name: {car.get_name()}')
if isinstance(car, CarColor):
print(f'Color: {car.get_color()}')
red_car = RedCar('Toyota')
blue_car = BlueCar('Ford')
print_car_info(red_car)
print_car_info(blue_car)
在上面的代码中,CarColor 类定义了一个 getcolor 方法,用于获取汽车的颜色。RedCar 类和 BlueCar 类都继承自 Car 类和 CarColor 类,并实现了 getcolor 方法。printcarinfo 函数检查传入的对象是否是 CarColor 类型的实例,如果是,则打印汽车的颜色。这样,客户端只需要实现它们需要的接口,而不需要依赖于它们不需要的接口。
5. 依赖倒置原则(DIP):
高层模块不应该依赖于低层模块,它们应该依赖于抽象。这样可以使类之间的耦合度降低。
class Car:
def __init__(self, name, color):
self.name = name
self.color = color
def get_name(self):
return self.name
class CarSerializer:
def __init__(self, car):
self.car = car
def serialize(self):
serialized_car = {
'name': self.car.get_name(),
'color': self.car.color
}
return serialized_car
car = Car('Toyota', 'Red')
serializer = CarSerializer(car)
serialized_car = serializer.serialize()
print(serialized_car)
在上面的代码中,CarSerializer 类依赖于 Car 类,但是它依赖于 Car 类的抽象而不是具体的实现。CarSerializer 类的构造函数接受一个 Car 对象,并将其存储在实例变量中。serialize 方法使用存储的 Car 对象来生成序列化的字典。这样,CarSerializer 类不依赖于具体的 Car 类实现,而是依赖于 Car 类的抽象。
最准目标:高内聚,低耦合:
高内聚和低耦合是软件设计中的两个重要概念,它们有助于编写可维护、可扩展和可重用的代码。 高内聚指的是一个模块或类的内部元素之间的联系紧密程度。具有高内聚的模块或类通常具有单一的职责,并且其内部元素之间的联系紧密,这使得模块或类更加可维护和可重用。例如,一个负责处理订单的类应该只包含与订单相关的方法和属性,而不应该包含与其他功能无关的方法和属性。 低耦合指的是模块或类之间的联系松散程度。具有低耦合的模块或类之间的依赖关系较少,这使得模块或类更加灵活和可扩展。例如,一个负责处理订单的类应该只依赖于与订单相关的类,而不应该依赖于与其他功能无关的类。
Day 12~13
1、静态(Static)
使用方法:
//1.在内部类中使用
class A{
static class B{
}
}
//2.在成员变量中使用
class A{
static double pi=3.14; //静态成员变量(类变量)---在内存中具有唯一性
}
//3.静态块
class A{
static {
}
}
//4.修饰函数
class A{
static void B() //静态函数
}
静态在使用时不需要去new
public class test4 {
public static void main(String[] args) {
System.out.println(A.pi);
}
}
//在成员变量中使用
class A{
static double pi=3.14; //静态成员变量(类变量)---在内存中具有唯一性
}
out:3.14
静态块在类加载时首先会自动运行(只运行一次);
public class test4 {
static {
System.out.println("hello");
}
public static void main(String[] args) {
}
}
out:hello
练习1:
编写一个圆类,实现能够计算周长和面积,要求半径当作参数传入;
package test.test.yuan1;
public class Circle {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
public double getPerimeter() {
return 2 * Math.PI * radius;
}
public double getArea() {
return Math.PI * radius * radius;
}
}
package test.test.yuan1;
public class Main {
public static void main(String[] args) {
Circle Circle = new Circle(5);
System.out.println("半径:" + Circle.getRadius());
System.out.println("周长:" + Circle.getPerimeter());
System.out.println("面积:" + Circle.getArea());
}
}
out:
半径:5.0
周长:31.41592653589793
面积:78.53981633974483
2、内部类
class out{
int i = 0;
//1.嵌套内部类
class a{
}
//2.静态成员内部类
static class b{
}
public void print(){
//3.局部内部类
class C{
}
}
Fly fly = new Bird();
//4.匿名内部类
Fly fly1 = new Fly() {
@Override
public void Flying() {
System.out.println(i);
}
}
}
interface Fly{
void Flying();
}
class Bird implements Fly{
@Override
public void Flying() {
}
}
内部类可以直接使用外部类的成员变量;
class Mother{
int i = 0;
//嵌套内部类
class Son{
public void print(){
System.out.println(i);
}
}
}
3、字符串
作业:
1.给定一个网址,求协议,求域名,求项目名,求资源名https://localhost:8080/project/idex.html
https://localhost:8080/project/idex.html https://localhost:8080/project/login.html
package test.test;
import java.net.URI;
import java.net.URISyntaxException;
public class test2 {
public static void main(String[] args) {
String[] urls = {
"https://localhost:8080/project/index.html",
"https://localhost:8080/project/login.html",
"https://www.example.com/path/to/resource.html"
};
for (String url : urls) {
String xieyi = StringUrl.getxieyi(url);
String duankou = StringUrl.getduankou(url);
String ip = StringUrl.getip(url);
String project = StringUrl.getproject(url);
String ziyuan = StringUrl.getziyuan(url);
System.out.println("URL: " + url);
System.out.println("协议: " + xieyi);
System.out.println("端口号: " + duankou);
System.out.println("IP地址: " + ip);
System.out.println("项目名: " + project);
System.out.println("资源名: " + ziyuan);
System.out.println();
}
}
}
class StringUrl {
public static String getxieyi(String urls) {
return urls.substring(0, urls.indexOf(':'));
}
public static String getduankou(String urls) {
try {
URI uri = new URI(urls);
int port = uri.getPort();
return port == -1 ? "" : String.valueOf(port);
} catch (URISyntaxException e) {
return "";
}
}
public static String getip(String urls) {
try {
URI uri = new URI(urls);
String host = uri.getHost();
return host == null ? "" : host;
} catch (URISyntaxException e) {
return "";
}
}
public static String getproject(String urls) {
try {
URI uri = new URI(urls);
String path = uri.getPath();
if (path == null || path.isEmpty() || path.equals("/")) {
return "";
}
String[] segments = path.split("/");
return segments.length > 1 ? segments[1] : "";
} catch (URISyntaxException e) {
return "";
}
}
public static String getziyuan(String urls) {
try {
URI uri = new URI(urls);
String path = uri.getPath();
if (path == null || path.isEmpty() || path.equals("/")) {
return "";
}
String[] segments = path.split("/");
return segments.length > 1 ? segments[segments.length - 1] : "";
} catch (URISyntaxException e) {
return "";
}
}
}
out:
URL: https://localhost:8080/project/index.html
协议: https
端口号: 8080
IP地址: localhost
项目名: project
资源名: index.html
URL: https://localhost:8080/project/login.html
协议: https
端口号: 8080
IP地址: localhost
项目名: project
资源名: login.html
URL: https://www.example.com/path/to/resource.html
协议: https
端口号:
IP地址: www.example.com
项目名: path
资源名: resource.html
2.给定一个字符串,包含了属性和值,请解析存储到数组中
name=张三,age=25,email=songzt@lanqiao.org,address=“内蒙古” name=李四,age=30,email=zhangsan@lanqiao.org,address=“北京”
package test.test;
import java.util.Arrays;
public class test3 {
public static void main(String[] args) {
String input = "name=张三,age=25,email=songzt@lanqiao.org,address=“内蒙古”\n" +
"name=李四,age=30,email=zhangsan@lanqiao.org,address=“北京”";
String[] lines = input.split("\n");
Student[] students = new Student[lines.length];
for (int i = 0; i < lines.length; i++) {
String[] tokens = lines[i].split(",");
Student student = new Student();
for (int j = 0; j < tokens.length; j++) {
String[] keyValue = tokens[j].split("=");
String key = keyValue[0];
String value = keyValue[1].replaceAll("“|”", "");
if (key.equals("name")) {
student.setName(value);
} else if (key.equals("age")) {
student.setAge(value);
} else if (key.equals("email")) {
student.setEmail(value);
} else if (key.equals("address")) {
student.setAddress(value);
}
}
students[i] = student;
}
for (Student student : students) {
System.out.println(student);
}
}
}
class Student {
private String name;
private String age;
private String email;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
", email='" + email + '\'' +
", address='" + address + '\'' +
'}';
}
}
out:
Student{name='张三', age='25', email='songzt@lanqiao.org', address='内蒙古'}
Student{name='李四', age='30', email='zhangsan@lanqiao.org', address='北京'}
1.字符串的不可变性
在Java中,字符串是不可变的,这意味着一旦创建了一个字符串对象,就不能更改它的值。这是因为Java中的字符串是通过String类来表示的,而String类是final的,不能被继承或修改。
String str1 = "Hello";
String str2 = "World";
String str3 = str1 + str2;
System.out.println(str1); // 输出 "Hello"
System.out.println(str2); // 输出 "World"
System.out.println(str3); // 输出 "HelloWorld"
String str = "Hello";
str[0] = 'h'; // 编译错误:字符串是不可变的
这是因为字符串是不可变的,我们无法直接修改字符串对象的值。如果我们需要修改字符串,可以使用StringBuilder或StringBuffer类,例如:
StringBuilder sb = new StringBuilder("Hello");
sb.setCharAt(0, 'h');
String str = sb.toString(); // str的值为"hello"
在这个例子中,我们首先创建了一个可变的字符串对象StringBuilder,并将其初始化为"Hello"。然后,我们使用setCharAt方法修改了字符串的第一个字符,最后将StringBuilder对象转换为不可变的字符串对象,赋值给变量str。
2.可变字符串
在Java中,可变字符串是指可以修改其值的字符串对象。Java提供了两个类来表示可变字符串:StringBuilder和StringBuffer。
StringBuilder和StringBuffer类的用法非常类似,它们都提供了一些方法来修改字符串的值,例如添加、插入、删除、替换等操作。与不可变字符串不同的是,这些操作会直接修改原始的字符串对象,而不是创建新的字符串对象。
StringBuilder和StringBuffer的主要区别在于线程安全性。StringBuilder是非线程安全的,适用于单线程环境下的字符串操作;而StringBuffer是线程安全的,适用于多线程环境下的字符串操作。由于StringBuffer需要进行同步操作,因此在单线程环境下,StringBuilder的性能要优于StringBuffer。
以下是一个使用StringBuilder类的例子,展示了可变字符串的特点:
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
sb.insert(5, ",");
sb.deleteCharAt(0);
String str = sb.toString(); // str的值为"ello, World"
在这个例子中,我们首先创建了一个可变字符串对象StringBuilder,并将其初始化为"Hello"。然后,我们使用append方法在字符串末尾添加了一个空格和"World",使用insert方法在字符串的第五个字符位置插入了一个逗号,使用deleteCharAt方法删除了字符串的第一个字符。最后,我们将StringBuilder对象转换为不可变的字符串对象,赋值给变量str。注意,这些操作都是直接修改原始的字符串对象,而不是创建新的字符串对象。
面向对象程序作品:坦克大战游戏
原笔记链接:FlowUs 息流 - 新一代生产力工具