有一段时间没有写博客了,我这段时间去学习java了,谁也不会想到,短短两周的时间,我的java学习已经学习了不少东西了,毕竟python这座山也可以去攻java这块玉,对应python那就是基础的大部分内容,不过java的这次基础学习设计了一些超标内容,不过也不超标,也就是多了一些网络编程和java的多线程机制,我在学习python的时候就已经提前上手学了 些许 多线程的相关知识,不过没想到多线程的神奇之处,又深深的体会到资源的有限,而欲望的无限,还是感到压力山大,但是无所谓,没有压力哪有动力,不逼自己一下,真没想到自己真的可以两周做到这种程度,尽管自己对自己学过的这些知识越来越觉得不过如此,而且我还没有学完网络编程的相关知识,但是没关系,加个班,对自己的总结效率真的感到有点伤,我需要提升的关键区域,看来博客还得多写,很有可能是这段时间没有写博客,失去了总结的力量来支撑自己往下学;
在这段时间,我体会过面向对象的神奇,也感受到java中的“类型决定一切”,至于为什么说这句话,那自然是数据类型决定他可以去做什么,他没有数据类型直接就编译不通过了,这就涉及到java的虚拟机jvm了,java是一种半编译半解释型的语言,只要是支持jvm虚拟机的操作系统就都支持java可执行文件,jvm会把原本的java class编译成.class文件,然后再解释器的解释下,就可以直接去执行了,java的非平台性也就体现出来了。
下面就是这段时间的笔记总结了
首先,开头,必然是一个思维导图来进行小逻辑展示
数据类型
java中的数据类型分为:基本数据类型、引用数据类型
基本数据类型
超出这四类八种的就全部都是引用数据类型,不过,可以看它有没有new,如果有new的话,那规定的这个数据类型,就是引用数据类型,针对数组的写出来没有new,那只是它的new 的简写
整数类型
应该还很清楚,整数类型,int,但是在java它和python不一样了,他规定出来了更多的数据类型,他把他们都归为了整数类型,不过在计算中就数据类型会存在自动类型转换以及强制类型转换,不然也实现不了计算,毕竟单位不一样了
byte、short、int、long这些数据类型也不过如此,
这张图片确实没什么用 ,不过存在即合理,比如他的占用存储空间,就很关键,其他就无需多言了,高手的练成,注定是一片的报红出来的。
浮点类型
因为float和double两种类型的占用存储空间不同,但他们还存在着小数,同样会出现c语言中的精度溢出这种现象。
字符类型
不行,写的太累了,还是cv吧,不行,我要尝试在这过程总结出来我学的不完善的地方
布尔类型
我还记得布尔类型,此时的他相对python还没有让我完全懵,现在还好,boolean,进行流程控制,true和false,他对大小写敏感,只有小写,最关键的是他不可以是0或非0来代替true和false,这样就少了很多的争论(python中曾出现过的)了,但是今天发现了似乎他并没有消失,而是以另一种形式又出现在我身边。
equals和== 还有上头的hashcode,不过都还好,csdn的大佬还是很多的,很多的知识我都可以很轻松的获得,就比如针对这个问题的一文详解java中的==和equals()_java==和equals-CSDN博客
基本数据类型转换
自动数据类型转化,容量小的数据类型自动转换为容量大的数据类型:数据类型按容量大小排序为:byte,short,char->int->long->float->double
byte,short,char之间不会进行互相转换,他们三,都是弟弟,都得变成int才能运算。
强制类型转换,容量大的数据类型转换为容量小的数据类型,需要加上强制转换符,但很可能会造成initity无穷的溢出或者精度降低。
多种类型的混合计算(混合乱斗),那就全部一起向容量最大(最能打的那个)转换(集火),然后再进行运算(混合乱斗)
代码整合
package com.runnoob.test;
public class TestConvert {
public static void main(String arg[]) {
// int i1 = 123;
// int i2 = 456;
// double d1 = (i1+i2)*1.2;//系统将转换为double类型运算
// float f1 = (float)((i1+i2)*1.2);//需要加强制转换符
// byte b1 = 67;
// byte b2 = 61 ;
// byte b3 = (byte)(b1+b2);//系统将转换为int型运算,需要强制转换符
// System.out.println(b3);
//
// double d2 = 1e200;//实数默认是double
// float f2 = (float)d2; // 会产生溢出无穷大,double-float不可以这么写
// System.out.println(f2);
//
// float f3 = 1.23f;//必须加f
// long l1 = 123;
// long l2 = 3000000000000L; //必须加L
// float f = l1 + l2 + f3; //系统将强制转换为float型计算
// long l = (long)f;//强制转换会舍去小数部分(不是四舍五入)
// System.out.println(l);
int i=1;
int j = 12;
float f1=0.1f;//编译错误,不可以转换类型由double到float ,需要强转,
// 0.1f和float强转,不一样,一个是把字节强砍,一个是本身就存在
float f2=123;
long l1 = 12345678,l2=88888888;
double d1 = 2e20,d2=124;
byte b1=1, b2=2, b3=125;
j = j+10;
i = i/10;
i = (int)(i*0.1);//
char c1='a',c2=125;
byte b = (byte)(b1-b2);//Dint到byte有问题,不可以这么转换
char c = (char)(c1+c2-1);
float f3 = f1+f2;
float f4 = (float)(f1+f2*0.1);//0.1是double,double不可以到float,需要强转
double d = d1*i+j;
float f = (float)(d1*5+d2);
System.out.println(i);
System.out.println(j);
System.out.println(f1);
System.out.println(l1);
System.out.println(l2);
System.out.println(d1);
System.out.println(d2);
System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
System.out.println(c1);
System.out.println(c2);
System.out.println(b);
System.out.println(f3);
System.out.println(f4);
System.out.println(d);
System.out.println(f);
}
}
才写了一个数据类型和我的感受就三千字了,字数怎么这么快就这么多了,我还有好多好多都没有写呢。【悲伤】【emoji】
方法(函数)
我的方法是b站学习黑马的阿伟老师,不得不说阿伟老师真的很有实力
Java入门-01-Java学习介绍_哔哩哔哩_bilibili
针对方法的使用进行了很详细的讲解
不过还是对java的方法是什么需要有所记忆
方法(method)是程序中最小的执行单元,从main开始,你猜为什么从main开始,自然是main方法被jvm记住了,他知道执行一个java文件的开头就是main方法;
方法的定义格式只有一种:
public static 返回值类型 方法名(参数){
方法体;
return 返回值;
}
针对参数,那就是形参和实参,这就是一段久远的回忆了,我记得还在五百年前,啊呸,在前几个月,我针对python 的参数的理解,参数就是这样了
方法定义的小技巧:(阿伟老师分享)
1.我要干什么 (方法体)
2.我干这件事需要什么才能完成?(形参)
public class Test1{
public static void main(String[] args){
getlength(5.2,1.3);
}
public static void getlength(double len, double width){
double result = (len+width)*2;
System.out.println(result);
}
}
方法的重写
1.子类中可以根据需要对从基类继承来的方法进行重写
2.重写方法必须和被重写方法具有相同的犯法名称,参数列表和返回类型
3.重写方法不能使用比被重写方法更严格的访问权限
方法的重载
在同一个类中,定义了多个同名的方法,这些同名的方法具有同种的功能。
每个方法具有不同的参数类型或参数个数,和谐同名方法,就构成了重载关系。
简单记:在同一个类中,方法名相同,参数不同的方法。与返回值无关。
参数不同:个数不同、类型不同、顺序不同
参数条件:任何一个符合即可。
Java 虚拟机比较有实力,它会通过参数的不同来区分同名的方法。
重写和重载的对比
比较项目 | 方法重写(Override) | 方法重载(Overload) |
发生范围 | 存在于子类和父类之间 | 在一个类中 |
方法名称 | 必须相同 | 必须相同 |
参数列表 | 必须相同 | 必须不同(参数类型、参数个数、参数顺序至少有一个不同) |
返回类型 | 必须相同或为子类型(协变返回类型) | 可以相同或不同 |
访问修饰符 | 可以扩大访问权限,但不能缩小 | 无特殊要求 |
异常列表 | 可以减少或删除异常,但不能抛出新的、更广泛的异常 | 无限制 |
作用 | 实现多态性,子类根据需要重新定义父类方法的行为 | 方便使用者根据不同的参数列表来调用同一个方法 |
有时候ai就是考虑的比人全面呀,ai工具,虽然不建议用,但是查漏补缺还不错
方法的内存
方法调用的基本内存原理
虚拟机在运行的时候会占用一块空间
栈 与方法有关,进入栈,完成就出栈
堆 new 关键字,一定在堆里开辟了一个小空间
进栈——出栈,内存的释放是逐渐的
方法传递基本数据类型的内存原理
当我们传递基本数据类型的时候,传递的是真实的数据,形参的改变,不影响实际参数的值。
如果想要影响实际参数的值,就返回然后把值赋给原变量。
方法传递引用数据类型的内存原理
当我们传递引用数据类型的时候,传递的是地址值,形参的改变,影响实际参数的值
扩展:内存角度什么是基本数据类型,什么是引用数据类型
什么是基本数据类型,什么是引用数据类型
基本数据类型——4 类 8 种
本质没有展示出来
基本数据类型的变量里面存储的是真实的数据
只要是 new 出来的都是引用数据类型
在堆里面开辟的都有地址
变量中存储的是引用数据类型,那这时就会存储的是地址
数组
总结完了数组,就是三个,初始化,内存,操作;就是这三者,他们之间可谓是相爱相杀,扯远了,不过说他们之间有很大关系,那是完全没有问题
对比要点 | 一维数组 | 二维数组 |
结构 | 线性结构,元素排成一条线。 | 表格结构,由行和列组成,可以看作是多个一维数组的组合。 |
定义方式 |
|
|
初始化示例 |
|
|
元素访问 | 通过一个索引访问,如 | 通过两个索引访问,如 |
内存布局 | 元素在内存中连续存储在一段线性空间。 | 元素按行优先或列优先规则在内存中存储,每行(或每列)是一个连续的存储区域,不同行(或列)之间可能有间隔。 |
应用场景 | 适合存储简单的线性数据序列,如一组学生的成绩。 | 适合表示表格型数据,如矩阵、棋盘游戏的格子状态等。 |
不得不说,让我自己来写二维表的话,我只会考虑这三者,而ai却可以考虑的更加全面,我真的觉得ai太可怕了,但是ai的能力有强大的可怕,我仿佛在和无数先贤交手,不过三两回合变被拿下,哀人生之须臾,不过我不慌,我干不动就开摆了,不过为什么我要和他人比,我只要比昨天的我更有生命力,我就是更好的自己了。
初始化
介绍一下,初始化,在内存中,为数组容器开辟空间,并将数据存入容器的过程
面向对象
那就是还按照python的逻辑先过一遍
类和对象
类的定义主要由两方面组成——成员变量和方法。
对象的创建和引用
必须使用 new 关键字创建对象
2.使用对象(引用)成员变量或来引用对象的成员变量
3.使用对象(引用)方法(参数列表)来调用对象的方法
4.同一类的每个对象都有不同的成员变量存储卡空间。
5.同一类的每个对象共享该类的方法
非静态方法是针对每个对象进行调用
三大特性
封装
他与python的封装,区别不大,思想是同样的,省劲,直接拿去用就完了,调用就完了。
继承
在java的继承中有着多个关键字,extends和implement 针对c++他没有指针和多继承,也就是他只有单继承,但是他有接口,让他实现类似多继承的效果
不过在学习继承的过程中,也想python一样,存在着是否允许继承调用的关键字方法等,比如final还有private、protected等
多态
同样,都是面向对象编程的,都有着这三大特性,这种思想我愿称之为面向人类编程。
不过在这里有一个叫做对象类型转换的东西,如下
对象类型转换,是指存在继承关系的对象,不是任意类型的对象。
Java 语言允许某个类型的引用变量引用子类的实例,而且可以对这个引用变量进行类型转换。Java 中引用类型之间的类型转换(前提是两个类是父子关系)主要有两种,分别是向上转型和向下转型。如有疑问,请查阅其他博主的博文;
接口
这个东西,我记得有个博主讲的特别好,我找找
JAVA基础——接口(全网最详细教程)_java接口怎么写-CSDN博客
异常处理
对比项 | Error | Exception |
---|---|---|
含义 | 表示严重的问题,通常是不可恢复的情况,例如 JVM 内部错误、动态链接失败等。 | 表示可恢复的异常情况,通常是由于程序中的错误条件或意外情况引起的。 |
能否被程序处理 | 一般情况下,程序无法处理 Error。 | 程序可以通过 try-catch 块等方式来捕获和处理 Exception。 |
常见类型举例 | OutOfMemoryError、StackOverflowError 等。 | IOException、SQLException、RuntimeException 等。 |
累了,就不对异常和接下来的内容进行过多赘述
String
类别 | String | StringBuffer |
可变性 | 不可变 | 可变 |
性能(大量拼接操作) | 性能较差,创建大量中间对象 | 性能较好 |
线程安全 | 非线程安全(但不可变特性在多线程只读场景安全) | 线程安全 |
适用场景 | 存储固定字符串值、无需频繁修改 | 大量字符串拼接、多线程环境下的字符串操作 |
自然,我的水平只能看到它的可变性和性能,最多在能说一点使用场景,线程安全自然是想不到,水平差的有点远。
包装类Integer和Double
package com.runnoob.String;
import java.lang.Integer;
public class BasicalNumberPackage {
public static void main(String[] args) {
Integer i = 100;
Double d = Double.valueOf("123.456");
int j = i + d.intValue();
float f =i.floatValue()+d.floatValue();
System.out.println(j);
System.out.println(f);
double pi = Double.parseDouble("3.1415926");
double r = Double.valueOf("2.0").doubleValue();
double s = pi*r*r;
System.out.println(s);
try{
int k = Integer.parseInt("1.25");
}catch (NumberFormatException e){
System.out.println("数据格式不对!");
}
System.out.println(STR."\{Integer.toBinaryString(123)}B");
System.out.println(STR."\{Integer.toHexString(123)}H");
System.out.println(Integer.toOctalString(123)+"O");
}
}
以及Math和File
package com.runnoob.Math;
public class TestMath {
public static void main(String[] args) {
double a = Math.random();
double b = Math.random();
System.out.println(Math.sqrt(a*a+b*b));
System.out.println(Math.pow(a,8));
System.out.println(Math.round(b));
System.out.println(Math.log(Math.pow(Math.E,15)));
double d = 60.0, r = Math.PI/4;
System.out.println(Math.toRadians(d));
System.out.println(Math.toDegrees(r));
}
}
还有一个枚举,不在过多陈述,基础知识的广度是很大的,都说就太累了
容器
容器的概念
装着其他东西的器皿
主要接口层次
Collection接口
list接口和set接口,太累了,不写相关的方法了hashset和treeset,arraylist和linkedlist
Map接口
类似python的字典,键值对,hashmap和treemap
辅助接口层次
Comparable接口
这个接口很特殊,它是只有一个方法,它会有三种返回值,0表示对象大小相等,正数表示当前对象大于比较对象,负数表示当前对象小于比较对象
Iterator接口
它也挺特殊,用来遍历各种集合,jdk版本1.4之前返回值始终是object,现在是泛型了
IO流
输入输出、字符字节、节点处理这六种流
流类型 | 描述 | 特点 | 用途示例 |
FileInputStream(字节流、节点流) | 从文件中读取二进制数据。 | 直接与文件连接,以字节为单位读取数据。 | 读取图像、音频等二进制文件。 |
FileOutputStream(字节流、节点流) | 向文件中写入二进制数据。 | 直接与文件连接,以字节为单位写入数据。 | 保存二进制文件,如图片、视频等。 |
BufferedInputStream(字节流、处理流) | 为其他输入流提供缓冲功能,提高读取效率。 | 包装其他输入流,减少实际的 I/O 操作次数。 | 搭配其他输入流使用,加快文件读取速度。 |
BufferedOutputStream(字节流、处理流) | 为其他输出流提供缓冲功能,提高写入效率。 | 包装其他输出流,减少实际的 I/O 操作次数。 | 搭配其他输出流使用,加快文件写入速度。 |
InputStreamReader(字符流、处理流) | 将字节流转换为字符流,可指定字符编码。 | 可以处理文本文件,方便处理不同字符编码。 | 读取文本文件,指定合适的编码格式。 |
OutputStreamWriter(字符流、处理流) | 将字符流转换为字节流,可指定字符编码。 | 用于向文件写入字符数据,可指定编码。 | 将文本写入文件,设置特定编码。 |
java多线程机制
线程的体会,一条线,从0到1
线程的创建和启动
第一种方法
定义线程类实现Runnable接口,然后重写run方法
第二种方法
定义一个Thread子类然后重写run方法
package com.runnoob;
public class Multithreading {
public static void main(String[] args) {
Runner1 r = new Runner1();
//r.run();//方法调用
Thread t = new Thread(r);//并行运行,多线程
t.start();
for (int i = 0;i<40;i++){
System.out.println("Main Thread:------"+i);
}
}
}
class Runner1 implements Runnable{
public void run(){
for(int i = 0;i<40;i++){
System.out.println("Runner1:"+i);
}
}
}
建议使用接口的形式,尽量不要从Thread类中去继承
线程的调度和优先级
它有一个叫做时间片的东西,然后它的优先级越高,得到cpu执行的时间片也就越多,从1到10,从低到高,就是采用sleep的形式控制两个线程,进行调换
线程的状态控制
new 出来一个内存,之后需要等一会,不可以他 start 进来他就先来。
抢饭吃,这是争抢的关系。1 号先吃两口,之后就让他接着等一会(回到就绪状态)让 2 号吃两口,然后 2 号吃饱了(导致阻塞的事件/终止)然后 1 号继续——。。。相应的优先级,县长来了,给县长设置一个更高的优先级,让原先的线程先一边sleep或者wait(大概率),然后让县长先吃。
在 Java 中,让线程休眠的方法有很多,这些方法大致可以分为两类,一类是设置时间,在一段时间后自动唤醒,而另一个类是提供了一对休眠和唤醒的方法,在线程休眠之后,可以在任意时间对线程进行唤醒。
阻塞是活着的,终止就是死了
线程同步
线程同步:
即当有一个线程在对
内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态,实现线程同步的方法有很多,临界区对象就是其中一种。(银行的取钱)检查操作,和吐钱的操作之间,被打断了。
解决办法:把当前对象锁住就行。synchronized 锁定某个东西,他被锁住了 ,互斥锁。在执行当前方法的过程中,当前对象被锁定。
生产者消费者问题
package com.runnoob.Multithreading;
public class ProducerConsumer {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
Producer p = new Producer(ss);
Consumer c = new Consumer(ss);
new Thread(p).start();
new Thread(c).start();
}
}
class WoTou {
int id;
WoTou(int id) {
this.id = id;
}
public String toString() {
return "WoTou:" + id;
}
}
class SyncStack {
int index = 0;
WoTou[] arrWT = new WoTou[6];
public synchronized void push(WoTou wt) {
if (index == arrWT.length) {
try {
this.wait();//当前正在我这个对象访问的线程,wait
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
arrWT[index] = wt;
index++;
}
public synchronized WoTou pop() {
if (index == 0) {
try {
this.wait();//wait时候,锁不归他管,不归他所有
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();//叫醒正在线程等待的线程,结束wait
index--;
return arrWT[index];
}
}
class Producer implements Runnable {
SyncStack ss = null;
Producer(SyncStack ss) {
this.ss = ss;
}
public void run() {
for (int i = 0; i < 20; i++) {
WoTou wt = new WoTou(i);
ss.push(wt);
System.out.println("生产了" + wt);
try {
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
SyncStack ss = null;
Consumer(SyncStack ss) {
this.ss = ss;
}
public void run() {
for (int i = 0; i < 20; i++) {
WoTou wt = ss.pop();
System.out.println(wt);
System.out.println("消费了" + wt);
try {
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Socket通信
TCP 是面向连接的运输层协议。应用程序在使用 TCP 协议之前,必须先建立 TCP 连接。在传送数据完毕后,必须释放已经建立的 TCP 连接
一般的网络编程就叫 Socket 编程
端口号用来区分程序
1024 以下的端口号,随时可能会被占用
TCP 端口和 UDP 端口是分开的
每一个 65536 个端口
代码演示
TCPServer
package com.runnoob.TCP;
import java.io.DataInputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args) throws Exception {
//首先启动server之后再启动client
ServerSocket ss = new ServerSocket(8848);//一般会告诉他让他始终保持不动,让他在监听这个端口
while (true) {
Socket s = ss.accept();//阻塞式的,不连接他,就傻傻的等着
DataInputStream dis = new DataInputStream(s.getInputStream());//管子接收
System.out.println(dis.readUTF());
dis.close();
s.close();
System.out.println("A client connect!");
}
}
}
TCPClient
package com.runnoob.TCP;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class TCPClient {
public static void main(String[] args) throws IOException {
Socket s = new Socket("127.0.0.1", 8848);
java.io.OutputStream os = s.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF("hello server!");
dos.flush();
dos.close();
s.close();
}
}
总结
老弟作为15天尝试速通j2se基础的选手,中间学的怎么样,自然也就不用多说了,还需要很多的测试,实现,代码量的还需要好多好多的代码才能实现,如果中间有错误,请随时提出,感谢。
拜拜