$\text{Java}$ 机测主观题 $\text{Collection}$

不会Java,不保证完全正确(叠甲)
—— By NagoriYuuuki

8-1 sdut-网络编程-1 TCP协议通信

分数 10

作者 周雪芹

单位 山东理工大学

1、TCP Socket编程实现服务器和客户端的交互:
(1)服务器端先运行,利用循环时刻为客户端提供服务;
(2)客户端与服务器接通后,从键盘上输入若干字符(若客户端发送“end”字符串,服务器终止程序),传到服务器,服务器在控制台显示所收到的数据,形式为:”I have received ”,并向客户端 反馈信息“Message from Server is:**”,此次通话结束;
(3)客户端接收来自服务器端的数据,在控制台显示:“Client has received .............“。

//服务器端 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.ServerSocket; 
import java.net.Socket; 
 
public class TCPServer { 
    public static void main(String[] args) throws IOException { 
        ServerSocket ss = new ServerSocket(8888); //服务器端口号使用8888,可根据情
况更换其他 
 
        //服务器端循环接受客户端连接,直以“end“结束 
        while (true) { 
            //服务器等待接受来自客户端的连接,若有连接,就建立通信线路 
            Socket socket = ss.accept(); // IP+端口号 
            //System.out.println(socket); 
            //获得此次连接的输入、输出流 
            InputStream is = socket.getInputStream(); 
            OutputStream os = socket.getOutputStream(); 
 
            // 2 服务器端读数据 
            int len = 0; 
            byte[] bytes = new byte[10]; 
            StringBuffer buffer = new StringBuffer(); 
            while ((len = is.read(bytes)) != -1) { 
                buffer.append(new String(bytes, 0, len)); 
            } 
 
            // 显示 
            System.out.println("I have received " + buffer.toString()); 
 
            // 3 向客户端写数据 
            os.write(("Message from Server is: "+buffer.toString()).getBytes
 ()); 
 
            //关闭输入、输出流            
            is.close(); 
            os.close(); 
             
            //关闭通信连接 
            socket.close(); 
             
            //若符合通信结束的条件,服务器不再继续循环等待客户端的通信连接 
            if("end".equals(buffer.toString())) 
            { 
                break; 
            } 
 
        } 
        //关闭服务器 
        ss.close(); 
    } 
} 
 
//客户端 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.InetAddress; 
import java.net.Socket; 
import java.net.UnknownHostException; 
import java.util.Scanner; 
 
public class TCPClient { 
    public static void main(String[] args) throws UnknownHostException, IOExce
 ption { 
        Scanner sc=new Scanner(System.in); 
        InetAddress ip=InetAddress.getByAddress(new byte[]{127,0,0,1}); 
        //本机的8888端口号提供服务器程序,客户端和服务器端建立通信连接 
        Socket socket=new Socket(ip,8888); 
        //System.out.println(socket); 
 
        //得到此次连接的输入、输出流 
        InputStream is = socket.getInputStream(); 
        OutputStream os = socket.getOutputStream(); 
 
        //1 客户端写数据 
        String line=sc.nextLine();  //读一行数据 
        os.write(line.getBytes());  //写到服务器端 
        socket.shutdownOutput();    //写出结束 
 
        //2 客户端接收数据,显示 
        int len=0; 
        byte[] bytes=new byte[10]; 
        StringBuffer buffer=new StringBuffer(); 
        while((len=is.read(bytes))!=-1){ 
            buffer.append(new String(bytes,0,len)); 
        } 
 
        //显示 
        System.out.println("Client has received:"+buffer.toString()); 
        //关闭输入、输出流 
        is.close(); 
        os.close(); 
            //关闭通信连接 
        socket.close(); 
    } 
}

8-2 sdut-网络编程-2 UDP协议通信

分数 10

作者 周雪芹

单位 山东理工大学

UDP Socket编程实现服务器和客户端的交互:
(1)服务器端先运行,利用循环时刻为客户端提供服务;
(2)客户端与服务器接通后,从键盘上输入若干字符(若客户端发送“end”字符串,服务器终止程序),传到服务器,服务器在控制台显示所收到的数据,形式为:”I have received ”,并向客户端 反馈信息“Message from Server is:**”,此次通话结束;
(3)客户端接收来自服务器端的数据,在控制台显示:“Client has received .............“。

//服务器端代码 
import java.io.IOException; 
import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.InetAddress; 
 
 
public class UDPServer { 
    public static void main(String[] args) throws IOException { 
        //创建一个服务器端的通信对象,使用本机的9999端口号 
        DatagramSocket ds = new DatagramSocket(9999); 
 
        //服务器端循环接受客户端信息,直以“end“结束 
        while (true) { 
            // 2 服务器端接收来自于客户端的数据 
            byte[] bytes = new byte[1024]; 
 
            //(1)准备接收数据的数据报对象 
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length); 
            //(2)接收数据进数据报对象 
            ds.receive(dp); 
            //(3)分析数据,并打印 
            byte[] dataIn = dp.getData(); 
            int length = dp.getLength(); 
            String strIn=new String(dataIn,0,length); 
            InetAddress ip = dp.getAddress(); 
            int port = dp.getPort(); 
            System.out.print("I have received "); 
            System.out.println(strIn); 
 
            // 3 服务器端向客户端写数据 
            //(1)准备写出去的数据 
            byte[] dataOut=("Message from Server is:"+strIn).getBytes(); 
            //(2)创建写出的数据报 
            DatagramPacket dp1 = new DatagramPacket(dataOut, dataOut.length, i
 p, port); 
            //(3)发送数据报 
            ds.send(dp1); 
 
            //若符合结不条件,服务器端跳出无限循环,即将停止服务 
            if ("end".equals(strIn)) { 
                break; 
            } 
        } 
 
        //停止UDP服务器 
        ds.close(); 
    } 
} 
  
//客户端代码 
import java.io.IOException; 
import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.InetAddress; 
import java.util.Scanner; 
 
public class UDPClient { 
    public static void main(String[] args) throws IOException { 
 
        Scanner sc=new Scanner(System.in); 
        //创建一个客户端端的通信对象 
        DatagramSocket ds=new DatagramSocket(); 
 
        //1 客户端向服务器端写数据 
        String line=sc.nextLine(); 
        //(1)创建客户端发送的数据报 
        DatagramPacket  dp=new DatagramPacket( 
                line.getBytes(), 
                line.getBytes().length, 
                InetAddress.getByAddress(new byte[]{127,0,0,1}), 
                9999); 
        //(2)发送数据报 
        ds.send(dp); 
 
        //4 客户端接收服务器端发送来数据 
        byte[] bytes=new byte[1024]; 
        //(1)准备接收的数据报对象 
        DatagramPacket dp1=new DatagramPacket(bytes, bytes.length); 
        //(2)接收服务器端的数据报 
        ds.receive(dp1); 
        //(3)分析数据并输出 
        byte[] data=dp1.getData(); 
        int length = dp1.getLength(); 
        System.out.print("Client has received:"); 
        System.out.println(new String(data,0,length)); 
 
        //关闭UDP协议通信对象 
        ds.close(); 
    } 
} 

8-3 sdut-线程-1 利用多线程类实现20个偶数和20个奇数的随机输出。

分数 10

作者 周雪芹

单位 山东理工大学

利用多线程类实现20个偶数和20个奇数的随机输出。

public class NumberThread extends Thread{
    int value;
    public NumberThread(int value) {
        super();
        this.value = value;
    }
    @Override
    public void run() {
        for(int i=0;i<20;i++)
        {
            System.out.print(value+" ");
            value+=2;
        }
    }
}
public class Main{
    public static void main(String[] args) {
        NumberThread nt=new NumberThread(0);
        NumberThread nt1=new NumberThread(1);
        nt.start();
        nt1.start();
    }
}

8-4 sdut-线程-3 利用多线程编程实现多个窗口卖票的问题:三个窗口同时各卖10张票。

分数 10

作者 周雪芹

单位 山东理工大学

利用多线程编程实现多个窗口卖票的问题:三个窗口同时各卖10张票。

 class MyRunnable implements Runnable{ 
    int num=10; 
    public void run() { 
        while(true) 
        { 
            if(num<=0) 
                break; 
            System.out.println(Thread.currentThread().getName()+"卖出第"+num--
 +"张票"); 
        } 
    } 
} 
 
public class Main{ 
    public static void main(String[] args) { 
        MyRunnable m1=new MyRunnable(); 
        Thread t1=new Thread(m1,"窗口1"); 
        Thread t2=new Thread(m1,"窗口2"); 
        Thread t3=new Thread(m1,"窗口3"); 
        t1.start(); 
        t2.start(); 
        t3.start(); 
    } 
} 

8-5 sdut-线程-2 利用多线程编程实现多个窗口卖票的问题:三个窗口共同卖10张票。

分数 10

作者 周雪芹

单位 山东理工大学

利用多线程编程实现多个窗口卖票的问题:三个窗口共同卖10张票。

class MyRunnable implements Runnable{ 
    @Override 
    public void run() { 
        for(int i=1;i<=10;i++) 
            System.out.println(Thread.currentThread().getName()+"卖出第"+i
 +"票"); 
    } 
} 
 
 
public class Main{ 
    public static void main(String[] args) { 
        MyRunnable m1=new MyRunnable(); 
        MyRunnable m2=new MyRunnable(); 
        MyRunnable m3=new MyRunnable(); 
        Thread t1=new Thread(m1,"窗口1"); 
        Thread t2=new Thread(m2,"窗口2"); 
        Thread t3=new Thread(m3,"窗口3"); 
        t1.start(); 
        t2.start(); 
        t3.start(); 
    } 
} 

8-6 sdut-JDBC-1 实现数据库表的CRUD操作

分数 10

作者 周雪芹

单位 山东理工大学

已知MySQL数据库school,字符集为utf8。在其中建立表student,对表中数据进行操作的SQL语句示范如下。

create table student(
id int PRIMARY KEY auto_increment,
name varchar(20) not null,
score float not null);   -- 创建表

insert into student values(null,'李丽',86);   -- 增加记录举例
insert into student values(null,'王五',99);
insert into student values(null,'张三',88);

DELETE FROM student WHERE id=1;                 -- 删除操作举例:从表中删除id=?的记录
UPDATE student SET NAME='山东理工' WHERE id=2;   -- 修改表中记录举例:将id=2的记录姓名和金额列的值修改为新值
SELECT * FROM student;              -- 查询举例1:查询所有记录的所有列信息
SELECT * FROM student WHERE id=2;   -- 查询举例2:查询id=2记录的所有列信息

已知数据库连接字符串为:

Connection conn = DriverManager.getConnection(
             "jdbc:mysql://localhost:3307/school?useunicode=true&characterEncoding=utf-8", 
             "root", 
             "123456");  //数据库服务器名称(地址)、端口号、数据库名称、用户名、密码须根据实际情况改变

功能要求:

(1)向表中增加记录并显示所有记录(数据自己指定);

(2)从表中删除id=1的记录,并显示所有记录;

(3)修改表中记录:查询条件id=2,将name修改为:山东理工,修改完毕显示所有记录;

(4)查询表中id=3的记录并显示。

提交说明: 粘贴JAVA程序代码。

//解决方案1 利用Statement解决问题 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //Class.forName("com.mysql.cj.jdbc.Driver"); 
        Connection con = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/school?useUnicode=true&characterE
                ncoding=utf-8"
                , "root", "123456");

        Statement st = con.createStatement();

        //增加记录 
        String insertSQL1 = "insert into student values(null,'李华',86)";
        String insertSQL2 = "insert into student values(null,'李国',85)";
        st.executeUpdate(insertSQL1);
        st.executeUpdate(insertSQL2);

        //显示所有记录 
        System.out.println("---1.插入记录并显示所有记录---");
        String selectall = "Select * from student";
        ResultSet rs = st.executeQuery(selectall);
        while (rs.next()) {
            int id = rs.getInt(1);  //根据列号取值 
            String name = rs.getString(2);  //根据列号取值 
            double score = rs.getDouble(3); //根据列号取值 
            System.out.println(id + " " + name + " "+ score);
        }

        //删除id=1的记录,显示所有记录 
        String deletSQL = "delete from student where id=1";
        st.executeUpdate(deletSQL);

        //显示所有记录 
        System.out.println("\n---2.删除记录并显示所有记录---");
        rs = st.executeQuery(selectall);
        while (rs.next()) {
            int id = rs.getInt(1);  //根据列号取值 
            String name = rs.getString(2);  //根据列号取值 
            double score = rs.getDouble(3); //根据列号取值 
            System.out.println(id + " " + name + " "+ score);
        }

        //修改id=2,将name修改为:山东理工 
        String updateSQL = "update student set name='山东理工' where id=2";
        st.executeUpdate(updateSQL);
        //显示所有记录 
        System.out.println("\n---3.修改记录并显示所有记录---");
        rs = st.executeQuery(selectall);
        while (rs.next()) {
            int id = rs.getInt(1);  //根据列号取值 
            String name = rs.getString(2);  //根据列号取值 
            double score = rs.getDouble(3); //根据列号取值 
            System.out.println(id + " " + name + " "+ score);
        }

        //查询表中id=3的记录并显示 
        String selectSQL = "select * from student where id=3";
        rs = st.executeQuery(selectSQL);
        System.out.println("\n---4.条件查询记录并显示查询结果---");
        if (rs.next()) {
            int id = rs.getInt("id"); //根据列名取值 
            String name = rs.getString("name"); //根据列名取值 
            double score = rs.getDouble("score"); //根据列名取值 
            System.out.println(id + " " + name + " "+ score);
        }
    }
} 
 

8-7 sdut-JDBC-2 实现数据库表的CRUD操作_中级(PreparedStatement)

分数 10

作者 周雪芹

单位 山东理工大学

已知MySQL数据库school,字符集为utf8。在其中建立表student,对表中数据进行操作的SQL语句示范如下。

create table student(
id int PRIMARY KEY auto_increment,
name varchar(20) not null,
score float not null);   -- 创建表

insert into student values(null,'李丽',86);   -- 增加记录举例
insert into student values(null,'王五',99);
insert into student values(null,'张三',88);

DELETE FROM student WHERE id=1;                 -- 删除操作举例:从表中删除id=?的记录
UPDATE student SET NAME='山东理工' WHERE id=2;   -- 修改表中记录举例:将id=2的记录姓名和金额列的值修改为新值
SELECT * FROM student;              -- 查询举例1:查询所有记录的所有列信息
SELECT * FROM student WHERE id=2;   -- 查询举例2:查询id=2记录的所有列信息

已知数据库连接字符串为:

Connection conn = DriverManager.getConnection(
             "jdbc:mysql://localhost:3306/school?useunicode=true&characterEncoding=utf-8", 
             "root", 
             "123456");  //数据库服务器名称(地址)、端口号、数据库名称、用户名、密码须根据实际情况改变

要求:利用PreparedStatement实现如下功能,其中的操作数据由外部提供。
(1)向表中增加记录(id列自增,可只考虑姓名和成绩),并显示所有记录;
(2)从表中删除id=? 的记录,并显示所有记录;
(3)修改表中记录:查询条件id=?,将name修改为:?,修改完毕显示所有记录;
(4)查询表中id=? 的记录并显示。
提交说明:粘贴JAVA程序代码。

//利用PreparedStatement解决问题
import java.sql.*;
public class Main {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //Class.forName("com.mysql.cj.jdbc.Driver");
        Connection con = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/school?useUnicode=true&characterE
                ncoding=utf-8"
                , "root", "123456");

        PreparedStatement pst = null; //定义预编译SQL语句执行对象

        //增加记录
        String insertSQL= "insert into student values(null,?,?)";
        pst=con.prepareStatement(insertSQL);
        pst.setString(1,"ANNA"); //为SQL语句中第1个未知数据提供数值
        pst.setDouble(2,86.5);   //为SQL语句中第2个未知数据提供数值
        pst.executeUpdate();

        //显示所有记录
        System.out.println("---1.插入记录并显示所有记录---");
        String selectall = "Select * from student";
        ResultSet rs = pst.executeQuery(selectall);
        while (rs.next()) {
            int id = rs.getInt(1);
            String name = rs.getString(2);
            double score = rs.getDouble(3);
            System.out.println(id + " " + name + " "  + score);
        }

        //删除id=1的记录,显示所有记录
        String deleteSQL = "delete from student where id=?";
        pst=con.prepareStatement(deleteSQL);
        pst.setInt(1,1);
        pst.executeUpdate();

        //显示所有记录
        System.out.println("\n---2.删除记录并显示所有记录---");
        rs = pst.executeQuery(selectall);
        while (rs.next()) {
            int id = rs.getInt(1);
            String name = rs.getString(2);
            double score = rs.getDouble(3);
            System.out.println(id + " " + name + " "  + score);
        }

        //修改id=2,将name修改为:山东理工
        String updateSQL = "update student set name=? where id=?";
        pst=con.prepareStatement(updateSQL);
        pst.setString(1,"山东理工");
        pst.setInt(2,2);
        pst.executeUpdate();
        //显示所有记录
        System.out.println("\n---3.修改记录并显示所有记录---");
        rs = pst.executeQuery(selectall);
        while (rs.next()) {
            int id = rs.getInt(1);
            String name = rs.getString(2);
            double score = rs.getDouble(3);
            System.out.println(id + " " + name + " "  + score);
        }

        //查询表中id=3的记录并显示
        String selectSQL = "select * from student where id=?";
        pst=con.prepareStatement(selectSQL);
        pst.setInt(1,3);
        rs = pst.executeQuery();
        System.out.println("\n---4.条件查询记录并显示查询结果---");
        if (rs.next()) {
            int id = rs.getInt("id"); //根据列名取值
            String name = rs.getString("name"); //根据列名取值
            double score = rs.getDouble("score"); //根据列名取值
            System.out.println(id + " " + name + " "+ score);
        }

        //关闭数据库连接等对象,后打开的先关闭,先打开的后关闭
        rs.close();
        pst.close();
        con.close();
    }
}

8-8 sdut-JDBC-9901 银行账户管理及求账户余额1

分数 20

作者 周雪芹

单位 山东理工大学

1、已知MySQL数据库bank,字符集为utf-8。在其中建立表account,并向表里插入几条记录。SQL语句如下:

DROP table if EXISTS ACCOUNT;  -- 如果ACCOUNT表存在,就删除

create table ACCOUNT    -- 创建表ACCOUNT
(
id int PRIMARY KEY AUTO_INCREMENT,  -- 账户id
name varchar(20) not NULL,   -- 姓名
balance float not NULL    -- 账户余额
);

insert into account values(null,'李丽',1065.55);    -- 插入第1条记录
insert into account values(null,'王五',5656.35);  -- 插入第2条记录
insert into account values(null,'张三',100);     -- 插入第3条记录

SELECT * FROM account;    -- 查询所有记录

2、已知数据库连接字符串为:

Connection conn = DriverManager.getConnection(
             "jdbc:mysql://localhost:3306/bank?useunicode=true&characterEncoding=utf-8", 
             "root", 
             "");  //数据库服务器名称(地址)、端口号、数据库名称、用户名、密码须根据实际情况改变

3、功能要求:
(1)向表中增加记录(姓名:LISA,账户余额:2000);
(2)从表中删除id=1的记录;
(3)修改表中记录:查询条件id=2,将金额修改为:900,
(4)显示account表中的所有记录的内容,各行数据输出形式为:“id name balance”,数据之间有1个空格;
(5)计算account表中所有账户的余额之和并输出该数的整数值,形式为:“账户总金额为:整数值”。

4、提交说明: 粘贴JAVA程序代码。

5、操作表数据的SQL语句提示如下:

insert into ACCOUNT values(null,'ABCD',100);  --增加记录示例
delete from ACCOUNT where 条件;                --删除记录示例
update ACCOUNT set 字段1=?,字段2=? where 条件;  --修改记录示例
select * from ACCOUNT;                        --查询所有记录的所有字段
select * from ACCOUNT  where 条件;            --按条件查询记录的所有字段
import java.sql.*;

public class Main {
    public static void main(String[] args) throws SQLException {
        Connection conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/bank?useunicode=true&characterEncoding=utf-8",
                "root",
                "");  //数据库服务器名称(地址)、端口号、数据库名称、用户名、密码须根据实际情况改变
//        updateRecord(conn,2,"aaaa",(float)1);
//        listRecord(conn,2);
        addRecord(conn,"LISA",2000);
        deleteRecord(conn,1);
        updateRecord(conn,2,(float)900);
        listRecord(conn);
        System.out.println(getBalance(conn));
//        Statement st=conn.createStatement();
//        st.executeQuery("");
    }

    public static int getBalance(Connection conn) throws SQLException {
        PreparedStatement st=conn.prepareStatement("select * from ACCOUNT;");
        ResultSet res=st.executeQuery();
        float sum=0;
        while(res.next())
            sum+=res.getFloat("balance");
        return (int)sum;

    }
    public static void addRecord(Connection conn,String name,float balance) throws SQLException {
//        System.out.println(name+" "+balance);
        PreparedStatement st=conn.prepareStatement("insert into ACCOUNT values(null,?,?);");
        st.setString(1,name);
        st.setFloat(2,balance);
        st.executeUpdate();
    }

    public static void deleteRecord(Connection conn,int id) throws SQLException {
        PreparedStatement st=conn.prepareStatement("delete from ACCOUNT where id=?;");
        st.setInt(1,id);
        st.executeUpdate();
    }


    public static void listRecord(Connection conn) throws SQLException {
        PreparedStatement st= conn.prepareStatement("select * from ACCOUNT;");
        st.executeQuery();
        ResultSet rs=st.getResultSet();
        while (rs.next()){
            System.out.println(rs.getInt("id")+" "+rs.getString("name")+" "+rs.getFloat("balance"));
        }
    }
    public static void updateRecord(Connection conn,int id,float balance) throws SQLException {
        PreparedStatement st= conn.prepareStatement("update ACCOUNT set balance=? where id=?;");
        st.setInt(2,id);
        st.setFloat(1,balance);
        st.executeUpdate();
    }
}

8-9 sdut-JDBC-9902 银行账户管理及求账户余额2

分数 15

作者 周雪芹

单位 山东理工大学

1、题目说明:

已知MySQL数据库bank,字符集为utf-8。在其中建立表account,并向表里插入几条记录。SQL语句如下:

DROP table if EXISTS ACCOUNT;  -- 如果ACCOUNT表存在,就删除

create table ACCOUNT    -- 创建表ACCOUNT
(
id int PRIMARY KEY AUTO_INCREMENT,  -- 账户id
name varchar(20) not NULL,   -- 姓名
balance float not NULL    -- 账户余额
);

insert into account values(null,'LINA',2365.55);    -- 插入第1条记录
insert into account values(null,'HOTEL',4535.45);   -- 插入第2条记录
insert into account values(null,'WANGLI',100);      -- 插入第3条记录

SELECT * FROM account;    -- 查询所有记录

2、已知数据库连接字符串为:

Connection conn = DriverManager.getConnection(
             "jdbc:mysql://localhost:3306/bank?useunicode=true&characterEncoding=utf-8", 
             "root", 
             "");  //数据库服务器名称(地址)、端口号、数据库名称、用户名、密码须根据实际情况改变

3、功能要求:
(1)向表中增加记录(姓名:LISA,账户余额:2000);
(2)修改表中记录:查询条件id=2,将账户金额减去1;
(3)显示account表中的所有记录的内容,各行数据输出形式为:“id name balance”,数据之间有1个空格;
(4)计算account表中所有账户的余额之和并输出该数的整数值,形式为:“账户总金额为:整数值”。

4、提交说明: 粘贴JAVA程序代码。

5、操作表数据的SQL语句提示如下:

insert into ACCOUNT values(null,'ABCD',100);      --增加记录示例
update ACCOUNT set balance=balance-1 where 条件;  --修改记录,将符合条件的记录的金额列数值-1
select * from ACCOUNT;                           --查询所有记录的所有字段
select * from ACCOUNT  where 条件;                --按条件查询记录的所有字段
import java.sql.*;
public class Main
{
    public static void main(String[] args) throws SQLException {
        Connection con = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/bank?useunicode=true&characterEncoding=utf-8",
                "root",
                "");  //数据库服务器名称(地址)、端口号、数据库名称、用户名、密码须根据实际情况改变
        addRecord(con,"LISA",2000);
        updateRecord(con,2);
        listRecord(con);
        System.out.println("账户总金额为:"+sumRecord(con));
    }
    public static void addRecord(Connection con,String name,float balance) throws SQLException {
        PreparedStatement st= con.prepareStatement("insert into ACCOUNT values(null,?,?);");
        st.setString(1,name);
        st.setFloat(2,balance);
        st.executeUpdate();
    }
    public static void updateRecord(Connection con,int id) throws SQLException {
        PreparedStatement st=con.prepareStatement("update ACCOUNT set balance=balance-1 where id=?;");
        st.setInt(1,id);
        st.executeUpdate();
    }
    public static void listRecord(Connection con) throws SQLException {
        PreparedStatement st=con.prepareStatement("select * from ACCOUNT;  ");
        ResultSet res=st.executeQuery();
        while(res.next())
            System.out.println(res.getInt("id")+" "+res.getString("name")+" "+ res.getFloat("balance"));
    }
    public static int sumRecord(Connection con) throws SQLException {
        PreparedStatement st=con.prepareStatement("select * from ACCOUNT;  ");
        ResultSet res=st.executeQuery();
        float sum=0;
        while(res.next())
            sum+=res.getFloat("balance");
        return (int)sum;
    }
}

8-10 sdut-JDBC-9903 图书信息管理

分数 20

作者 周雪芹

单位 山东理工大学

已知MySQL数据库bookstore,字符集为utf-8。在其中建立表book,利用Java程序对book表中的数据进行管理。
已知:创建book表和向表中增加记录的SQL语句如下:

create table book
(
id int PRIMARY KEY AUTO_INCREMENT,  -- 图书id,主键,自增
name varchar(20) not NULL,   -- 书名,非空
price float not NULL,    -- 单价,非空
  count int not NULL  -- 数量,非空
);

insert into book values(null,'Java程序设计',59.5,1000);    -- 插入第1条记录
insert into book values(null,'JSP程序设计',36.9,30);        -- 插入第2条记录
insert into book values(null,'C语言程序设计',40.5,100);     -- 插入第3条记录

SELECT * FROM book;    -- 查询所有记录

已知数据库连接字符串为:

Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/bookstore?useunicode=true&characterEncoding=utf-8", 
             "root", 
             "");  //数据库服务器名称(地址)、端口号、数据库名称、用户名、密码须根据实际情况改变

功能要求:
(1)向表中增加一本书并显示所有记录(id自动增1,书名为JavaWeb,单价为50.2,数量为35);
(2)从表中删除图书数量count<50的图书;
(3)修改表中记录:查询条件count为1000的记录,将其图书数量修改为100;

(4)显示book表中所有的记录,形式为:“1 Java程序设计 59.5 100”,列数据之间加1个空格;
(5)求book表中所有图书的总价(每本书的单价*数量之和,取整数值),并输出,格式为:“图书总价为:100”。
提交说明: 粘贴JAVA程序代码。

对表进行操作的SQL提示及建议:
(1)增加记录的SQL语句:insert into book values(null,'C语言',40.5,100);
(2)删除记录的SQL语句为:delete from book where 条件;
(3)修改记录的SQL语句为:update book set 字段=值 where 条件
(4)查询表中所有记录的所有字段的SQL语句为:select * from book
(4)查询表中符合条件的记录的所有字段的SQL语句为:select * from book where 条件

import com.mysql.cj.jdbc.PreparedStatementWrapper;

import java.sql.*;
public class Main
{
    public static void main(String[] args) throws SQLException {
        Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/bookstore?useunicode=true&characterEncoding=utf-8",
                "root",
                "");  //数据库服务器名称(地址)、端口号、数据库名称、用户名、密码须根据实际情况改变
        addRecord(conn,"JavaWeb", 50.2F,35);
        deleteRecord(conn,50);
        updateRecord(conn,1000,100);
        listRecord(conn);
        System.out.println("图书总价为:"+getSum(conn));

    }

    public static void addRecord(Connection con,String name,float price,int count) throws SQLException {
        PreparedStatement st=con.prepareStatement("insert into book values(null,?,?,?);");
        st.setString(1,name);
        st.setFloat(2,price);
        st.setInt(3,count);
        st.executeUpdate();
        listRecord(con);

    }

    public static void deleteRecord(Connection con,int x) throws SQLException {
        PreparedStatement st=con.prepareStatement("delete from book where count<?;");
        st.setInt(1,x);
        st.executeUpdate();
    }

    public static void updateRecord(Connection con,int pre,int last) throws SQLException {
        PreparedStatement st=con.prepareStatement("update book set count=? where count=?;");
        st.setInt(1,last);
        st.setInt(2,pre);
        st.executeUpdate();
    }
    public static void listRecord(Connection con) throws SQLException {
        PreparedStatement st=con.prepareStatement("select * from book; ");
        ResultSet res=st.executeQuery();
        while(res.next())
            System.out.println(res.getInt("id")+" "+res.getString("name")+" "+res.getFloat("price")+" "+res.getInt("count"));
    }

    public static int getSum(Connection con) throws SQLException {
        PreparedStatement st=con.prepareStatement("select * from book; ");
        ResultSet res=st.executeQuery();
        float sum=0;
        while(res.next())
            sum+=res.getFloat("price")*res.getInt("count");
        return (int)sum;
    }
}

8-11 sdut-IO-2 利用字节输入输出流类,写出数据并读取文件

分数 10

作者 周雪芹

单位 山东理工大学

利用字节输入输出流类,完成如下任务:
(1)从键盘上获取数据(直到一行数据"end"为读取结束),将数据写出到文件d:\data.dat中。
(2)读出文件d:\data.dat里面的内容,将其显示在屏幕上。
可以使用不种的字节流读写数据。

说明:主类类名为Main。
提示:可用如下字节输入/输出流 FileInputStreamFileOutputStreamBufferedInputStreamBufferedOutputStreamDataInputStreamDataOutputStreamRandomAccessFile

//参考代码1: 
使用FileInputStream和FileOutputStream实现读写操作。 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.Scanner; 
 
public class Main { 
    public static void main(String[] args) throws IOException { 
        Scanner reader=new Scanner(System.in); //准备从键盘读取数据 
        String line = reader.nextLine();//读取一行 
 
        FileOutputStream fos=new FileOutputStream("d:\\data.dat"); //创建文件输
出流 
        //若读取到的一行字符串不为“end",写文件 
        while(!line.equals("end")) 
        { 
            fos.write((line).getBytes());  //写文件 
            line=reader.nextLine();      //从键盘再读一行字符 
        } 
        fos.close();  //输出流关闭 
 
        StringBuffer buf=new StringBuffer(); //创建字符串缓冲区 
        FileInputStream fis=new FileInputStream("d:\\data.dat"); //创建文件输出
流 
        byte[] bytes=new byte[10]; 
        int len=fis.read(bytes);  //第一次读文件 
        //若文件尚未读取结束,则边读边显示数据 
        while(len!=-1) 
        { 
            String str=new String(bytes,0,len); //由字节数组构造字符串,便于观察 
            buf.append(str); //追加到缓冲区,待文件读取完,再显示 
            len=fis.read(bytes); //再读一次文件 
        } 
        fis.close(); //文件输入流关闭 
        System.out.println(buf); //显示读取的数据 
    } 
} 
 
 
//参考代码2:使用BufferedInputStream 和BufferedOutputStream实现读写操作。 
import java.io.*; 
import java.util.Scanner; 
 
public class Main { 
    public static void main(String[] args) throws IOException { 
        Scanner reader = new Scanner(System.in); //准备从键盘读取数据 
        String line = reader.nextLine();//读取一行 
 
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStre
 am("d:\\data.dat")); //创建文件输出流 
        //若读取到的一行字符串不为“end",写文件 
        while (!line.equals("end")) { 
            bos.write((line).getBytes());  //写文件 
            line = reader.nextLine();      //从键盘再读一行字符 
        } 
        bos.close();  //输出流关闭 
 
        StringBuffer buf = new StringBuffer(); //创建字符串缓冲区 
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream
 ("d:\\data.dat")); //创建文件输出流 
        byte[] bytes = new byte[10]; 
        int len = bis.read(bytes);  //第一次读文件 
        //若文件尚未读取结束,则边读边显示数据 
        while (len != -1) { 
            String str = new String(bytes, 0, len); //由字节数组构造字符串,便于观
察 
            buf.append(str); //追加到缓冲区,待文件读取完,再显示 
            len = bis.read(bytes); //再读一次文件 
        } 
        bis.close(); //文件输入流关闭 
        System.out.println(buf); //显示读取的数据 
    } 
} 
 
 
//参考代码3:使用DataInputStream和DataOutputStream实现读写操作。 
import java.io.*; 
import java.util.Scanner; 
 
public class Main { 
    public static void main(String[] args) throws IOException { 
        Scanner reader = new Scanner(System.in); //准备从键盘读取数据 
        String line = reader.nextLine();//读取一行 
 
        DataOutputStream dos = new DataOutputStream(new FileOutputStream
 ("d:\\data.dat")); //创建文件输出流 
        //若读取到的一行字符串不为“end",写文件 
        while (!line.equals("end")) { 
            dos.write((line).getBytes());  //写文件 
            line = reader.nextLine();      //从键盘再读一行字符 
        } 
        dos.close();  //输出流关闭 
 
        StringBuffer buf = new StringBuffer(); //创建字符串缓冲区 
        DataInputStream dis = new DataInputStream(new FileInputStream("d:\\dat
 a.dat")); //创建文件输出流 
        byte[] bytes = new byte[10]; 
        int len = dis.read(bytes);  //第一次读文件 
        //若文件尚未读取结束,则边读边显示数据 
        while (len != -1) { 
            String str = new String(bytes, 0, len); //由字节数组构造字符串,便于观
察 
            buf.append(str); //追加到缓冲区,待文件读取完,再显示 
            len = dis.read(bytes); //再读一次文件 
        } 
        dis.close(); //文件输入流关闭 
        System.out.println(buf); //显示读取的数据 
    } 
} 
 
 
//参考代码4:使用RandomAccessFile实现读写操作。 
import java.io.IOException; 
import java.io.RandomAccessFile; 
import java.util.Scanner; 
 
public class Main { 
    public static void main(String[] args) throws IOException { 
        Scanner reader=new Scanner(System.in); //准备从键盘读取数据 
        String line = reader.nextLine();//读取一行 
 
        RandomAccessFile raf=new  RandomAccessFile("d:\\data.dat","rw"); //以读
写方式创建随机访问文件流 
        //若读取到的一行字符串不为“end",写文件 
        while(!line.equals("end")) 
        { 
            raf.write((line).getBytes());  //写文件 
            line=reader.nextLine();      //从键盘再读一行字符 
        } 
 
        StringBuffer buf=new StringBuffer(); //创建字符串缓冲区 
        raf.seek(0);  //下一步即将读取数据,移动文件指针至文件开始位置 
        byte[] bytes=new byte[10]; 
        int len=raf.read(bytes);  //第一次读文件 
        //若文件尚未读取结束,则边读边显示数据 
        while(len!=-1) 
        { 
            String str=new String(bytes,0,len); //由字节数组构造字符串,便于观察 
            buf.append(str); //追加到缓冲区,待文件读取完,再显示 
            len=raf.read(bytes); //再读一次文件 
        } 
        raf.close(); //文件输入流关闭 
        System.out.println(buf); //显示读取的数据 
    } 
} 

8-12 sdut-IO-3 利用字符输入输出流类,写出数据并读取文件

分数 10

作者 周雪芹

单位 山东理工大学

利用字符输入输出流类,完成如下任务:
(1)从键盘上获取数据(直到一行数据"end"为读取结束),将数据写出到文件d:\data.txt中。
(2)读出文件d:\data.txt里面的内容,将其显示在屏幕上。
说明:主类类名为:Main。
捍示:可用如下字符输入/输出流 FileReaderFileWriterBufferedReaderBufferedWriter

//参考代码1:利用FileReader和FileWriter对文件进行读写操作。 
import java.io.*; 
import java.util.Scanner; 
 
public class Main { 
    public static void main(String[] args) throws IOException { 
        Scanner reader=new Scanner(System.in); //准备从键盘读取数据 
        String line = reader.nextLine();//读取一行 
 
        FileWriter fw=new FileWriter("d:\\data.dat"); //创建文件输出流 
        //若读取到的一行字符串不为“end",写文件 
        while(!line.equals("end")) 
        { 
            fw.write(line);  //写文件 
            line=reader.nextLine();      //从键盘再读一行字符 
        } 
        fw.close();  //输出流关闭 
 
        StringBuffer buf=new StringBuffer(); //创建字符串缓冲区 
        FileReader fr=new FileReader("d:\\data.dat"); //创建文件输出流 
        char[] chars=new char[10]; 
        int len=fr.read(chars);  //第一次读文件 
        //若文件尚未读取结束,则边读边显示数据 
        while(len!=-1) 
        { 
            String str=new String(chars,0,len); //由字节数组构造字符串,便于观察 
            buf.append(str); 
            len=fr.read(chars); //再读一次文件 
        } 
        fr.close(); //文件输入流关闭 
        System.out.println(buf); 
    } 
} 
 
//参考代码2:利用BufferedFileReader和BufferedFileWriter对文件进行读写操作。 
import java.io.*; 
import java.util.Scanner; 
 
public class Main { 
    public static void main(String[] args) throws IOException { 
        Scanner reader=new Scanner(System.in); //准备从键盘读取数据 
        String line = reader.nextLine();//读取一行 
 
        BufferedWriter bw=new BufferedWriter(new FileWriter("d:\\data.dat")); 
//创建文件输出流 
        //若读取到的一行字符串不为“end",写文件 
        while(!line.equals("end")) 
        { 
            bw.write(line);  //写文件 
            line=reader.nextLine();      //从键盘再读一行字符 
        } 
        bw.close();  //输出流关闭 
 
        StringBuffer buf=new StringBuffer(); //创建字符串缓冲区 
        BufferedReader br=new BufferedReader(new FileReader("d:\\data.dat")); 
//创建文件输出流 
        char[] chars=new char[10]; 
        int len=br.read(chars);  //第一次读文件 
        //若文件尚未读取结束,则边读边显示数据 
        while(len!=-1) 
        { 
            String str=new String(chars,0,len); //由字节数组构造字符串,便于观察 
            buf.append(str); 
            len=br.read(chars); //再读一次文件 
        } 
        br.close(); //文件输入流关闭 
        System.out.println(buf); 
    } 
} 

8-13 sdut-IO-4 利用对象输入/输出流进行文件的读写

分数 10

作者 周雪芹

单位 山东理工大学

利用对象输入/输出流进行文件的读写。
(1)创建类Student,内含学号、姓名、年龄、班级等属性,重写父类的toString()方法,用于输出学生的信息;
(2)建立测试类,建立Student类的对象数组stuArray,里面放置若干个学生对象,将数组中的数据依次写入文件stu.dat;然后读取该文件中的信息,依次还原出数组中各Student对象的信息。

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.Serializable; 
import java.util.*; 
class Student implements Serializable{  //接口Serializable可序列化 
    String id; 
    String name; 
    int age; 
    String clas; 
    public Student(String id, String name, int age, String clas) { 
        super(); 
        this.id = id; 
        this.name = name; 
        this.age = age; 
        this.clas = clas; 
    }  
    public String toString() { 
        return "id:"+id+"\tname:"+name+"\tage:"+age+"\tclass:"+clas; 
    } 
} 
public class Main { 
    public static void main(String[] args) throws FileNotFoundException, IOExc
 eption, ClassNotFoundException { 
       Scanner reader=new Scanner(System.in); 
       Student Array[]= { 
               new Student("001","xyl",19,"3"), 
               new Student("002","smy",20,"3"), 
               new Student("003","zgl",18,"3") 
       }; 
       ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("st
 u.dat")); 
       oos.writeObject(Array); 
       ObjectInputStream ois=new ObjectInputStream(new FileInputStream("stu.da
 t")); 
       Object ob = ois.readObject(); 
       if(ob instanceof Student[]) 
       { 
           Student list[]=(Student[])ob; 
           for(Student stu:list) 
           { 
               System.out.println(stu); 
           } 
       } 
    } 
}

8-14 sdut-IO-5 读取网络资源,写出代码至文件。

分数 10

作者 周雪芹

单位 山东理工大学

读取网络资源,写出代码至文件。
读取“http://www.sdut.edu.cn“网页内容,存至“d:\sdut.html”。

提示语句:

URL url=new URL("https://www.sdut.edu.cn/");
InputStream is = url.openStream();
import java.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
public class Main {
    public static void main(String[] args) throws IOException {
        URL u=new URL("https://www.sdut.edu.cn/");
        InputStream is=u.openStream();
        OutputStream os=new FileOutputStream("d:/sdut.html");
        byte byes[]=new byte[10];
        int len=0;
        while((len=is.read(byes))!=-1)
        {
            os.write(byes, 0, len);
        }
    }
} 

8-15 sdut-IO-7 利用File类进行文件及文件夹名称的显示

分数 10

作者 周雪芹

单位 山东理工大学

利用File类进行文件及文件夹名称的显示。
编写应用程序,列出指定目录(d:/test)下的所有文件和目录名,然后将该目录下的所有文件后缀名为.txt的文件过滤出来显示在屏幕上。

import java.io.*; 
public class Main { 
    public static void main(String[] args) throws IOException, ClassNotFoundEx
 ception { 
        File file=new File("d:/test"); 
        File[] l = file.listFiles(); 
        if(l==null) 
        { 
            System.out.println("不存在"); 
        } 
        else 
        { 
            for(int i=0;i<l.length;i++) 
                System.out.println(l[i]); 
            System.out.println("------所有文本文件如下------"); 
            String[] l2 = file.list(); 
            for(int i=0;i<l2.length;i++) 
            { 
                if(l2[i].endsWith(".txt")) 
                    System.out.println(l2[i]); 
            } 
        } 
    } 
} 

8-16 sdut-IO-9901 利用字节输入输出流(或字符输入输出流)类,读入数据-输出文件-读入文件-显示数据

分数 10

作者 周雪芹

单位 山东理工大学

利用字节或字符输入、输出流,完成如下任务:
(1)从键盘上获取一行数据,将数据写出到文件d:\data\myfile.txt中(直到该行数据为"END"时,读取结束)。
(2)读出文件d:\data\myfile.txt,将其中的字符显示在屏幕上。
说明:主类类名为:Main。

import java.io.*;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        // (1) 从键盘获取一行数据并写入到文件中,直到输入"END"
        try (Scanner scanner = new Scanner(System.in); // 用于从键盘读取数据
             FileWriter fileWriter = new FileWriter("d:/data/myfile.txt")) {

            System.out.println("请输入数据,输入'END'结束:");
            while (true) {
                // 获取用户输入
                String line = scanner.nextLine();

                // 如果输入"END",则停止写入并退出循环
                if ("END".equals(line)) {
                    break;
                }

                // 将输入的数据写入文件
                fileWriter.write(line + System.lineSeparator()); // 使用换行符写入
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        // (2) 读取文件内容并显示在屏幕上
        try (FileReader fileReader = new FileReader("d:/data/myfile.txt");
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {

            String line;
            System.out.println("文件内容如下:");
            while ((line = bufferedReader.readLine()) != null) {
                System.out.println(line);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

论述题均为GPT生成

8-17 sdut-论述-面向对象-多态

分数 5

作者 周雪芹

单位 山东理工大学

什么是多态?请提供一个Java代码示例,展示如何通过方法重载和方法覆盖实现多态性。

  多态(Polymorphism)概述:

多态是面向对象编程中的一个核心概念,它指的是同一个方法或操作在不同的对象上表现出不同的行为。在 Java 中,多态通常通过方法重载(Overloading)和方法覆盖(Overriding)来实现。

1. 方法重载(Method Overloading)

方法重载是指在同一个类中,可以定义多个方法名相同,但参数列表不同(可以是参数类型不同、参数个数不同,或者两者同时不同)的多个方法。方法重载是静态多态(编译时多态),即方法的调用在编译时就能决定。

2. 方法覆盖(Method Overriding)

方法覆盖是指在子类中重新定义父类已经定义的方法,并且方法签名完全相同。方法覆盖是动态多态(运行时多态),即方法的调用在运行时决定,依据对象的实际类型。

示例代码:

以下示例演示了如何通过方法重载和方法覆盖来实现多态。

// 父类
class Animal {
    // 方法覆盖:父类中定义的叫声方法
    public void sound() {
        System.out.println("Animal makes a sound");
    }
}

// 子类1:Dog
class Dog extends Animal {
    // 方法覆盖:子类Dog覆盖父类的sound方法
    @Override
    public void sound() {
        System.out.println("Dog barks");
    }

    // 方法重载:同名方法,但参数不同
    public void sound(int times) {
        System.out.println("Dog barks " + times + " times");
    }
}

// 子类2:Cat
class Cat extends Animal {
    // 方法覆盖:子类Cat覆盖父类的sound方法
    @Override
    public void sound() {
        System.out.println("Cat meows");
    }
}

public class Main {
    public static void main(String[] args) {
        // 多态性:通过父类引用指向子类对象
        Animal animal1 = new Dog(); // 向上转型
        Animal animal2 = new Cat(); // 向上转型

        // 调用覆盖方法,根据实际对象类型决定调用哪个方法
        animal1.sound();  // 输出: Dog barks
        animal2.sound();  // 输出: Cat meows

        // 通过子类对象调用重载方法
        Dog dog = new Dog();
        dog.sound(3);  // 输出: Dog barks 3 times
    }
}
代码解析:
  1. 方法重载(Overloading)

    • Dog 类中,sound(int times) 方法是对 sound() 方法的重载。它接受一个整数参数,表示狗叫的次数,并输出相应的信息。通过方法重载,我们可以使用相同的方法名实现不同的功能(参数不同)。
  2. 方法覆盖(Overriding)

    • DogCat 类都覆盖了父类 Animal 中的 sound() 方法。虽然 Animal 类中有一个 sound() 方法,但在 DogCat 中,这个方法的实现各自不同。这就是多态的体现。调用 sound() 时,实际执行的是当前对象(DogCat)中的方法,而不是父类中的方法。
    • 动态多态:在 main 方法中,animal1Animal 类型的引用,但它指向的是 Dog 类型的对象;animal2Animal 类型的引用,但它指向的是 Cat 类型的对象。在运行时,Java 会根据实际对象的类型来决定调用哪个 sound() 方法。这就是方法覆盖实现的多态性。
输出结果:
Dog barks
Cat meows
Dog barks 3 times
总结:
  • 方法重载:在同一个类中,允许多个方法拥有相同的名字,但方法签名(参数个数或类型)不同。方法重载发生在编译时。
  • 方法覆盖:子类重新实现父类的方法,方法签名完全相同。方法覆盖发生在运行时,Java 根据对象的实际类型来调用对应的覆盖方法。

通过这种方式,Java 实现了多态性,让相同的方法名在不同的类中表现出不同的行为。


8-18 sdut-论述-面向对象-封装

分数 5

作者 周雪芹

单位 山东理工大学

描述Java中的封装概念,并举例说明如何在实际项目中应用封装来保护数据。

封装(Encapsulation)概念:

封装是面向对象编程的基本特性之一,它指的是将对象的状态(属性)和行为(方法)包装在一起,并通过访问控制机制(如 privatepublic 等)来限制外部对对象内部细节的直接访问。封装的目的是保护数据的完整性,避免外部代码直接修改对象的内部状态,从而提高代码的安全性和可维护性。

封装的关键点:
  1. 数据隐藏:通过将类的属性设置为私有的(private),防止外部直接访问和修改这些属性。
  2. 提供公共方法:通过公共的 getter 和 setter 方法来允许外部代码安全地访问和修改对象的属性,同时可以在这些方法中加入验证和逻辑,以确保数据的合法性。
示例:封装在实际项目中的应用
// 类:银行账户
class BankAccount {
    // 私有属性,外部无法直接访问
    private double balance;

    // 构造方法
    public BankAccount(double initialBalance) {
        if (initialBalance > 0) {
            balance = initialBalance;
        } else {
            balance = 0;
        }
    }

    // 公共方法:获取余额(getter)
    public double getBalance() {
        return balance;
    }

    // 公共方法:存款(setter)
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        } else {
            System.out.println("存款金额必须大于0");
        }
    }

    // 公共方法:取款
    public void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
        } else {
            System.out.println("取款金额无效");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        // 创建一个银行账户对象
        BankAccount account = new BankAccount(1000.0);

        // 存款
        account.deposit(500.0);
        System.out.println("当前余额: " + account.getBalance());

        // 取款
        account.withdraw(200.0);
        System.out.println("当前余额: " + account.getBalance());

        // 试图存负数金额(非法操作)
        account.deposit(-100.0);

        // 试图取超过余额的金额(非法操作)
        account.withdraw(2000.0);
    }
}
代码解析:
  1. 数据隐藏balance 属性是 private 的,外部无法直接访问和修改这个属性,防止了直接修改余额的危险。
  2. 公共方法:提供了 getBalance() 方法来访问余额,deposit(double amount)withdraw(double amount) 方法来操作余额。每个方法内部都做了合理的验证(例如,存款金额必须大于 0,取款金额不能超过余额),确保数据的合法性。
输出结果:
当前余额: 1500.0
当前余额: 1300.0
存款金额必须大于0
取款金额无效
小结:

封装通过将对象的状态和行为绑定在一起,保护了数据的完整性,同时提供了控制访问和修改数据的机制。在实际项目中,通过封装可以避免直接修改对象的属性,确保数据的一致性和安全性。


8-19 sdut-论述-面向对象-继承

分数 5

作者 周雪芹

单位 山东理工大学

什么是继承?请提供一个Java代码示例,展示如何通过继承实现代码复用。

继承(Inheritance)概念:

继承是面向对象编程的一个重要特性,它允许一个类继承另一个类的属性和方法,从而实现代码的复用。继承的关键是子类可以继承父类的公共和保护成员(方法和属性),从而无需重新编写相同的代码。子类不仅可以使用父类的成员,还可以扩展或修改父类的功能。

继承的关键点:
  1. 父类(Superclass):被继承的类,包含一些基本的属性和方法。
  2. 子类(Subclass):继承父类的类,可以继承父类的属性和方法,也可以扩展或重写父类的方法。
  3. extends 关键字:在 Java 中,子类通过 extends 关键字来继承父类。
示例:通过继承实现代码复用
// 父类:Animal
class Animal {
    // 父类的属性
    String name;

    // 父类的构造方法
    public Animal(String name) {
        this.name = name;
    }

    // 父类的方法
    public void speak() {
        System.out.println(name + " makes a sound");
    }
}

// 子类:Dog,继承自Animal
class Dog extends Animal {
    // 子类的构造方法,调用父类的构造方法
    public Dog(String name) {
        super(name);  // 调用父类的构造方法
    }

    // 子类重写父类的方法
    @Override
    public void speak() {
        System.out.println(name + " barks");
    }
}

// 子类:Cat,继承自Animal
class Cat extends Animal {
    // 子类的构造方法,调用父类的构造方法
    public Cat(String name) {
        super(name);
    }

    // 子类重写父类的方法
    @Override
    public void speak() {
        System.out.println(name + " meows");
    }
}

public class Main {
    public static void main(String[] args) {
        // 创建子类对象,利用继承复用父类代码
        Animal dog = new Dog("Buddy");
        Animal cat = new Cat("Whiskers");

        // 调用子类重写的方法
        dog.speak();  // 输出: Buddy barks
        cat.speak();  // 输出: Whiskers meows
    }
}
代码解析:
  1. 父类 Animal

    • Animal 类有一个属性 name 和一个方法 speak(),它用于输出动物的叫声。
    • Animal 的构造方法初始化 name 属性。
  2. 子类 DogCat

    • DogCat 类都继承了 Animal 类,分别通过 extends Animal 继承了父类的属性和方法。
    • 子类 DogCat 重写了 speak() 方法,以便提供不同的行为。重写是通过 @Override 注解来标明的。
  3. 代码复用

    • 通过继承,DogCat 不需要重新实现 name 属性和构造方法,因为它们直接继承自 Animal 类。
    • 只有 speak() 方法被子类覆盖(重写),每个子类提供了自己的实现,从而实现了多态。
输出结果:
Buddy barks
Whiskers meows
小结:
  • 继承允许子类复用父类的代码,避免了重复编写相同的属性和方法。
  • 通过继承,子类可以扩展或修改父类的功能,例如重写父类的方法来实现多态性。
  • 继承是实现代码复用和增强代码灵活性的有效手段。

8-20 sdut-论述-面向对象-重载与重写

分数 5

作者 周雪芹

单位 山东理工大学

什么是方法的重载?什么是方法的重写? 可以举例说明。

方法的重载(Method Overloading)与方法的重写(Method Overriding)
1. 方法重载(Method Overloading)

方法重载指的是在同一个类中,可以定义多个方法名相同,但参数列表不同(参数类型不同、参数个数不同或两者同时不同)的方法。方法重载是静态多态的一种形式,即在编译时通过方法签名来确定调用哪个方法。

  • 重载规则

    • 方法名相同。
    • 参数列表不同(可以是参数个数不同或类型不同)。
    • 返回类型可以相同,也可以不同(不影响重载)。
  • 目的:通过方法重载,我们可以使用相同的方法名来执行不同的任务,增加代码的可读性和灵活性。
2. 方法重写(Method Overriding)

方法重写是指在子类中重新定义父类已经定义的方法,并且方法签名完全相同。方法重写发生在运行时,子类对象调用被重写的方法时,会执行子类的版本,而不是父类的版本。

  • 重写规则

    • 方法名相同。
    • 参数列表相同。
    • 返回类型相同或协变(子类返回类型可以是父类返回类型的子类)。
    • 子类的方法访问权限不能比父类更严格(例如,父类是 public,子类不能是 private)。
  • 目的:通过方法重写,子类可以修改或扩展父类的方法实现,达到定制化行为的目的。
举例说明:
// 父类:Animal
class Animal {
    // 方法重写:父类定义的speak方法
    public void speak() {
        System.out.println("Animal makes a sound");
    }
}

// 子类:Dog,继承自Animal
class Dog extends Animal {
    // 方法重写:子类重写父类的speak方法
    @Override
    public void speak() {
        System.out.println("Dog barks");
    }

    // 方法重载:同名但参数不同
    public void speak(int times) {
        System.out.println("Dog barks " + times + " times");
    }
}

// 主类
public class Main {
    public static void main(String[] args) {
        // 方法重载的使用
        Dog dog = new Dog();
        dog.speak();  // 调用父类的重写方法,输出: Dog barks
        dog.speak(3); // 调用重载方法,输出: Dog barks 3 times

        // 方法重写的使用
        Animal animal = new Dog(); // 多态:父类引用指向子类对象
        animal.speak();  // 输出: Dog barks,因为方法被重写
    }
}
代码解析:
1. 方法重载
  • Dog 类中,定义了两个 speak() 方法:

    • 一个是无参的方法 speak(),这是对 Animal 类中 speak() 方法的重写。
    • 另一个是带参数 speak(int times) 的方法,这是对 speak() 方法的重载,增加了一个参数 times,表示狗叫的次数。
  • 方法重载的目的:通过方法名相同但参数不同,提供多种不同的功能(例如,调用不带参数的 speak() 输出 "Dog barks",调用带参数的 speak(int times) 输出 "Dog barks 3 times")。
2. 方法重写
  • Dog 类中,speak() 方法重写了 Animal 类的 speak() 方法,使得调用 Dog 类的 speak() 方法时,输出的是 "Dog barks"。
  • 方法重写的目的:通过继承和重写,子类 Dog 定义了不同于父类 Animal 的行为。即使父类引用指向子类对象,调用 speak() 方法时,依然执行子类 Dog 中的版本(多态特性)。
输出结果:
Dog barks
Dog barks 3 times
Dog barks
总结:
  • 方法重载(Method Overloading)

    • 同一个方法名,在同一个类中,参数不同(数量或类型),用于提供不同的实现。
    • 发生在编译时。
    • 目的是增强代码的灵活性,使用相同的方法名完成不同的任务。
  • 方法重写(Method Overriding)

    • 子类重新实现父类的已定义方法,方法签名完全相同,用于改变或扩展父类的行为。
    • 发生在运行时。
    • 目的是子类定制父类的行为,从而实现多态。

    8-21 sdut-论述-面向对象-抽象类与接口-接口的好处

    分数 5

    作者 周雪芹

    单位 山东理工大学

    描述抽象类和接口的主要区别,并解释为什么有时会优先选择接口而不是抽象类。

    抽象类和接口的主要区别:

    在 Java 中,抽象类和接口都是用来定义抽象方法的工具,它们都可以被用来强制子类(或实现类)实现某些方法。但它们之间有一些关键的区别:

    特性抽象类(Abstract Class)接口(Interface)
    定义方式使用 abstract 关键字定义类使用 interface 关键字定义接口
    构造方法可以有构造方法不能有构造方法
    成员变量可以有实例变量、静态变量,可以有默认值,也可以是 final 类型只能有 public static final 常量(隐式定义为常量)
    方法可以有抽象方法,也可以有具体方法(带实现的非抽象方法)默认方法为抽象方法,但 Java 8 之后可以有 defaultstatic 方法(有实现)
    继承一个类只能继承一个抽象类(单继承)一个类可以实现多个接口(多实现)
    访问修饰符可以有各种访问修饰符(privateprotectedpublic 等)接口中的方法默认是 public,不能有 privateprotected
    实现与继承extends 关键字继承implements 关键字实现
    多态性通过继承实现代码重用,通常用于共享行为用于定义行为规范,允许不同类间共享接口定义但实现不同的行为
    1. 抽象类的特点
    • 抽象类可以包含具体方法(有方法实现)和抽象方法(没有方法实现)。
    • 抽象类可以有成员变量、构造方法,可以用来实现默认的行为或是代码重用。
    • 子类可以继承一个抽象类,并实现或重写抽象方法,但只能继承一个抽象类。
    • 抽象类更倾向于表示“is-a”关系,即“是一个”的关系。
    2. 接口的特点
    • 接口中的所有方法默认都是抽象的,但从 Java 8 开始,接口也可以有默认方法(default)和静态方法(static),这些方法可以有实现。
    • 接口不能有成员变量,所有的变量默认为 public static final
    • 接口更倾向于定义行为的规范,允许多重实现,适用于“can-do”关系(例如“能做某事”)。
    • 一个类可以实现多个接口,从而获得多个接口的行为特征。
    为什么有时会优先选择接口而不是抽象类?
    1. 多重继承

      • Java 不支持类的多重继承,但支持接口的多重实现。一个类可以实现多个接口,因此接口提供了比抽象类更灵活的继承方式。
      • 如果希望一个类能具备多种能力或特性,接口是更合适的选择,因为它可以从多个接口中继承方法,而抽象类则只能继承一个类。
    2. 定义行为规范

      • 接口通常用于定义一种规范或契约,强制类实现某些行为。例如,SerializableCloneable 等接口,它们并不需要提供任何具体的实现,只定义行为的标准。
      • 如果只需要让类具备某种能力或实现某个协议,接口通常更合适。
    3. 解耦

      • 接口有助于解耦代码,使得类之间的关系更加松散。接口提供了一种规范,而不关心实现细节。通过接口,我们可以将实现与接口的定义分开,增强了代码的灵活性和可维护性。
      • 如果类之间的协作不依赖于具体的实现,而只是依赖于行为的定义,使用接口可以使得代码更具扩展性和灵活性。
    4. 灵活性

      • 接口本质上是行为的声明,任何类都可以通过实现接口来获得这些行为,无论类之间是否存在继承关系。
      • 在设计复杂的系统时,接口通常用于扩展功能和模块化设计,而抽象类更适合于实现共享行为和代码复用。
    例子:选择接口
    // 定义接口:可飞行的行为
    interface Flyable {
        void fly();
    }
    
    // 定义接口:可游泳的行为
    interface Swimmable {
        void swim();
    }
    
    // 鸟类实现了Flyable接口
    class Bird implements Flyable {
        public void fly() {
            System.out.println("Bird is flying");
        }
    }
    
    // 鱼类实现了Swimmable接口
    class Fish implements Swimmable {
        public void swim() {
            System.out.println("Fish is swimming");
        }
    }
    
    // 鲸鱼实现了Flyable和Swimmable接口
    class Whale implements Flyable, Swimmable {
        public void fly() {
            System.out.println("Whale is flying");
        }
    
        public void swim() {
            System.out.println("Whale is swimming");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Flyable bird = new Bird();
            Swimmable fish = new Fish();
            Whale whale = new Whale();
    
            bird.fly();
            fish.swim();
            whale.fly();
            whale.swim();
        }
    }
    代码解释:
    • 通过接口 FlyableSwimmable,我们可以让不同的类实现多个行为,即使它们没有共同的继承关系(BirdFish 可以通过实现不同的接口,Whale 可以实现多个接口)。
    • 如果使用抽象类的话,Whale 就只能继承一个父类,因此接口提供了更大的灵活性和更好的扩展性。
    总结:
    • 抽象类用于表示共享的行为和代码复用,适用于有共性和父子类关系的情况。
    • 接口用于定义行为规范,支持多重继承,适用于需要多重能力或功能的场景,并解耦代码。
    • 如果只需要定义行为规范或使多个类具备某种能力,优先选择接口;如果有共享代码需要重用且类之间有“is-a”关系,选择抽象类。

    8-22 sdut-论述-面向对象-抽象类与接口-抽象类的好处

    分数 5

    作者 周雪芹

    单位 山东理工大学

    在什么情况下使用抽象类比使用接口更合适?请提供一个应用场景的例子。

    使用抽象类比使用接口更合适的情况:
    1. 需要共享代码(行为复用)

      • 如果多个类有共同的行为,且这些行为可以在父类中实现,而不是在每个实现类中重复实现,使用抽象类更合适。
      • 抽象类可以包含非抽象的方法,这些方法可以直接被子类继承和使用,避免了代码重复。
    2. 类之间有“is-a”关系

      • 当多个类之间存在继承关系时,通常使用抽象类表示它们的共同父类,体现“是一个”的关系。
    3. 限制继承的数量

      • 如果你希望控制类的继承结构并只允许继承一个类,那么使用抽象类更合适,因为 Java 不支持多重继承。
    示例:使用抽象类

    假设我们有一个图形库,表示不同形状的图形。每种形状都有共同的功能,例如计算面积和周长,这些功能可以在抽象类中实现。

    // 抽象类 Shape
    abstract class Shape {
        // 抽象方法:每个形状都有一个计算面积的功能
        abstract double area();
    
        // 共有方法:计算周长
        public double perimeter() {
            return 0;  // 默认返回值
        }
    }
    
    // 具体类:圆形
    class Circle extends Shape {
        double radius;
    
        public Circle(double radius) {
            this.radius = radius;
        }
    
        @Override
        double area() {
            return Math.PI * radius * radius;  // 圆的面积
        }
    
        @Override
        public double perimeter() {
            return 2 * Math.PI * radius;  // 圆的周长
        }
    }
    
    // 具体类:矩形
    class Rectangle extends Shape {
        double length, width;
    
        public Rectangle(double length, double width) {
            this.length = length;
            this.width = width;
        }
    
        @Override
        double area() {
            return length * width;  // 矩形的面积
        }
    
        @Override
        public double perimeter() {
            return 2 * (length + width);  // 矩形的周长
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Shape circle = new Circle(5);
            Shape rectangle = new Rectangle(4, 6);
    
            System.out.println("Circle area: " + circle.area());
            System.out.println("Circle perimeter: " + circle.perimeter());
    
            System.out.println("Rectangle area: " + rectangle.area());
            System.out.println("Rectangle perimeter: " + rectangle.perimeter());
        }
    }
    代码解释:
    • Shape:抽象类,包含一个抽象方法 area(),每个形状类都需要实现该方法;此外,提供了一个已经实现的 perimeter() 方法,所有子类都可以直接继承和使用该方法。
    • CircleRectangle:具体的子类,继承了 Shape 类,并实现了 area() 方法,同时也可以继承和重用 perimeter() 方法。
    为什么选择抽象类?
    • 共享代码perimeter() 方法在 Shape 类中实现,避免了在每个具体的形状类中重复实现相同的逻辑。
    • 行为复用:如果未来有更多形状(例如正方形、三角形等),可以直接继承 Shape 类并复用 perimeter() 方法,只需实现 area() 方法。
    总结:
    • 抽象类适用于需要在多个子类之间共享实现的场景,避免代码重复,增强代码复用性。
    • 接口适用于不关心共享实现而是关注行为的场景,例如多个类可以实现同一个接口,提供不同的实现。

    8-23 sdut-论述-面向对象-抽象类与接口适用

    分数 5

    作者 周雪芹

    单位 山东理工大学

    比较抽象类和接口的不同之处,包括它们的定义方式、实现方式以及应用场景。举例说明何时选择抽象类,何时选择接口。

    抽象类与接口的比较
    1. 定义方式
    • 抽象类:使用 abstract 关键字定义,可以包含抽象方法(没有方法体)和具体方法(有方法体)。
    • 接口:使用 interface 关键字定义,所有方法默认都是抽象的,且不能包含具体的实现(Java 8 以后可以有默认方法和静态方法,但不能定义实例方法)。
    2. 实现方式
    • 抽象类:

      • 子类使用 extends 关键字继承抽象类。
      • 子类必须实现所有抽象方法,除非子类本身也是抽象类。
      • 可以继承一个抽象类(Java 不支持多重继承)。
    • 接口:

      • 类使用 implements 关键字实现接口。
      • 类可以实现多个接口,这支持多重实现。
      • 可以使用 default 关键字为接口中的方法提供默认实现(Java 8 以后)。
    3. 成员变量
    • 抽象类:

      • 可以有实例变量、构造方法、静态变量、常量等。
      • 实例变量可以有不同的访问修饰符(如 privateprotected)。
    • 接口:

      • 只能定义 public static final 常量(即常量字段),不能定义实例变量。
      • 不能有构造方法。
    4. 应用场景
    • 抽象类:

      • 用于表示具有共同基础行为的类的父类,强调代码复用和共享实现。
      • 当不同的类之间存在“is-a”关系时,使用抽象类。抽象类适合用于代码复用和实现共享行为。
    • 接口:

      • 用于定义行为规范,强调类之间的行为契约,而不关心具体的实现。
      • 当不同的类之间并没有直接的继承关系,但希望共享某种行为时,使用接口。接口适合定义多种不同类可能需要遵循的规范或能力。
    主要区别总结
    特性抽象类接口
    定义方式使用 abstract 关键字定义使用 interface 关键字定义
    构造方法可以有构造方法不能有构造方法
    成员变量可以有实例变量、静态变量、常量只能有常量(public static final
    方法实现可以有抽象方法,也可以有具体方法(实现)只能包含抽象方法(Java 8 以后可以有默认方法)
    继承/实现只能继承一个类可以实现多个接口
    访问修饰符可以使用各种访问修饰符(privateprotectedpublic等)所有方法默认为 public
    多态性支持继承中的代码复用和多态支持类实现多重接口中的多态
    应用场景用于共享行为、代码复用、父子类关系用于定义行为规范、没有继承关系的类共享行为
    何时选择抽象类,何时选择接口
    选择抽象类
    • 当类之间有共性行为,并且希望子类共享某些实现时。例如,你可能希望在父类中实现某些默认行为,让所有子类都可以复用。
    • 当你希望限制类只能继承一个父类时。Java 不支持多重继承,因此如果你希望多个类共享某些方法,可以通过抽象类来实现。

    应用场景:例如,动物类的继承结构。

    abstract class Animal {
        abstract void sound();
        
        public void eat() {
            System.out.println("Eating food...");
        }
    }
    
    class Dog extends Animal {
        @Override
        void sound() {
            System.out.println("Barking");
        }
    }
    
    class Cat extends Animal {
        @Override
        void sound() {
            System.out.println("Meowing");
        }
    }
    • Animal 类提供了共同的行为 eat(),但 sound() 方法是抽象的,子类必须实现。
    选择接口
    • 当类之间没有继承关系,但需要共享某些行为时。接口适合定义“能力”或“行为”,类可以选择实现它们,而不需要在类之间建立继承关系。
    • 当需要实现多重继承时,即一个类需要具备多个功能,接口可以帮助实现这一目标。

    应用场景:例如,飞行能力和游泳能力。

    interface Flyable {
        void fly();
    }
    
    interface Swimmable {
        void swim();
    }
    
    class Bird implements Flyable {
        @Override
        public void fly() {
            System.out.println("Bird is flying");
        }
    }
    
    class Fish implements Swimmable {
        @Override
        public void swim() {
            System.out.println("Fish is swimming");
        }
    }
    
    class Whale implements Flyable, Swimmable {
        @Override
        public void fly() {
            System.out.println("Whale is flying");
        }
        
        @Override
        public void swim() {
            System.out.println("Whale is swimming");
        }
    }
    • FlyableSwimmable 接口定义了飞行和游泳的行为,不同的类(Bird, Fish, Whale)根据其特性实现这些接口。
    总结:
    • 抽象类:适用于具有共享行为和代码复用的场景,通常用于具有“is-a”关系的类之间。
    • 接口:适用于需要定义行为规范或多重继承的场景,通常用于具有“can-do”关系的类之间。

    在实际开发中,如果类之间的关系是“继承”和共享行为的,使用抽象类;如果是“能力”或“行为”的共享,且需要多重实现时,选择接口。


    8-24 sdut-论述-常用类-包装类

    分数 5

    作者 周雪芹

    单位 山东理工大学

    如何在Java中将基本数据类型转换为对应的包装类对象?请提供一个示例;如何在Java中将对应的包装类对象转换为基本数据类型?请提供一个示例。

    1. 将基本数据类型转换为对应的包装类对象(自动装箱)

    Java 会自动将基本数据类型转换为对应的包装类对象,这个过程称为 自动装箱

    示例:
    public class Main {
        public static void main(String[] args) {
            int num = 10;
            Integer obj = num;  // 自动装箱,int 转换为 Integer
            System.out.println(obj);
        }
    }
    2. 将包装类对象转换为基本数据类型(自动拆箱)

    Java 会自动将包装类对象转换为对应的基本数据类型,这个过程称为 自动拆箱

    示例:
    public class Main {
        public static void main(String[] args) {
            Integer obj = 10;
            int num = obj;  // 自动拆箱,Integer 转换为 int
            System.out.println(num);
        }
    }
    总结:
    • 自动装箱:基本数据类型 → 对应包装类对象。
    • 自动拆箱:包装类对象 → 对应基本数据类型。

    自动装箱和自动拆箱是 Java 提供的隐式转换,可以简化代码,不需要显式调用构造函数或方法进行转换。


    8-25 sdut-论述-数据类型-自动转换与强转

    分数 5

    作者 周雪芹

    单位 山东理工大学

    解释自动类型转换和强制类型转换的区别,并给出一个示例代码,演示如何在Java中进行这两种类型的转换。

    1. 自动类型转换(隐式转换)

    自动类型转换发生在 兼容类型之间,并且目标类型的范围更大。Java 会自动进行类型转换,无需显式转换。

    • 条件:目标类型能够容纳源类型的值(通常是从小范围到大范围的类型,如 int 转为 long)。
    2. 强制类型转换(显式转换)

    强制类型转换需要使用 强制类型转换运算符 (),通常发生在 不兼容类型之间,或者当数据可能丢失时。

    • 条件:源类型的范围超出了目标类型的范围,或者不同类型之间需要显式转换。
    示例代码:
    自动类型转换(隐式转换):
    public class Main {
        public static void main(String[] args) {
            int num = 100;
            long bigNum = num;  // 自动类型转换,int 转为 long
            System.out.println(bigNum);
        }
    }
    强制类型转换(显式转换):
    public class Main {
        public static void main(String[] args) {
            double decimal = 9.78;
            int num = (int) decimal;  // 强制类型转换,double 转为 int,丢失小数部分
            System.out.println(num);
        }
    }
    总结:
    • 自动类型转换:发生在兼容类型之间,目标类型更大。
    • 强制类型转换:需要显式指定,通常发生在不兼容类型之间或者类型转换可能丢失数据时。

    8-26 sdut-论述-常用类-字符串与其他类型互转

    分数 5

    作者 周雪芹

    单位 山东理工大学

    举例说明字符串类如何与基本数据类型、字符串缓冲区类、日期类之间相互转换。

    1. 字符串与基本数据类型之间的转换
    字符串 → 基本数据类型

    使用包装类的 parse 方法进行转换。

    public class Main {
        public static void main(String[] args) {
            String str = "123";
            int num = Integer.parseInt(str);  // 字符串转为 int
            System.out.println(num);
        }
    }
    基本数据类型 → 字符串

    使用 String.valueOf() 或直接连接字符串。

    public class Main {
        public static void main(String[] args) {
            int num = 123;
            String str = String.valueOf(num);  // int 转为字符串
            System.out.println(str);
        }
    }
    2. 字符串与字符串缓冲区(StringBuffer)之间的转换
    字符串 → StringBuffer

    使用 StringBuffer 的构造函数。

    public class Main {
        public static void main(String[] args) {
            String str = "Hello";
            StringBuffer sb = new StringBuffer(str);  // 字符串转为 StringBuffer
            System.out.println(sb);
        }
    }
    StringBuffer → 字符串

    使用 toString() 方法。

    public class Main {
        public static void main(String[] args) {
            StringBuffer sb = new StringBuffer("Hello");
            String str = sb.toString();  // StringBuffer 转为字符串
            System.out.println(str);
        }
    }
    3. 字符串与日期类(Date)之间的转换
    字符串 → Date

    使用 SimpleDateFormat 进行解析。

    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class Main {
        public static void main(String[] args) throws Exception {
            String str = "2024-12-18";
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date date = sdf.parse(str);  // 字符串转为 Date
            System.out.println(date);
        }
    }
    Date → 字符串

    使用 SimpleDateFormat 格式化。

    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class Main {
        public static void main(String[] args) {
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String str = sdf.format(date);  // Date 转为字符串
            System.out.println(str);
        }
    }
    总结:
    • 字符串 ↔ 基本数据类型:使用包装类的 parsevalueOf 方法。
    • 字符串 ↔ StringBuffer:直接使用构造方法和 toString()
    • 字符串 ↔ Date:使用 SimpleDateFormat 进行解析和格式化。

    8-27 sdut-论述-集合-List、Set和Map集合特点

    分数 5

    作者 周雪芹

    单位 山东理工大学

    分析并比较List、Set和Map三种集合的特点。请分别列举它们各自适用的场景,并给出具体的使用示例。

    1. List 集合
    特点:
    • 有序:元素按照插入顺序排列。
    • 允许重复:可以包含重复元素。
    • 可通过索引访问:可以通过索引(下标)访问元素。
    适用场景:
    • 需要按顺序存储元素且允许重复的情况,如存储用户的历史记录。
    示例:
    import java.util.ArrayList;
    import java.util.List;
    
    public class Main {
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("apple");
            list.add("banana");
            list.add("apple");  // 允许重复
            System.out.println(list);  // 输出:[apple, banana, apple]
        }
    }
    2. Set 集合
    特点:
    • 无序:元素不保证按插入顺序排列。
    • 不允许重复:集合中的元素是唯一的。
    适用场景:
    • 需要保证元素唯一性且不关心顺序,如存储用户的唯一 ID。
    示例:
    import java.util.HashSet;
    import java.util.Set;
    
    public class Main {
        public static void main(String[] args) {
            Set<String> set = new HashSet<>();
            set.add("apple");
            set.add("banana");
            set.add("apple");  // 不允许重复
            System.out.println(set);  // 输出:[apple, banana]
        }
    }
    3. Map 集合
    特点:
    • 键值对:存储的是键值对(key-value)形式的数据。
    • 键唯一:每个键对应一个唯一的值,但值可以重复。
    • 无序:不保证顺序(对于 HashMap 来说),但 TreeMap 会按键排序。
    适用场景:
    • 需要通过键快速查找对应的值,如存储用户信息(键:用户名,值:用户数据)。
    示例:
    import java.util.HashMap;
    import java.util.Map;
    
    public class Main {
        public static void main(String[] args) {
            Map<String, Integer> map = new HashMap<>();
            map.put("apple", 5);
            map.put("banana", 3);
            map.put("apple", 10);  // 键唯一,覆盖值
            System.out.println(map);  // 输出:{apple=10, banana=3}
        }
    }
    总结
    • List:有序、允许重复,适用于需要保持顺序的场景。
    • Set:无序、不允许重复,适用于需要唯一性但不关心顺序的场景。
    • Map:键值对存储,适用于快速查找键对应的值的场景。

    8-28 sdut-论述-综合 Java语言与C语言之比较

    分数 10

    作者 周雪芹

    单位 山东理工大学

    1、Java语言与C语言在基础语法上相比较,有哪些区别(或者各有哪些特点)?(6分,至少列举3个);
    2、你是如何理解面向对象编程的? 它与面向过程的编程思想相比,有什么优势?(4分,至少有2个分析点)

    1. Java与C语言基础语法的区别
    1. 内存管理
    • C语言:程序员手动管理内存(使用 mallocfree)。
    • Java:自动垃圾回收机制,内存管理由JVM自动处理。
    2. 数据类型
    • C语言:支持指针,可以直接操作内存地址。
    • Java:没有指针,所有对象通过引用进行操作,安全性更高。
    3. 面向对象
    • C语言:不支持面向对象,只有过程式编程。
    • Java:是纯粹的面向对象编程语言,所有代码都必须在类中。
    2. 面向对象编程的理解与优势
    理解:

    面向对象编程(OOP)通过将数据和操作数据的函数封装在对象中,强调封装、继承和多态,能够更好地模拟现实世界的事物及行为。

    优势:
    1. 代码重用:通过继承,子类可以复用父类的代码,减少重复。
    2. 易于维护和扩展:通过封装,修改一个类的实现不会影响到其他类,系统更易于扩展和维护。

# Final