编译原理之寄存器的理解
通用寄存器
寄存器:存储数据:CPU>内存>硬盘
32位CPU:8 16 32
64位CPU:8 16 32 64
通用寄存器
#32位寄存器只有8个
32位寄存器名称:EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI
存值的范围:0~FFFFFFFF
计算机如何向寄存器存值
对二进制来说:直接修改
对于会变来说:
MOV指令
#汇编就是16进制,底层2进制
FFFF FFFF FF
32位 16位 8位
#位数改变寻址能力
8位:高8位+低8位=16位
#通用寄存器存储任意值
#其他寄存器存储特定的值,每一位都有自己特定的功能
#平时操作的都是通用寄存器
位运算的加减乘除(就是计算机底层的加减乘除)
计算机只认识0 1
基本数学是建立在加减乘除之上
计算机依靠加减乘除处理任何操作
#计算机是怎么操作的
0000 0100
0000 0101
-----------(加法:计算机不会直接加的)
0000 1001
#计算机的实现原理
#第一步:异或:如果不考虑进位,异或可以直接得出结果
0000 0100
0000 0101
---------
0000 0001
#第二步:与运算(判断进位,如果与运算结果为0,没有进位)
0000 0100
0000 0101
---------
0000 0100
#第三步:将与运算的结果,左移一位 0000 10000
#第四步:异或
0000 0001
0000 1000
---------
0000 1001
#第五步:与运算(判断进位,如果与运算结果为0,没有进位)
0000 0001
0000 1000
---------
0000 0000
#所以最终结果就是与运算为0的结果的上一个异或运算
//UDP接收方
package com.Rui.Study.demo08;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* Create by Administrator
* Data 2021/12/27 18:31
* Description
**/
public class TalkRecive implements Runnable{
DatagramSocket socket = null;
private int port;
private String msgForm;
public TalkRecive(int port,String msgForm) {
this.port = port;
this.msgForm = msgForm;
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
try {
//准备接受包裹
byte[] container = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(container, 0, container.length);
socket.receive(datagramPacket);
//断开链接
byte[] data = datagramPacket.getData();
String receiveData = new String(data, 0, data.length);
System.out.println(msgForm + ": " + receiveData);
if (receiveData.equals("bye")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
//UDP发送方
package com.Rui.Study.demo08;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
/**
* Create by Administrator
* Data 2021/12/27 17:57
* Description
**/
public class TalkSend implements Runnable{
DatagramSocket socket = null;
BufferedReader reader = null;
private int Formprot;
private String toIp;
private int toPort;
public TalkSend(int Formport, String toIp, int toPort) {
this.Formprot = Formport;
this.toIp = toIp;
this.toPort = toPort;
try {
socket = new DatagramSocket(Formport);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
//准备数据:读取控制台System.in
while (true) {
try {
String data = reader.readLine();
byte[] bytes = data.getBytes();//转为数据
DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length, new InetSocketAddress(this.toIp, this.toPort));
socket.send(datagramPacket);
if (data.equals("bye")) {
break;
}
}catch (IOException e){
e.printStackTrace();
}
}
socket.close();
}
}
public class TalkStudent {
public static void main(String[] args) {
//开启两个线程,既可能是接收方,也可能是发送方
new Thread(new TalkSend(7777,"localhost",9999)).start();
new Thread(new TalkRecive(8888,"老师")).start();
}
}
//多线程聊天室,通过实现runable接口实现
public class TalkTeacher {
public static void main(String[] args) {
new Thread(new TalkSend(5555,"localhost",8888)).start();
new Thread(new TalkRecive(9999,"学生")).start();
}
}
网络编程入门
ip和port端口
port(端口)
端口表示计算机上的一个程序进程
1.不同的进程有不同的端口号!用来区分软件!
2.被规定0~65535
3.TCP,UDP:65535*2(两个协议,可以重复使用一个端口),tcp:80,udp:80
4.端口分类
1>公有端口0~1023
* HTTP:80
* HTTPS:443
* FTP:21
* Telent:23
2>程序注册端口:1024~49151,分配用户或程序
* Tomcat:8080
* MySql:3306
* Orcale:1521
3>动态,私有:49152~65535
netstat -ano|findstr "5900" #查看指定的端口
tasklist|findstr "8696" #查看指定端口进程
通信协议
协议:约定,就好比我们现在说的普通话
网络通讯协议:速率,传输码率,代码结构,传输控制。。。
问题:非常很复杂,就用分层来解决
大事化小:分层
TCP/IP协议簇
重要:
- TCP:用户传输协议
- UDP:用户数据报协议
TCP UDP对比
TCP:打电话 连接,稳定,三次握手,四次挥手,客户端和服务端
UDP:发短信 不连接,不稳定,客户端,服务端:没有明确的界限,不管有没有准备好,都可以发给你…DDOS:饱和攻击
1.成员方法和成员变量
在 Java 语言中对象的属性以成员变量的形式存在,对象的方法以成员方法的形式存在。
成员变量
在 Java 中对象的属性也称为成员变量。就是类似javabean的成员变量既是属性。
成员方法
在 Java 语言中使用成员方法对应于类对象的行为。例如:get,set方法
2.构造方法和成员方法的区别
A:格式区别
构造方法和类名相同,并且没有返回类型,也没有返回值。
普通成员方法可以任意起名,必须有返回类型,可以没有返回值。
B:作用区别
构造方法用于创建对象,并进行初始化值。
普通成员方法是用于完成特定功能的。
C:调用区别
构造方法是在创建对象时被调用的,一个对象建立,只调用一次相应构造函数
普通成员方法是由创建好的对象调用,可以调用多次
3.抽象类的构造方法
抽象类是有构造方法的!!!
Java中的this和super总结
this和super
(一)指代不同
1.this 是自身的一个对象,代表对象本身,可以理解为:**指向对象本身的一个指针。**指的是当前对象的引用。
2.super 可以理解为是指向自己超(父)类对象的一个指针,**而这个超类指的是离自己最近的一个父类。**是当前对象里面的父对象的引用。
(二)调用函数不同
1、super:调用基类中的某一个构造函数(应该为构造函数中的第一条语句) 。
2、this:调用本类中另一种形成的构造函数(应该为构造函数中的第一条语句)。
(三)引用对象不同
1、super:引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)。
2、this:代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)。
对象的封装
涉及到了public private和protect三个关键字
//Student.class
public class Student{
//如果是public,则在main方法中直接调用不爆红
public String name;
//如果是private,则在main方法中直接调用会爆红,无法调用
//需要用get,set方法来处理
private int age;
}
//main文件
public class test {
public static void main(String[] args) {
Student student = new Student();
student.name;
student.age;
}
}
Java中的值传递和引用传递
https://www.cnblogs.com/ncl-960301-success/p/10574701.html
https://www.cnblogs.com/zhangshiwen/p/5830062.html
重点需要关注一下怎么样的情况是值传递,什么样的情况是引用传递,值传递不涉及形参对象,而引用传递要把形参当成对象来处理!
堆栈和方法区
方法区是在堆中的
转载文章
https://blog.csdn.net/zly921112/article/details/61192747
1.稀疏矩阵概念
如果一个矩阵中有很多的同一元素,那么正常的存储方式就会浪费内存,所以就衍生出了稀疏矩阵的概念,将正常的数组变为稀疏矩阵就是将数字压缩
[0] | 行 | 列 | 有效值 |
---|---|---|---|
[1] | 2 | 3 | 2 |
[2] | 3 | 1 | 3 |
意思为:2行3列是数字2,3行1列是数字3
2.代码实现
package com.yc.sparseArray;
import java.io.*;
public class SparseArray {
public static void main(String[] args) throws IOException {
//创建原始二位数组
//0表示 没有棋子 , 1表示黑子,2表示白子
int chessArr1[][] = new int[11][11];
chessArr1[1][2] = 1;
chessArr1[2][3] = 2;
chessArr1[4][5] = 2;
//输出原始二位数组
System.out.println("原始的二维数组:");
for (int[] row:chessArr1){
for(int data:row){
System.out.printf("%d\t",data);
}
System.out.println();
}
//将二维数组转为稀疏数组
//遍历二维数组,得到非零数据的个数
int sum = 0;
for (int i = 0; i < chessArr1.length; i++) {
for (int j = 0; j < chessArr1.length; j++) {
if(chessArr1[i][j] != 0){
sum++;
}
}
}
//2.创建对应的稀疏数组
int sparseArr[][] = new int[sum+1][3];
//给稀疏数组赋值
sparseArr[0][0] = chessArr1.length;
sparseArr[0][1] = chessArr1.length;
sparseArr[0][2] = sum;
//遍历二维数组,将非零的值存放到稀疏数组
int count = 0; //count用于记录第几个非0数据
for (int i = 0; i < chessArr1.length; i++) {
for (int j = 0; j < chessArr1.length; j++) {
if(chessArr1[i][j] != 0){
count ++;
sparseArr[count][0] = i;
sparseArr[count][1] = j;
sparseArr[count][2] = chessArr1[i][j];
}
}
}
//这里的 输出流 append属性一定不能设置为true,不然就是追加到文件中了
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:\\map.data",false));
BufferedWriter bw = new BufferedWriter(osw);
for (int[] ints : sparseArr) {
bw.write(ints[0]+ " " +ints[1]+ " " +ints[2]);
bw.newLine();
}
//重要的一个部分,关闭流,养成好的习惯
bw.flush();
bw.close();
//输出稀疏数组的形式
System.out.println();
System.out.println("得到的稀疏数组为:");
InputStreamReader isr = new InputStreamReader(new FileInputStream("d:\\map.data"));
BufferedReader br = new BufferedReader(isr);
for (int i = 0; i < sparseArr.length; i++) {
System.out.println(sparseArr[i][0] + "\t" +
sparseArr[i][1] + "\t" + sparseArr[i][2]);
}
//将稀疏数组恢复成原始二维数组
/*
先读取稀疏数组第一行,建立数组
*/
String first = br.readLine();
String[] firstLine = first.split(" ");
int chessArr2[][] = new int[Integer.parseInt(firstLine[0])][Integer.parseInt(firstLine[1])];
//在读取
String next = null;
while((next=br.readLine()) != null){
String[] nextLine = next.split(" ");
chessArr2[Integer.parseInt(nextLine[0])][Integer.parseInt(nextLine[1])] = Integer.parseInt(nextLine[2]);
}
//重要的一个部分,关闭流,养成好的习惯
isr.close();
br.close();
System.out.println();
System.out.println("还原的二维数组:");
//恢复后的二维数组;
for (int[] row:chessArr2){
for(int data:row){
System.out.printf("%d\t",data);
}
System.out.println();
}
}
}