2021-07-14

本文详细介绍了Java的基础知识,包括JDK、JRE、JVM的关系,以及Java中的数据类型、流程控制、输入输出、字符串操作和数组。深入探讨了JVM的工作原理,如类加载子系统、内存区域和垃圾回收机制。此外,还涵盖了多线程、网络编程、反射和注解等核心概念,为理解Java程序的运行提供了全面的视角。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Java

1.JDK、JRE、JVM

JDK:写java,包含JRE

JRE:运行java,包含JRE

JVM:java虚拟机

java程序——>字节码文件———>装载到 JVM 执行

2.基础知识

输入

import java.util.*;

Scanner input=new Scanner();

int x=input.nextInt();

input.next();//字符串

定义:
list<String> s = new ArrayList();
复制:
Link<String> a = copyList(s);
增加:
s.add("absc");


删除:
全删: s.clear();
指定位置:s.remove(index);
连续位置:s.removeRange(start,end);

获取元素:
s.get(index)
String[] a = s.toArray();

修改:
s.set(index,element);


搜索:
s.contains(element);
s.indexOf(element) //未出现返回-1
s.lastIndexOf(element)//最后一次出现的位置

是否为空:
s.isEmpty()

大小:
s.size()


HashMap
定义:
HashMap<Integer,String> s = new HashMap<Integer,String>();

添加
s.put(1,"234");

获取
s.get(2);//2是key值

删除
s.remove(3);//3是key值
s.clear();//删除所有

大小
s.size();

遍历:
获取key
for(Integer i : s.keySet()){
    Integer i = s.get(i);
}
获取value:
for(String i : s.values()){
    String v = i;
}

替换:
s.replace(key,oldvalue,newvalue);

[0,1,0,0,null,0,0,null,null,null,1,null,null,null,1]
[1,0,1,0,1,0,1]


List a=new ArrayList();

List c=new ArrayList();

访问b.get(index)

长度b.size();

字符转数字好像都不行所以还是减48或96吧

Integer.valueOf(i)

i是个String,

List a=new ArrayList();

字符串变小写、大写

String s = h.toLowerCase();

String s = h.toUpperCase();

函数前加static不用实例化就能使用,否则得实例化即创建一个对象。static对象存放在静态存储区。

import java.math.*;

Math.max(a,b);

Arrays.sort(b)将数组b排序

哈希表

HashMap a = new HashMap<>();

a.containsKey(keyname) 查看hash表中是否含有该keyname

a.get(keyname).add(value) a.get(keyname)因为得到了key对于的value,在本例中是个Arraylist

2.1注释

单行 //

多行 /*

​ 。。。

​ */

文档注释 /* *与 */之间

2.2数据类型
2.2.1基本类型

整数:byte short int long 1 2 4 8

由大到小强制转换。由小到大自动转换

前缀

二进制 :0b

八进制 :0

十六进制 :0x

long num=20L;

字符串 String 是一个类

字符 char 2个字节

一个汉字2个字节

最好完全使用浮点数进行比较

浮点数 float double 4 8

金额可用BigDecimal类

float num2=50.1f;

布尔 True False

符号运算

与&:相同为本身,不相同为较小的那个

或 |:相同为本身,不相同为较大的那个

异或^:相同为0,不同为1

非~:取反

2.2.2引用类型

接口

数组

2.3包机制

package pkg1.pkg2.pkg3…;

import package.packsge2… .classname;

3.流程控制

if while for else break continue

Scanner获取用户输入

//创建一个扫描器对象,用于接收键盘数据,yi
Scanner scanner = new Scanner(System.in);
//判断是否有输入
if(scanner.hasNext()){
    String str = scanner.next();
}
//next不能得到有空格的输入
if(scanner.hasNextLine()){
    String str = scanner.nextLine();
}
//nextline可以
scanner.close();

4.方法

4.1重载

参数个数、类型、顺序不同;

返回类型不同不能构成重载、

4.2可变参数

一个方法只能有一个,且放在最后

public class helloworld {
    public static void main(String[] args) {
        helloworld d=new helloworld();
        d.test(2,3,4);
    }
    public void test(int... i)//
    {
        System.out.println(i[0]);
        System.out.println(i[2]);
    }
}
4.3数组
int[] nums={1,2,3,4,5};
nums.length
nums.for
fori

5.对象

5.1封装

alt + insert 生成get/set

5.2继承

extends

ctrl+h

super

先构造父,再构造子

静态static方法与左边有关,非静态方法与右边实例化对象有关(重写)

A a=new B ()

A能调用自己的方法、共有的方法(未重写则自己,重写则子类的)

子转父类,自动转,父转子类,强制转换

6常用类

6.1String
//字面量赋值
String s = "abc";
//s定义在字符串常量池中(方法区),不会存在两个相同的字符串
String b = "abc";//s  b指向同一个地址
s= "hello";//会在常量池中重新指定一块区域,将s指向这块区域
s+="world";//同上,不会在原先的abc后面加上def
s.replace('e','m');//把a变为m,同样会重新指定一块区域

//new 赋值

StringBuffer 额外空出16个char位置,k扩容时,原长度*2+2/扩展的特别长

StringBuilder s

扩容时 s.append(“ass”);

6.2日期时间API
//时间戳:距离1970年。。。
//System类中currentTimeMillis()
long time = System.urrentTimeMillis();

java.util.Date
    java.s1l.Date(子类);//对应数据库中的日期变量
//偏移量 年从1900开始,月份从0开始
Date date2 = new Date(2020-1900,9,8);
Date date = new Date();
System.out.println(date.toString());
System.out.println(date.getTime());//毫秒数(时间戳)
//也可指定毫秒数,创建Date对象

//LocalDate、LocalTime、LocalDateTime
LocalDate date = LocalDate.now();//另外两个同
LocalDateTime date1 = LocalDateTIme.now();
date.of(2020,10,9,12,23,12);//没有偏移量,同

//get
date1.getDayOfManth();
date1.getDayOfWeek();
date1.getMonth();
date1.getMonthValue();
//set 不可变性
LocalDate date3 = localDate.withDayOfMonth(22);
//原先的localDate不会变

//plus
LocalDateTime date4 = date1.plusMonths(1);

//minus减
LocalDateTime date5 = date1.minusDays(1);

JVM

1.架构模型

基于栈的指令集:零地址指令方式,每一个方法都是入栈操作,方法结束出栈

基于寄存器指令集:

解释器:将每行代码都编译,循环的话循环体重复解释n次

即时编译器 jit :寻找热点代码,将热点代码存到缓存中

sun classic VM :内部只提供编译器,用即时编译器要外挂,而一旦外挂,就不能用即时编译器

如果只用即时编译器,一开始的等待时间会较长

exact VM

准确式内存管理

可以确认内存中某个位置的数据具体是什么类型

热点检测 编译器与解释器混合工作

hotspot VM 热点检测 多用途

JRockit专注于服务端 响应速度 只靠即时编译器 最快的 JVM ,不考虑一开始的启动时间

J9 多用途

2.类加载子系统
2.1加载阶段

将class文件写入到内存中

ClassLoader

引导类加载器:Bootstrap CLass加载器 以c/c++实现 其余都属于自定义类的加载器

扩展类加载器:

系统类加载器:

ClassLoader SystemClassLOader = ClassLOader.getSystemClassLoader

2.1.1通过类名获取定义此类的二进制字节流

2.1.2将字节流代表的静态存储结构转化为方法区的运行时数据结构

2.1.3在内存中生成代表这个类的javva.lang.Class对象,作为方法区这个类的各种数据的访问接口

2.2链接

2.2.1验证

验证class文件中字节流信息的符合当前虚拟机要求

2.2.2准备

为类变量分配空间并设置变量的默认初始值如int 的设置为0

不包括加了final修饰的static,因为final在编译时就会分配,准备阶段会显式初始化

类变量分配在方法区,实例变量随对象放到java堆中

2.2.3解析

常量池内的符号转换成直接引用的过程

事实上,解析会伴随着JVM在执行完初始化之后再执行

2.3初始化

执行类构造器方法

对类变量赋值和静态代码区中的语句一起

按顺序执行

保证一个类在多线程下同步加锁,否则一个加载后加锁后会阻塞其他线程的进行。

2.4类加载器
  • 根加载器 bootstrap
  • 扩展类加载器
  • 系统加载器、应用程序加载器
class A{
    psvm{
        A a = new A();
        Class b =a.getClass();
        ClassLoader c = b.getClassLoader();
    }
}
2.5双亲委派机制

类加载器收到类加载的请求

将这个请求委托给父类加载器去完成,系统——>扩展类——>根加载器

委托到根加载器后,启动加载器检查是否能加载当前类,能加载就结束,不能会向下抛出异常,通知下层加载器去加载

2.6沙箱机制

字节码校验器:不是所有的类文件都经过字节码校验 比如核心类

类装载器

  • 防止恶意代码干涉正常代码:双亲委派机制 比如重写String类
  • 守护了被信任的类库边界 双亲委派机制
  • 将代码归入保护域,确定了代码可以进行哪些操作

虚拟机为不同的类加载器载入的类提供不同的命名空间,这个命名空间是由JVM虚拟机为每一个类装载器维护的,之间互相不可见

2.7native

带native关键字的表示会调用底层c语言的代码

会进入本地方法栈 调用本地方法接口 JNI

JNI的作用:扩展Java的使用 融合不同的编程语言

在内存区域中开辟了一块标记区域:Native Method Stack 登记native方法

3.数据区
3.1概述

线程私有:程序计数器、栈、本地栈

共享:堆、堆外内存(元空间、代码缓存)

一个JVM 对应 Runtime对象实例

分为五部分:本地方法栈 栈 方法区 程序计数器 堆

  • 有垃圾回收机制:方法区、堆

  • OOM(有溢出错误的可能):除程序计数器外都有

3.2PC寄存器(程序计数器)

是对物理PC寄存器的一个模拟

栈帧对应一个方法

程序计数器记录当前线程正在执行的java方法的 JVM 指令地址,如果是native方法,则是未定值(undefined),native方法记录在本地方法栈

唯一在java中未定义OutOtMemoryError情况

3.3方法区

static final Class 常量池放在方法区中,实例变量放在堆内存中,和方法区无关

3.4栈

mian先执行,先入栈,最后结束

线程结束,栈内存释放,对于栈来说,不存在垃圾回收

栈帧:

栈+堆+方法区

4.执行引擎
5.垃圾回收

JAVA反射

Java 代码在计算机中经历三个阶段

获取class对象的方法

1.Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象

全类名:包名+类名

2.类名.class 通过类名的属性class获取

3.对象.getClass(): getCLass在object类中定义

内置对象如INTEGER可以 INTEGER.Type

同一个字节码文件在一次文件程序过程中,只会被加载一次,不论通过那一次获取

class对象功能

获取成员变量 Field[] getFileds[]

​ Filed getFiled(String name)

​ Filed[] getDeclaredFields()

​ Filed getDeclaredFiled(String name)

获取构造方法

Constructor<?>[] getConstructors()

Constructor getConstructor(类<?>… parameterTypes)

获取成员方法

Method[] getMethods()

Method[] getMethod(String name ,类<?>… paramTYpes)

Method[] getDeclaredMethod()

获取类名 String getName()

创建properties对象
propertise pro = new Properties();
加载配置文件,转换为一个集合 

ClassLoader classLoader = ReflectTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("pro.properties")
pro.load(is);

获取配置文件中定义的数据
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");

加载该类进内存
 Class cl = Class.forName(className);
 创建对象
 Object obj = cls.newInstance();
 获取对象方法
 Method method = cls.getMethod(methodName);
 执行方法
method.invoke(obj);


配置文件:
className = cn.itcast.domin.Student//该目录下有以一个Student类
method=eat

JAVA注解

Annotation

对程序做出解释,能被编译器读取

内置注解

@Overwrite
@Deprecated 不推荐使用的程序元素 或者有更好的选择
@SuppressWarning("all")镇压警告

元注解

负责解释其他注解的注解
@Target 描述注解的使用范围
@Retention 表示需要在什么级别保存该注释信息,用于描述注解的声明周期
 SOURCE <CLASS<RUNTIME
 源代码时有效 类中有效  运行时有效
@Document 说明注解将被包含在javadoc中
@lnherited 说明子类可以继承父类中的注解

如@Tareget(value=ElementType.METHOD)
@Retention(value=RententionPolicy.RUNTIME)
@Document
@lnherited
@interface MyAnnotation{
 //注解的参数,不是方法  参数类型+参数名() default是默认的参数,如果没有参数会报错
  String name() default "";
  int id() default -1;//默认值为-1,代表不存在
}表示定义的注释只用在方法上

只有一个参数时命名为value,可以省略 value = 其他的不可以 要写成 name ="1223"

定义注解

JAVA多线程

1.进程 线程 并行 并发

进程:正在执行的程序段

线程:共享进程的堆和方法区,程序计数器和虚拟机栈每个线程各有一个,一个进程有多个线程

一个java应用程序至少有3个进程:main()主线程 gc()垃圾回收线程 异常处理线程

并行:多个cpu同时执行多个任务

并发:一个CPU采用时间片"同时"执行多个任务

多线程的优点:

  1. 提高应用程序的响应 对图形化界面更有意义,可增强用户体验

  2. 提高CPU利用率

2.创建线程与使用

java.lang.Thread

创建1.继承Thread类,重写run函数

创建实例,然后实例 . start():启动线程 并调用run方法

只用run方法的话不会新建线程,还是在总main()线程

Thread.currentThread,getName()获取当前进程的名字

对一个线程来说,只能start一次,不然会报错 只能新new一个

new Thread(){

public void run(){

}}

匿名类,重写run方法

currentThread() : 静态方法,返回执行当前代码的线程

getName()获取线程名字

setName() 设置线程名字 在启动前使用

yield() : 释放当前线程的执行权 但有可能下次又抢到了执行

join() : 如h1.join() 直到h1进程执行完之后原线程才会结束阻塞状态

stop() : 结束一个线程 该方法已过时,不建议使用

sleep(): 进程进入阻塞状态 参数为阻塞的时间

isAlive():判断进程是否还存活

创建2:实现接口Runnable

如果以一个实现类来创建几个进程的话,几个进程共享数据,可以实现共享数据不用static

Thread也实现了Runnable接口,本质上创建一个线程就是实现接口类里面的run方法

线程同步

某个线程对共享变量还没操作结束另一个进程也要读取、修改共享变量,这时就会出现问题

如何解决:当一个线程操作共享数据时,其他线程不能参与

操作不止包含修改删除,还有调用也是

同步机制:

方法一:

同步代码块:

//处理Runnable实现的方式
synchronized(同步监视器){
  //需要同步的代码:操作共享数据的代码
}
//同步监视器:锁,任何一个类的对象都可以充当锁 多个线程共用一个锁

//处理Thread继承方式:
//多个进程要创建n个实例对象,所以在初始化锁时,要加上static 


//锁可以用this 指向当前对象 不能用于继承方式 
//可以用window.class  window是类名 
    
方法二:

同步方法

如果操作共享数据的代码完整地声明在一个方法中,把这个方法定义为同步的

//解决Runnable
public synchronized void show(){//同步监视器是this
    //代码与同步代码块内的代码相同
}
//解决继承Thread
public static synchronized void show(){//锁是类 window.class
    //保证内部函数也是静态的 Thread.currentThread.getName
}

单例模式 懒汉式

//使用同步机制将单例模式中的懒汉式改写为线程安全的
class Bank{
    private Bank(){}
    private static Bank instance = null;
    public static Bank getInstance(){
        //多个线程都调用该函数时,有可能会出现安全问题
        //处理方法:1 public static synchronized Bank getInstance()
        // 2 synchronzied (Bank.class){
        //  里面是if else 内容
        //  }
        /*if(instance==null){
            synchronized (Bank.class){
                if(instance == null){
                    instance = new Bank();
                }
          }
        }
        return instance;*/
  
        if(instance==null){
            instance = new Bank();
        }
        return instance;
    }
}
方式三
lock锁 jdk5新增

class Window implements Runnable(){
    private int ticket = 100;
    //实例化
    //可设置参数为true: private ReentrantLock lock = new ReentrantLock(true);一个线程解锁后不会立即又一次将资源分配给该进程
    private ReentrantLock lock = new ReentrantLock();
    //如果是继承的方式 lock要加上static
    public void(){
        while(true){
            try{
                lock.lock();
            }finally{
                lock.unlock();
            }
        }
    }
}

lock与synchronized不同
synchronized :自动释放同步监视器;有代码块,也有方法锁;隐式锁
lock: 需要手动启动、结束同步;只有代码块锁;JVM花费较少时间调度线程;性能更好;显式锁
lock > 同步代码块 > 同步方法
    
进程通信

wait() 使进程阻塞,该线程一阻塞,会释放锁,而sleep不会
notify()一旦执行会唤醒wait的优先级最高的那个线程
notifyAll() 唤醒所有

  1. 必须放在同步代码块或同步方法中
  2. 这三个方法的调用者必须是同步代码块或同步方法中的同步监视器
  3. 这三个方法定义在object类中

sleep与wait:

相同:都会使线程阻塞

不同:

  1. Thread类声明sleep() Object声明wait

  2. sleep可以在任何场景下 wait在同步代码块或同步方法

  3. 都在同步代码块或同步方法中 sleep不用释放锁 wait需要

生产者、消费者问题

class clert{
    private int number=0;
    public void add(){
        number = number+1;
    }
    public void seq(){
        number = number - 1;
    }
}
class producer extends Thread{
    private clert clerk;
    public producer(clert clerk){
        this.clerk = clert;
    }
    //用同一个clerk初始化该类
    public void run(){
        while(true){
            synchronized(){
                if(a.)
            }
        }
    }
}
class Consumer extends Thread{
    private clert clerk;
    public Comsumer(clert clerk){
        this.clerk = clert;
    }
    public void run(){
        while(true){
            synchronized(){
                if(a.number>0)
                {
                    a.seq();  
                }
            }
        }
    }
}
jdk 5.0新增线程创建方式
  1. 实现Callerable接口:可抛出异常、有返回值、支持泛型返回

    1. 创建一个实现Callable的实现类
    2. 实现call函数,线程完成的任务放在call函数中
    3. 创建Callable实现类的对象
    4. 将此对象传递给FutureTask构造器中
    5. 将FutureTask对象传到Thread构造器中
    class  myThread implements Callable{
        public Object call() throws Exception{
            int sum=0;
            return sum;
        }
    }
    public class A{
        psvm{
            myThread a = new myThread();
            FutureTask b = new FutureTask(a);
            new Thread(b).start();
            //FutureTask是唯一实现Future接口的实现类,同时也实现了Runnable,可以获得取消、获取 实现Callable和Runnable类 执行结果
            Object sum = b.get();//要try catch
        }
    }
    
  2. 使用线程池: 提前创建多个线程,放入线程池,使用时直接获取,使用完放回池中

    提高响应速度

    降低资源消耗

    便于线程管理

    corePoolSize

    maximumPoolSize

    keepAliveTime

    public class B{
        psvm(){
            ExecutorService service = Executors.newFixedThreadPool(10);
            //有10个进程的进程池
            service.execute();//参数为Runnable实现类
            service.submit();//参数为Callable实现类  有返回值
            service.shutdown();//关闭线程池
            
        }
    }
    

java常用类

内部类
class outer{
    private String name;
    class inner{
        private String name;
    }
}
//内部类可调用外部类的变量 变量重名时,调用的是内部的,要访问外部的 要用outer.this.name
//内部类中不能定义static成员,可以包含静态常量 pricate static final 
//创建
class outer = new outer();
class inner = outer.new inter();

//静态内部类 
class outer{
    private String name="xxx";
    class static inner {
        //创建外部类才能访问对象
        outer a = new outer();
        System.out.println(a.name);
        
        private static int b=10;
    }
}
   
//不依赖外部类就能创建实例 级别和外部类一样 可以有静态变量

main(){
    outer.inner c = new outer.inner();
}


//局部内部类
//静态方法里面不能直接调用外部变量
class outer {
    public void show(){
        //局部变量add是一个常量 1.8之后省略了final 1.7及之前要显式加上final
        //加了final,局部内部类才能调用该变量
        final String add = "深圳"; 
        class inner {
            public void show2(){
                System.out.println(outer.this.name);
            }
        }
        inner  c = inner();
    }
}
//创建外部类,
包装类
//基本类型转包装对象
Integer a = Integer.valueOf(30);
Integer a = new Integer(3);
Integer a = new Integer("123");
Integer a = Integer.parseInt("999");
//反之
int b = a.intValue();

String str = a.toString();
Integer.MAX_VALUE;

//自动装箱、拆箱
Integer c= 10;//把10装成一个对象
int a=c;//把c变成int

//Integer 中[-128,127]中在缓存中,创建-128~127之间的话,直接从缓存中拿出,是同一个对象,如果不在这个范围中,会新建对象
Integer a = new Integer(3);
Integer b = new Integer(3);
//a==b为true
Integer a = new Integer(1111);
Integer b = new Integer(1111);  
//a==b为false;

String a= "hello";
String b = "world";
String c= a+b;
String d ="hello" + "world";
//c==d为false c.equals(d)也是
    
//可变字符序列
StringBuilder sb = new StringBuilder("abcdefg");
sb.setCharAt(2,"M");//把c变为M
sb.append("2333");
sb.reverse();//翻转
sb.insert(0,"你");
sb.delete(0,2);//删除下标0~2的字符


//Date类

JAVA网络编程

1.1概述

TCP:打电话 连接、通话

UDP:发短信 发完就完事了 接收

  1. 如何定位一个网络上的一台主机:ip地址:端口 定位到这个计算机上的某个资源

  2. 硬件连接 有线、无线

    网页编程 javaweb B/S

    网络编程 TCP/IP C/S

1.2网络通信的要素

如何实现网络的通信?

  • 如何如何定位网络上的一台或多台主机
  • 找到主机如何通信

通信双方地址:

  • ip
  • 端口号

规则:网络通信的协议 TCP、UDP

1.3 IP

ip地址:InetAddress

  • 127.0.0.1 本机localhost

  • ip地址分类

    • ipv4/ipv6

      • ipv4 :127.0.0.1 4个字节组成 42亿 亚洲4亿

      • ipv6 8个无符号整数 128位

        1238:abcd:9291:cccc:2819:abcd:7478:bdec
        
    • 公网-互联网 私网-局域网

      • ABCD类地址
      • 192.168.xx.xx专门给组织内部使用
InetAddress inetAddress1 = InetAddress.getByName("www.baidu.com");
//getHostName获取域名
//getHostAddress获取ip
1.4端口

端口表示计算机中一个程序的进程

  • 不同的进程有不同的端口号,用来区分软件

  • 规定为0~65536

  • TCP ,UDP 单个协议下端口号不能相同

  • 端口分类

    • 公有端口0~1023

      • HTTP:80
      • HTTPS:443
      • FTP:21
      • Telent:23
    • 程序注册端口

      • Tomcat:8080
      • Mysql: 3306
      • Oracle:1521
    • 动态、私有端口:49152~65535

      netstat -ano
      netstat -ano |findstr "5900" 查找进程
      
1.5通信协议

TCP/IP协议 传输层

  • TCP:用户传输协议
    • 连接 稳定
    • 三次握手 四次挥手
    • 客户端、服务端
    • 传输完成 释放连接 效率低
  • UDP:用户数据报协议
    • 不连接 不稳定
    • 客户端、服务端 :没有明确的界定
    • 不管有没有准备好,都可以发给你
1.6TCP
//客户端
public class C{
    psvm{
        //获取ip地址 端口号
        InetAddress c = InetAddress.getByName("127.0.0.1");
        int port=9999;
        //创建socket连接
        Socket socket = new Socket(c,port);
        //发送消息
        OutputStream os = socket.getOutStream();
        os.write("你好hahaha".getButes()); 
        //关闭资源 io流 scoket资源
    }
}
//服务端
public class S{
    psvm{
        try{
            //1.创建地址
            ServerSocket s = new ServerSocket("9999");
            //2.等待连接
            Socket socket = serverSocket.accept();
            //3.获取服务端消息
            InputStream is =socket.getInputStream();
            
            //管道流
            ByteArratOutputStream baos = new ByteArratOutputStream();
            byte[] = buffer = new byte[1024];
            int len;
            while((len=is.read(buffer))!=-1){
                baos.write(buffer,0,len);
            }
            System.out.println(baods.toString());
            //关闭资源 先开的后关
            
        }catch
    }
}

上传文件

class C {
    psvm{
        //创建一个连接
        Socket socket = new Socket(InetAddresss.getByName("127.0.0.1"),9999);
        //获取输出流
        OutputStream os = socket.getOutputStream();
        //获取文件流
        FileInputStream fis = new FileInputStream(new File("3/txt"));
        //写出文件
        byte[] buffer = new byte[1024];
        int len;
        while((len=fis.read(buffer))!=-1){
            os.write(buffer,0,len);
        }
        //关闭资源
        fis.close();
        os.close();
        socket.close();
    }
}

class S{
    psvm{
        //创建服务
        ServerSokcet serverSocket = new ServerSokcet();
        //等待连接 阻塞式等待 会一直等待直到客户端连接
        Socket socket = serverSocket.accept();
        //获取输入流
        InputStream is = socket.getInputStream();
        //文件输出
        FileOutputStream fos = new FileOutputStream(new File("recesive.txt"));
        byte[] buffer = new byte[1024];
        int len;
        while((len=fos.read(buffer))!=-1){
            fos.write(buffer,0,len);
        }
        
        //关闭资源
        fos.close();
        is.close();
        socket.close();
        serverSocket.close();
        
    }
}
1.7 Tomcat
  1. 把文件放到webapps目录下

  2. Tomcat下的D:\Tomcat\apache-tomcat-9.0.43\conf\Catalina\localhost目录下

    部署文件:path是访问路由,docBase是项目目录

1.8UDP

不需要连接服务器

DatagramSocket 连接

DatagramPacket 发送包数据

public class C{
    psvm{
        //1创建一个Socket
        DatagramSocket socket = new DatagramSocket();
        //创建包
        String msg = "hahahhahaha";
        
        InetAddress l = InteAddress.getByName("localhost");
        int port=9000;
        //数据 数据的长度 起始 地址
        DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,l,port);
        //发送包
        socket.send(packet);
        //关闭资源
        socket.close();
    }
}

//接收
public class S{
    psvm{
        //开放端口
        DatagramSocket s = new DatagramSocket("9000");
        //接收数据包
        byte[] b = new byte[1024];
        DatagramPacket p = new DatagramPacket(b,0,b.length);
        socket.receive();
        System.out.println(new String(packet.getData(),0,packet.getData().length());
        //关闭连接
        socket.close();
        
    }
}

循环发送

//发送方
java class A{
    psvm{
        //创建发送方的端口
        DatagramSocket s =new DatagramSocket("6666");   
        //从控制台读取输入,转化为输入流
        BufferedReader d = new BufferedReader(new InputStream(system.in));
        while(true){
            //读取输入流的一行
            String data = d.readLine();
            //转化为byte数组
            byte[] sendData = data.getBytes();
            //进行发送
            DatagramPacket p = s.DatagramPacket(sendData,0,sendData,length,new InteSocketAddress("localhost",8888));
            s.sendPacket(p);
            if(data.equals("bye")){
                break;
            }
        }
        s.close();
    }
}

//接收方
java class B{
    psvm{
        //创建接收方的端口
        DatagramSocket s =new DatagramSocket("6666");
        while(true){
            byte[] da = new byte[1024];
            DatagramPacket d = new DatagramPacket(da,0,da.length);
            s.reveice(d);
            System.out.println(new String(d.getData(),0,d.getData().length);
            if()
        }
        s.close();
    }
}
1.9URL

统一定位资源符

DNS域名解析 www.baidu.com <=>xx.xx.xx.xx;

协议://ip域名:端口/项目名/资源

通过url下载

psvm{
    URL url = new URL("http://.../cc/cs");
    
    HttpURLConnetcion urlConnection = (HttpURLConnetcion) url.openCOnnection();
    
    InputSTream inputStream = urlConnection.getInputStream();
    
    FileOutputStream fos = new FileOutputStream("down.txt");
    
    byte[] buffer =new byte[1024];
    int len;
    while((len=inputStream.read(buffer))!=-1){
        fos.write(buffer,0,len);
    }
    fos.close();
    inputStream.close();
    urlConnection.disconnect()l
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值