JAVA网络编程案例教程(JAVA网络编程)
Java网络编程,高手进
package org.kevin.ftp;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class DLFrame extends JFrame
{
private JPanel contentPane;
private JTextField textField1=new JTextField();
private JTextField textField2=new JTextField();
private JButton button=new JButton();
private JLabel label1=new JLabel();
private JLabel label2=new JLabel();
private JTextArea textArea=new JTextArea();
private String dlURL=new String();
private String saveFileAs=new String();
public DLFrame()
{
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try
{
toInit();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
private void toInit() throws Exception
{
contentPane=(JPanel) this.getContentPane();
contentPane.setLayout(null);
this.setSize(new Dimension(380,320));
this.setLocation(100,100);
this.setTitle("多线程下载");
textField1.setBounds(new Rectangle(150,200,200,20));
textField1.setText("");
textField2.setBounds(new Rectangle(150,240,120,20));
textField2.setText("d:\\try.rar");
label1.setBounds(new Rectangle(20,200,120,20));
label1.setText("下载的目标文件为: ");
label2.setBounds(new Rectangle(20,240,120,20));
label2.setText("下载的文件另存为: ");
button.setBounds(new Rectangle(280,240,60,20));
button.setText("下载");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
button_actionPerformed(e);
}
});
JScrollPane scrollPane = new JScrollPane(textArea);
//textArea.setBounds(new Rectangle(20,20,330,170));
scrollPane.setBounds(new Rectangle(20,20,330,170));
textArea.setEditable(false);
contentPane.add(textField1,null);
contentPane.add(textField2,null);
contentPane.add(label1,null);
contentPane.add(label2,null);
contentPane.add(button,null);
//contentPane.add(textArea,null);
contentPane.add(scrollPane,null);
dlURL=textField1.getText();
saveFileAs=textField2.getText();
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void button_actionPerformed(ActionEvent e)
{
//启动分析下载文件的进程
dlURL=textField1.getText();
saveFileAs=textField2.getText();
if(dlURL.compareTo("")==0 saveFileAs.compareTo("")==0)
{
textArea.setText("请输入要下载的文件和保存文件完整地址");
}
else
{
try
{
DownFile downFile=new DownFile(dlURL,saveFileAs,5,textArea);
downFile.start();
textArea.append("主线程启动、、、");
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
public static void main(String[] args)
{
new DLFrame().setVisible(true);//要实例化一个对象的时候才会去执行构造方法
}
}
package org.kevin.ftp;
import javax.swing.JTextArea;
import java.net.*;
import java.io.*;
public class DownFile extends Thread //分析要下载的文件并启动下载进程
{
String dlURL;
String saveFileAs;
int nthread;
String info=new String();
JTextArea textArea=new JTextArea();
long[] position;
long[] startPos;
long[] endPos;
DownFileSplitter[] downFileSplitter; //子线程对象
long fileLength;
boolean stop=false;
//DataOutputStream output;
public DownFile(String sURL,String saveFileAs,int nthread,JTextArea textArea) throws IOException
{
this.dlURL=sURL;
this.saveFileAs=saveFileAs;
this.nthread=nthread;
this.textArea=textArea;
startPos=new long[nthread];
endPos=new long[nthread];
}
public void run()
{
info="目标文件: "+dlURL;
System.out.println(info);
textArea.append("\n"+info);
info="\n 线程总数: "+nthread;
System.out.println(info);
textArea.append("\n"+info);
try
{
fileLength=getFileSize();
if (fileLength==-1)
{
System.err.println("不可知的文件长度");
textArea.append("\n 不可知的文件长度!请重试!!");
}
else
{
if(fileLength==-2)
{
System.err.println("文件无法获取!");
textArea.append("\n 文件无法获取!请重试!!");
}
else
{
for(int i=0;istartPos.length;i++){
startPos[i]=(long) (i*(fileLength/startPos.length));
}
for(int i=0;iendPos.length-1;i++)
endPos[i]=startPos[i+1];
endPos[endPos.length-1]=fileLength;
for(int i=0;istartPos.length;i++)
{
info="线程:"+i+"下载范围:"+startPos[i]+"--"+endPos[i];
System.out.println(info);
textArea.append("\n"+info);
}
downFileSplitter=new DownFileSplitter[startPos.length];
//启动一组子线程
for(int i=0;istartPos.length;i++)
{
downFileSplitter[i]=new DownFileSplitter(dlURL,saveFileAs,
startPos[i],endPos[i], i,textArea);
info="线程 "+i+"启动";
textArea.append("\n"+info);
downFileSplitter[i].start();
System.out.println(info);
}
boolean breakWhile=true;
while(breakWhile)
{
Thread.sleep(500);
breakWhile=false;
for(int i=0;idownFileSplitter.length;i++)
{
if(!downFileSplitter[i].done)
{
breakWhile=true;
break;
}
}
}
System.out.println("文件传输结束!");//文件传输结束
textArea.append("\n 文件传输结束!");
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
public long getFileSize()
{
int fileLength=-1;
try
{
URL url=new URL(dlURL);
HttpURLConnection httpConnection=(HttpURLConnection) (url.openConnection());
int responseCode=httpConnection.getResponseCode();
if(responseCode=400)
{
System.out.println("Web服务器响应错误");
return -2;//Web服务器响应错误
}
String sHeader;
for(int i=1;;i++)//查找标识文件长度的文件头,获取文件长度
{
sHeader=httpConnection.getHeaderFieldKey(i);
if(sHeader!=null)
{
if(sHeader.equals("Content-Length"))
{
fileLength=Integer.parseInt(httpConnection.getHeaderField(sHeader));
break;
}
}
else
{
break;
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
return fileLength;
}
}
package org.kevin.ftp;
import javax.swing.JTextArea;
import java.net.*;
import java.io.*;
public class DownFileSplitter extends Thread
{
String dlURL;
long startPos;
long endPos;
int threadID;
JTextArea textArea=new JTextArea();
boolean done=false;
boolean stop=false;
RandomAccessFile file;
public DownFileSplitter(String dlURL,String saveAs,long nStart,long nEnd,
int id,JTextArea textArea) throws IOException
{
this.dlURL=dlURL;
this.startPos=nStart;
this.endPos=nEnd;
this.threadID=id;
this.textArea=textArea;
file=new RandomAccessFile(saveAs,"rw");
file.seek(startPos);
}
public void run()
{
try
{
URL url=new URL(dlURL);
HttpURLConnection httpConnection=(HttpURLConnection)url.openConnection();
String sProperty="bytes="+startPos+"-";
httpConnection.setRequestProperty("RANGE",sProperty);
System.out.println("线程"+threadID+"下载文件、、、请等待");
textArea.append("\n 线程"+threadID+"下载文件、、、请等待");
InputStream input=httpConnection.getInputStream();
byte[] buf=new byte[1024];
int offset;
offset=(int)endPos-(int)startPos;
if(offset1024)
offset=1024;
while(input.read(buf,0,offset)0 startPosendPos)
{
offset = (int) endPos - (int) startPos;
if (offset 1024)
offset = 1024;
System.out.println("threadID: "+threadID+" started: "+startPos+" offset: "+offset);
file.write(buf,0,offset);
startPos+=offset;
}
System.out.println("线程"+threadID+"下载完毕!!");
textArea.append("\n 线程"+threadID+"下载完毕!!");
file.close();
input.close();
done=true;
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
JAVA基础入门教程 -
第一阶段:Java语言基础
★ Java语言基础
1、面向对象思维JAVASE
2、(类加载机制与反射,annotation,泛型,网络编程,多线程,IO,异常处理,常用API,面向对象,JAVA编程基础)
3、Java8新特性
JAVA战狼班第二阶段:数据库
★ 数据库
1、Oracle(SQL语句、SQL语句原理、SQL语句优化、表、视图
2、序列、索引、Oracle数据字典、Oracle 数据库PL/SQL开发
3、数据库设计原则、 MySQL 、 JDBC
第三阶段:Web基础
★ Web基础
1、HTML5(H5)基本文档结构、链接、列表、表格、表单;
2、CSS 基础语法、盒子模型、浮动布局、定位;
3、JavaScript语言基础、DOM 编程、事件模型等),JQuery,AJAX框架,XML,BootStrap组件
第四阶段:Java Web技术和主流框架
★ Java Web技术和主流框架
1、JSPServlet、struts2,hibernate4,spring4,JPA,maven
2、SpringData,SpringMVC,MyBatis,SpringSecurity,shiro,Nginx
第五阶段:Linux
★ Linux
1、Linux安装、熟悉Linux的基础命令、vi编辑器的使用、awk和sed命令使用、用户和组
2、文件及目录权限管理、使用ACL进行高级访问控制、网络配置和软件包安装、启动流程和服务管理
3、系统监控和日志管理、进程管理和计划任务、ssh远程登录、shell基础和shell脚本。
第六阶段:大数据技术(Hadoop和Spark)
★ 大数据技术(Hadoop和Spark)
1、Hadoop (Hadoop基础和环境搭建,HDFS体系结构,MapReduce;Hadoop的集群模式、HDFS联盟,利用ZooKeeper来实现Hadoop集群的HA(高可用性)功能
2、Yarn的任务调度机制,Apache Hive,Pig数据处理,集成Hadoop和Sqoop
3、Flume以及Apache Kafka来实现数据的交换,安装部署HBase,Storm)
4、Scala 语言(Scala环境搭建、Scala基础语法、模式匹配、重载与构造器、Map与reduce、元组、继承、StringContext,Option Some None,Tuple;集合方法和运算,future 对象同步处理和异步处理返回结果)
5、Spark(Spark搭建,Spark-shell 的使用,Spark-submit 提交应用, Spark的内核设计和实现,并对内核中的实现架构、运行原理进行详细的讲解;Spark生态体系中的各个组件,包括:Spark Core,Shark,Spark SQL和Spark Streaming等等)
第七阶段:项目
★ 项目
1、China-UCSP 项目 SSM(Spring+SpringMVC+MyBatis)
2、用户关系管理系统 S2SH+Maven+Nodejs+MySQL技术实战开发
3、电子商务交易平台 S2SH+Maven+Shiro+Oracle
java网络编程
我也才写了一个,我不想看代码
你可以把发送和接受信息都写在一个死循环里
客户端:1.发送 2.接受
服务端:1.接受 2.发送
这个接收我第一个代码用的BufferedRedaer br = new BufferedReader(new InputStreamReader(in))
br.readline();//这个是阻塞式的,不接受到消息它是不会往后执行的,更ServerSocket里的accept方法一样的
客户端发送了就会卡在接受那,而服务器这边就会收到,服务器就会执行回复的输入,回复输入后,客户端这边就能接收到,就这样循环
第一次写的时候用的是PrintWriter进行发送,用inputstream的read方法读出来会不对
printwriter的write方法就是写入缓存,要用到String的getbytes方法,注意要使用flush方法清空缓存
读取用的是BufferedReader
一个最简单的java网络编程
你好:Socket s = new Socket("localhost", 6660);//14行
这个的话,你的没通, 去黑窗口输入 tenlet 127.0.0.1 6660;看看是否有结果输出,再就是你别用localhost了,换成实际的127.0.0.1的地址,
Java网络编程从入门到精通(18):Socket类的getter和setter方法(2)
二 用于获得和设置Socket选项的getter和setter方法
Socket选择可以指定Socket类发送和接受数据的方式 在JDK *** 有 个Socket选择可以设置 这 个选项都定义在 SocketOptions接口中 定义如下
????public?final?static?int?TCP_NODELAY?=? x ;??? public?final?static?int?SO_REUSEADDR?=? x ;??? public?final?static?int?SO_LINGER?=? x ;????public?final?static?int?SO_TIMEOUT?=? x ;????public?final?static?int?SO_SNDBUF?=? x ;????public?final?static?int?SO_RCVBUF?=? x ;????public?final?static?int?SO_KEEPALIVE?=? x ;????public?final?static?int?SO_OOBINLINE?=? x ;
有趣的是 这 个选项除了第一个没在SO前缀外 其他 个选项都以SO作为前缀 其实这个SO就是Socket Option的缩写 因此 在Java中约定所有以SO为前缀的常量都表示Socket选项 当然 也有例外 如TCP_NODELAY 在Socket类中为每一个选项提供了一对get和set方法 分别用来获得和设置这些选项
TCP_NODELAY
public?boolean?getTcpNoDelay()?throws?SocketExceptionpublic?void?setTcpNoDelay(boolean?on)?throws?SocketException
在默认情况下 客户端向服务器发送数据时 会根据数据包的大小决定是否立即发送 当数据包中的数据很少时 如只有 个字节 而数据包的头却有几十个字节(IP头+TCP头)时 系统会在发送之前先将较小的包合并到软大的包后 一起将数据发送出去 在发送下一个数据包时 系统会等待服务器对前一个数据包的响应 当收到服务器的响应后 再发送下一个数据包 这就是所谓的Nagle算法 在默认情况下 Nagle算法是开启的
这种算法虽然可以有效地改善网络传输的效率 但对于网络速度比较慢 而且对实现性的要求比较高的情况下(如游戏 Telnet等) 使用这种方式传输数据会使得客户端有明显的停顿现象 因此 最好的解决方案就是需要Nagle算法时就使用它 不需要时就关闭它 而使用setTcpToDelay正好可以满足这个需求 当使用setTcpNoDelay(true)将Nagle算法关闭后 客户端每发送一次数据 无论数据包的大小都会将这些数据发送出去
? SO_REUSEADDR
public?boolean?getReuseAddress()?throws?SocketException???????????public?void?setReuseAddress(boolean?on)?throws?SocketException
通过这个选项 可以使多个Socket对象绑定在同一个端口上 其实这样做并没有多大意义 但当使用close方法关闭Socket连接后 Socket对象所绑定的端口并不一定马上释放 系统有时在Socket连接关闭才会再确认一下是否有因为延迟面未到达的数据包 这完全是在底层处理的 也就是说对用户是透明的 因此 在使用Socket类时完全不会感觉到
这种处理机制对于随机绑定端口的Socket对象没有什么影响 但对于绑定在固定端口的Socket对象就可能会抛出 Address already in use JVM_Bind 例外 因此 使用这个选项可以避免个例外的发生
package mynet;import? *;import?java io *;public?class Test{????public?static?void?main(String[]?args)????{????????Socket?socket ?=?new?Socket();????????Socket?socket ?=?new?Socket();????????try????????{????????????socket setReuseAddress(true);????????????socket bind(new?InetSocketAddress( ? ));????????????System out println( socket getReuseAddress(): ????????????????????+?socket getReuseAddress());????????????socket bind(new?InetSocketAddress( ? ));????????}????????catch?(Exception?e)????????{????????????System out println( error: ?+?e getMessage());????????????try????????????{????????????????socket setReuseAddress(true);????????????????socket bind(new?InetSocketAddress( ? ));????????????????System out println( socket getReuseAddress(): ????????????????????????+?socket getReuseAddress());????????????????System out println( 端口 第二次绑定成功! );????????????}????????????catch?(Exception?e )????????????{????????????????System out println(e getMessage());????????????}????????}????}}
上面的代码的运行结果如下
socket getReuseAddress():trueerror:Address?already?in?use:?JVM_Bindsocket getReuseAddress():true端口 第二次绑定成功!
使用SO_REUSEADDR选项时有两点需要注意
? 必须在调用bind方法之前使用setReuseAddress方法来打开SO_REUSEADDR选项 因此 要想使用SO_REUSEADDR选项 就不能通过Socket类的构造方法来绑定端口
? 必须将绑定同一个端口的所有的Socket对象的SO_REUSEADDR选项都打开才能起作用 如在例程 中 socket 和socket 都使用了setReuseAddress方法打开了各自的SO_REUSEADDR选项
? SO_LINGER
public?int?getSoLinger()?throws?SocketExceptionpublic?void?setSoLinger(boolean?on ?int?linger)?throws?SocketException
这个Socket选项可以影响close方法的行为 在默认情况下 当调用close方法后 将立即返回 如果这时仍然有未被送出的数据包 那么这些数据包将被丢弃 如果将linger参数设为一个正整数n时(n的值最大是 ) 在调用close方法后 将最多被阻塞n秒 在这n秒内 系统将尽量将未送出的数据包发送出去 如果超过了n秒 如果还有未发送的数据包 这些数据包将全部被丢弃 而close方法会立即返回 如果将linger设为 和关闭SO_LINGER选项的作用是一样的
如果底层的Socket实现不支持SO_LINGER都会抛出SocketException例外 当给linger参数传递负数值时 setSoLinger还会抛出一个IllegalArgumentException例外 可以通过getSoLinger方法得到延迟关闭的时间 如果返回 则表明SO_LINGER是关闭的 例如 下面的代码将延迟关闭的时间设为 分钟
if(socket getSoLinger()?==? )?socket setSoLinger(true ? );
? SO_TIMEOUT
public?int?getSoTimeout()?throws?SocketExceptionpublic?void?setSoTimeout(int?timeout)?throws?SocketException
这个Socket选项在前面已经讨论过 可以通过这个选项来设置读取数据超时 当输入流的read方法被阻塞时 如果设置timeout(timeout的单位是毫秒) 那么系统在等待了timeout毫秒后会抛出一个InterruptedIOException例外 在抛出例外后 输入流并未关闭 你可以继续通过read方法读取数据
如果将timeout设为 就意味着read将会无限等待下去 直到服务端程序关闭这个Socket 这也是timeout的默认值 如下面的语句将读取数据超时设为 秒
socket setSoTimeout( ?*? );
当底层的Socket实现不支持SO_TIMEOUT选项时 这两个方法将抛出SocketException例外 不能将timeout设为负数 否则setSoTimeout方法将抛出IllegalArgumentException例外
? SO_SNDBUF
public?int?getSendBufferSize()?throws?SocketExceptionpublic?void?setSendBufferSize(int?size)?throws?SocketException
在默认情况下 输出流的发送缓冲区是 个字节( K) 这个值是Java所建议的输出缓冲区的大小 如果这个默认值不能满足要求 可以用setSendBufferSize方法来重新设置缓冲区的大小 但最好不要将输出缓冲区设得太小 否则会导致传输数据过于频繁 从而降低网络传输的效率
如果底层的Socket实现不支持SO_SENDBUF选项 这两个方法将会抛出SocketException例外 必须将size设为正整数 否则setSendBufferedSize方法将抛出IllegalArgumentException例外
? SO_RCVBUF
public?int?getReceiveBufferSize()?throws?SocketExceptionpublic?void?setReceiveBufferSize(int?size)?throws?SocketException
在默认情况下 输入流的接收缓冲区是 个字节( K) 这个值是Java所建议的输入缓冲区的大小 如果这个默认值不能满足要求 可以用setReceiveBufferSize方法来重新设置缓冲区的大小 但最好不要将输入缓冲区设得太小 否则会导致传输数据过于频繁 从而降低网络传输的效率
如果底层的Socket实现不支持SO_RCVBUF选项 这两个方法将会抛出SocketException例外 必须将size设为正整数 否则setReceiveBufferSize方法将抛出IllegalArgumentException例外
? SO_KEEPALIVE
public?boolean?getKeepAlive()?throws?SocketExceptionpublic?void?setKeepAlive(boolean?on)?throws?SocketException
如果将这个Socket选项打开 客户端Socket每隔段的时间(大约两个小时)就会利用空闲的连接向服务器发送一个数据包 这个数据包并没有其它的作用 只是为了检测一下服务器是否仍处于活动状态 如果服务器未响应这个数据包 在大约 分钟后 客户端Socket再发送一个数据包 如果在 分钟内 服务器还没响应 那么客户端Socket将关闭 如果将Socket选项关闭 客户端Socket在服务器无效的情况下可能会长时间不会关闭 SO_KEEPALIVE选项在默认情况下是关闭的 可以使用如下的语句将这个SO_KEEPALIVE选项打开
socket setKeepAlive(true);
? SO_OOBINLINE
?public?boolean?getOOBInline()?throws?SocketException?public?void?setOOBInline(boolean?on)?throws?SocketException
如果这个Socket选项打开 可以通过Socket类的sendUrgentData方法向服务器发送一个单字节的数据 这个单字节数据并不经过输出缓冲区 而是立即发出 虽然在客户端并不是使用OutputStream向服务器发送数据 但在服务端程序中这个单字节的数据是和其它的普通数据混在一起的 因此 在服务端程序中并不知道由客户端发过来的数据是由OutputStream还是由sendUrgentData发过来的 下面是sendUrgentData方法的声明
public?void?sendUrgentData(int?data)?throws?IOException
虽然sendUrgentData的参数data是int类型 但只有这个int类型的低字节被发送 其它的三个字节被忽略 下面的代码演示了如何使用SO_OOBINLINE选项来发送单字节数据
package mynet;import? *;import?java io *;class Server{????public?static?void?main(String[]?args)?throws?Exception????{????????ServerSocket?serverSocket?=?new?ServerSocket( );????????System out println( 服务器已经启动 端口号 );????????while?(true)????????{????????????Socket?socket?=?serverSocket accept();????????????socket setOOBInline(true);????????????InputStream?in?=?socket getInputStream();????????????InputStreamReader?inReader?=?new?InputStreamReader(in);????????????BufferedReader?bReader?=?new?BufferedReader(inReader);????????????System out println(bReader readLine());????????????System out println(bReader readLine());????????????socket close();????????}????}}public?class Client{????public?static?void?main(String[]?args)?throws?Exception????{????????Socket?socket?=?new?Socket( ? );????????socket setOOBInline(true);????????OutputStream?out?=?socket getOutputStream();????????OutputStreamWriter?outWriter?=?new?OutputStreamWriter(out);????????outWriter write( );??????????????//?向服务器发送字符 C ????????outWriter write( hello?world\r\n );????????socket sendUrgentData( );????????//?向服务器发送字符 A ????????socket sendUrgentData( );????????//?向服务器发送字符 B ????????outWriter flush();????????socket sendUrgentData( );???????//?向服务器发送汉字 中 ????????socket sendUrgentData( );????????socket sendUrgentData( );???????//?向服务器发送汉字 国 ????????socket sendUrgentData( );????????socket close();????}}
由于运行上面的代码需要一个服务器类 因此 在加了一个类名为Server的服务器类 关于服务端套接字的使用方法将会在后面的文章中详细讨论 在类Server类中只使用了ServerSocket类的accept方法接收客户端的请求 并从客户端传来的数据中读取两行字符串 并显示在控制台上
测试
由于本例使用了 因Server和Client类必须在同一台机器上运行
运行Server
java?mynet Server
运行Client
java?mynet Client
在服务端控制台的输出结果
服务器已经启动 端口号 ABChello?world中国
在ClienT类中使用了sendUrgentData方法向服务器发送了字符 A ( )和 B ( ) 但发送 B 时实际发送的是 由于sendUrgentData只发送整型数的低字节 因此 实际发送的是 十进制整型 的二进制形式如图 所示
图 ? 十进制整型 的二进制形式
从图 可以看出 虽然 分布在了两个字节上 但它的低字节仍然是
在Client类中使用flush将缓冲区中的数据发送到服务器 我们可以从输出结果发现一个问题 在Client类中先后向服务器发送了 C hello world r n A B 而在服务端程序的控制台上显示的却是ABChello world 这种现象说明使用sendUrgentData方法发送数据后 系统会立即将这些数据发送出去 而使用write发送数据 必须要使用flush方法才会真正发送数据
在Client类中向服务器发送 中国 字符串 由于 中 是由 和 两个字节组成的 而 国 是由 和 两个字节组成的 因此 可分别发送这四个字节来传送 中国 字符串
lishixinzhi/Article/program/Java/hx/201311/26387
(一)Java多线程 (二)输入输出流 (三)Java网络编程 (四)Java数据库编程
(1)多线程我感觉你应该知道首先实现线程类的两个方法。一个是继承Thread类.另一个是实现Runnable接口.然后怎样启动一个线程类。还有就是实现的两种方法的区别。例如资源是不是能共享呀等等。
(2)对于输入输出流.你首先要明白任何输出流输入流都是继承自OutputStream InputStream 还有Writer Reader。说得简单一点所有字符流的祖先都是(Writer或者Reader)而所有字节流的祖先都是
(OutputStream 或者InputStream)其中你还要明白字符和字节的区别。最后以上所有的祖先都是抽象的。所以要实现都是通过多态来实现的。用父类的引用指用子类的实例。
(3)Java网络编程这个就不好说了。全得平时的理解加上网络课的学习
(4)java数据库编程这个比较重要。首先你得知道。常用的数据库有那些。然后怎样让java程序与数据库连接起来。一般采用都是thin(对于oracle)然后。你得记住那些很固定的格式。例如什么驱动的字符呀。还有就是url呀。等等各个数据库是不一样的。例如oralce你要加载驱动你得用Class.forName("oracle.jdbc.driver.OracleDriver");其中里面的那个格式每个数据库都不一样。最后你得知道怎样从数据库里面查询一个你想要的结果。然后怎样能过程序得到这个结果。这就是jdbc里提供的一些方法了。例如像什么ResulSet对象呀。等等。总之多多练习就能了解的。