Tianyi's Blog Tianyi's Blog
首页
  • 计算机网络
  • 操作系统
  • 计算机科学
  • Nginx
  • Vue框架
  • 环境配置
  • Java
  • JVM
  • Spring框架
  • Redis
  • MySQL
  • RabbitMQ
  • Kafka
  • Mirror Sites
  • Dev Tools
  • Docker
  • Jenkins
  • Scripts
  • Windows
  • 科学上网
  • 旅行
  • 网站日记
  • 软件
  • 电子产品
  • 杂野
  • 分类
  • 友情链接
GitHub (opens new window)

Tianyi

一直向前,永不停止
首页
  • 计算机网络
  • 操作系统
  • 计算机科学
  • Nginx
  • Vue框架
  • 环境配置
  • Java
  • JVM
  • Spring框架
  • Redis
  • MySQL
  • RabbitMQ
  • Kafka
  • Mirror Sites
  • Dev Tools
  • Docker
  • Jenkins
  • Scripts
  • Windows
  • 科学上网
  • 旅行
  • 网站日记
  • 软件
  • 电子产品
  • 杂野
  • 分类
  • 友情链接
GitHub (opens new window)
  • Java

    • web基础
    • 策略模式
    • Java基础语法
      • Java的基础语法
      • 面向对象思想
        • 设计模式实践
        • Factory
        • Eager Initialization
        • Lazy Initialization
        • builder模式
        • 代理模式
        • 和其他语言的对比
      • 剩余没整的部分:
    • JavaWeb-Base
    • Optional处理空指针,这几招你会了吗?
    • 并发编程的艺术
    • 并发编程工具
    • 一个简单的 web 服务器实例
    • 小笔记-线程池
    • 小笔记-JUC入门
  • Golang

  • JVM的奇妙世界

  • Spring

  • Spring增强封装

  • Redis

  • MySQL

  • RabbitMQ

  • Kafka

  • 分享

  • 后端
  • Java
tianyi
2024-02-16
目录

Java基础语法

首先我们今天去先探讨一下Java的基础语法,然后是Java的一些语法糖,会讲一些比较坑的点

# Java的基础语法

  • 首先有位运算这些最基础的东西,让我们先认识一下代码世界的基础文字:0、1
    • 数据类型:数字(整型、浮点型)、文字符号(字符型)、逻辑符号(布尔型)。我举一个例子:1+1数学题,如何保存这个题目信息?在写程序的时候会写到如果这个题目是一个小学生出的题,或者是一个哲学家出的题,会进入到不同的程序进行处理。所以布尔型是计算机世界一个很重要的语言胶水。
      • byte、short、int、long、Char、Boolean
      • float占32位,(1位符号位,8位2的幂指数位,23位底数位)极限值:2*2^127
      • double占64位(1位符号、11位幂指数位、52位底数位<=>精确度位,科学计数法的数字,小数点之后的位数),在十进制下是双精度<=>更精确(但永远不如整型确定!)
  • 代码是怎么跑起来的?写Java代码其实就是写一个一个的.Java文件,我们运行的程序就是.Java文件。我们把这些交了文件写好了之后,他就会交给JVM去运行,Java的虚拟机首先将我们的 Java编译为字节码文件,然后再将这个字节码文件编译为各个操作系统的可执行文件。
  • jvm内存结构,有stack heap 程序区等。
    • Jvm虚拟机其实就是一个Java的虚拟系统,里面也会包含操作系统的一些经典的实现,例如程序计数器,堆栈等等
    • Java虚拟机的栈,在程序运行到某个方法的时候就会用到,方法执行的时候,程序会开拓一个区域。叫做战争,战争用来存储函数的局部变量操作数栈,也就是一些存储号,动态链接就是我引入其他原生库的链接方法,出口就是我的函数结束之后指向的地址的信息
    • 本地方法占native method stack跟jbl的战很像,区别只是他执行的不是Java代码,执行的是其他语言的代码。但是它只用来执行本地方法就是本地代码实现的方法,可能是由其他地方导入进来的库( C语言或者是C++等语言编写的)
    • Stack(存局部变量)、Heap(存放Java对象)、方法区(字节码文件)
    • 堆是整个虚拟机中最大的内存区域,它可以被所有的线程共享。不同带的虚拟机,为了优化整体的运行效率,节省内存空间,jvm开发了新生代老年代不同区域的垃圾回收策略,并随着jvm的版本更新不停迭代
    • 方法区method area,方法区也被称为永久代(Permanent Generation),在 Java 8 之后被元空间(Metaspace)所取代。存放常量池和类信息的地方
      • 运行时常量池:运行时常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用。
  • 类和对象的理解, Java是面向对象的语言,所有的代码都是放在类里面的。
  • 转义字符:
    • 正斜杠'/'的斜率是正的,反斜杠'\\'的斜率是负;
    • Backslash \\:反斜杠一般是WINDOWS的地址分隔符
    • Slash / :这个符号是我们比较常用的,表示or
  • for循环:
    • for的执行顺序:①对变量预处理、②{for的body主体}、③继续条件的判断、④步进语句
    • for是while语句的简写版
  • 数组
    • 数组声明<==>创造一个盒子,装着同一种类型的东西
      • new创建新数组,new后面的东西在Heap堆中,不可更改
    • 数组的复制:
      • System.arraycopy(src,srcPos, newarr, newarrPos, length);【底层为C,共享同一对象】【大数组时效率高】
      • for循环遍历:不能往小杯子里放,不然出现“ArrayIndexOutOfBoundsException”【最易理解】【适合小数组】
      • int[] = Arrays.copyOf(arr,arr.length)【可控新数组长度】【代码里面含有System.arraycopy】【效率最低】
      • newarr = arr.clone();【两个数组还是共享同一对象】
    • 数组的排序
      • Arrays类的sort()方法:可以直接对数组进行升序排列,返回排号的序给数组本身。
  • 方法、函数的理解:一个个函数就是一个个黑盒,输入一些东西,输出一些东西。而工程化的语言需要更多的限定输入输出的内容是什么?就有了方法可见范围修饰符、方法名、入参、返回值类型
    • 函数的定义:函数是一段可以重复使用的代码块,它是一个独立的模块,用于执行特定的任务。函数的优点:代码重用、模块化、简化代码、提高可读性、提高可维护性
    • 方法有修饰符、返回值类型、方法名称、参数
    • 修饰符(限定访问)
      • 在Java中,如果一个文件中有且仅有一个public修饰的类,那么该文件的名称应该与该public类的名称相同,并且扩展名为".java"。这是Java的命名规范之一,可以确保代码的可读性和可维护性。
    • void/return(返回值类型)

# 面向对象思想

面向对象是一种代码编程思维,天天都在使用。必须灵活掌握

既然是面向对象,那么首先就要注意Java的标准类:JavaBean
1.  所有的成员变量都要使用private关键字修饰
2.  为每一个成员变量编写Getter/Setter方法
3.  编写一个无参数的构造函数
4.  编写一个全参数的构造函数
1
2
3
4
5

类就是群体(模板),具备实例对象的向上抽象涵义。例如人类就是类,每个人向上所属都是属于一个共同的类——人类;实例是具体的对象,人就是人类的实例化/对象

  • 构造方法:减少代码量,使类具有更好的封装性。
  • toString方法
    • 当你直接打印(print)一个对象时,如果该对象的类没有重写(override)toString()方法,那么默认会调用Object类中的toString()方法。在类里面重写这个方法就可以让外界了解类里面有什么东西。如果没有重写,输出的是该对象的哈希码的字符串。

继承性:使得子类具有父类的属性和方法,还可以在子类中重新定义,以及追加属性和方法 方法重写:子类不满意合同,所以要重写写一份合同

  • 封装性:类包含了对象的属性和行为/方法:人都有年龄、性别、名字、以及一些隐藏属性:思维高度、金钱、社会关系,(可以看作在类里面用private修饰的成员变量);人可以吃饭、看电视、玩游戏、睡觉、学习,都是人的行为(也就是人类的方法)。将各种人类属性抽象到人类类中,就是类的封装性;

  • 继承性:例如我继承了父类有的功能,他的煮饭方法是公开的,那么我也会。我也可以增加新的方法——打王者荣耀,但是我的父亲不会,没有这个技能;(回顾过去,展望未来,对子类的拓展);

  • 多态性:同样的方法,在不同对象中执行得不一样。(前提:需要有继承、重写、引父new子)

  • Static修饰的类变量和方法:共享

  • 静态成员方法只能访问静态成员:共享的函数只能访问共享的数据

# 设计模式实践

设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结,其中最出名的当属 Gang of Four (GoF) 的分类了,他们将设计模式分类为 23 种经典的模式,根据用途我们又可以分为三大类,分别为创建型模式、结构型模式和行为型模式。

这样设计是因为所有的设计模式都是为了保证封装性,抽象性、可扩展,也是为了代码整体的优雅,提高代码的清晰度。为了方便后续代码的维护。这样就有了以下的原则需要遵守

  1. 面向接口编程,而不是面向实现。这个很重要,也是优雅的、可扩展的代码的第一步,这就不需要多说了吧。
  2. 职责单一原则。每个类都应该只有一个单一的功能,并且该功能应该由这个类完全封装起来。
  3. 对修改关闭,对扩展开放。对修改关闭是说,我们辛辛苦苦加班写出来的代码,该实现的功能和该修复的 bug 都完成了,别人可不能说改就改;对扩展开放就比较好理解了,也就是说在我们写好的代码基础上,很容易实现扩展。

设计模式也就是实现一个程序的方式,有写得丑的,也有写得好看的,优雅的。程序主要就是几步:初始化、处理、返回这几个步骤,所以设计模式也是围绕这几个方面展开的。

# Factory

  • 简单地说,简单工厂模式通常就是这样,一个工厂类 XxxFactory,里面有一个静态方法,根据我们不同的参数,返回不同的派生自同一个父类(或实现同一接口)的实例对象。我们强调职责单一原则,一个类只提供一种功能,FoodFactory 的功能就是只要负责生产各种 Food。
  • 工厂模式:需要使用两个或两个以上的工厂。二级工厂模式就出场了。
  • 抽象工厂模式:
    • 产品族的概念,它代表了组成某个产品的一系列附件的集合。保证肯定不存在兼容问题。
    • 抽象工厂的问题也是显而易见的,比如我们要加个显示器,就需要修改所有的工厂,给所有的工厂都加上制造显示器的方法。这有点违反了对修改关闭,对扩展开放这个设计原则。

# Eager Initialization

饿汉模式:很急的模式

public class Singleton {
    // 首先,将 new Singleton() 堵死
    private Singleton() {};
    // 创建私有静态实例,意味着这个类第一次使用的时候就会进行创建
    private static Singleton instance = new Singleton();

    public static Singleton getInstance() {
        return instance;
    }
    // 瞎写一个静态方法。这里想说的是,如果我们只是要调用 Singleton.getDate(...),
    // 本来是不想要生成 Singleton 实例的,不过没办法,已经生成了
    public static Date getDate(String mode) {return new Date();}
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# Lazy Initialization

通过私有静态内部类的方式来创建单例对象。这个内部类只有在需要时才会被加载,因此实现了延迟加载的效果。

public class Food {
	private Food() {};
    // 主要是使用了 嵌套类可以访问外部类的静态属性和静态方法 的特性
	private class SubFood {
		private static Food instance = new Food();
	}
	
	public static Food getInstance() {
		return SubFood.instance;
	}

}
1
2
3
4
5
6
7
8
9
10
11
12

学校里面教的是:

public class Food {
	private Food() {};
	
	private static Food instance = null;
	
	public static Food getInstance() {
		if(instance == null) {
			synchronized(Singleton.class) {
				if(instance == null) {
					instance = new Food();
				}
			}
		}
		return instance;
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# builder模式

建造者模式核心是:先把所有的属性都设置给 Builder,然后 build() 方法的时候,将这些属性复制给实际产生的对象。


使用 lombok;------》 @Builder

User user = new User().setName("").setPassword("").setAge(20);
1
2
3
4

创建型模式总体上比较简单,它们的作用就是为了产生实例对象,算是各种工作的第一步了,因为我们写的是面向对象的代码,所以我们第一步当然是需要创建一个对象了。

简单工厂模式最简单;工厂模式在简单工厂模式的基础上增加了选择工厂的维度,需要第一步选择合适的工厂;抽象工厂模式有产品族的概念,如果各个产品是存在兼容性问题的,就要用抽象工厂模式。单例模式就不说了,为了保证全局使用的是同一对象,一方面是安全性考虑,一方面是为了节省资源;建造者模式专门对付属性很多的那种类,为了让代码更优美;原型模式用得最少,了解和 Object 类中的 clone() 方法相关的知识即可。

# 代理模式

代理模式说白了就是做 “方法包装” 或做 “方法增强”。在面向切面编程中,其实就是动态代理的过程。比如 Spring 中,我们自己不定义代理类,但是 Spring 会帮我们动态来定义代理,然后把我们定义在 @Before、@After、@Around 中的代码逻辑动态添加到代理中。

说到动态代理,又可以展开说,Spring 中实现动态代理有两种,一种是如果我们的类定义了接口,如 UserService 接口和 UserServiceImpl 实现,那么采用 JDK 的动态代理,感兴趣的读者可以去看看 java.lang.reflect.Proxy 类的源码;另一种是我们自己没有定义接口的,Spring 会采用 CGLIB 进行动态代理,它是一个 jar 包,性能还不错。

将具体对象注入到适配器中,帮助适配器实现部分方法

一个采用继承,一个采用组合;

类适配属于静态实现,对象适配属于组合的动态实现,对象适配需要多实例化一个对象。

总体来说,对象适配用得比较多。居然是符合组合》继承的思想

比较对象适配器模式和代理模式,在代码结构上,它们很相似,都需要一个具体的实现类的实例。但是它们的目的不一样,代理模式做的是增强原方法的活;适配器做的是适配的活,为的是提供“把鸡包装成鸭,然后当做鸭来使用”,而鸡和鸭它们之间原本没有继承关系。——源自https://javadoop.com/post/design-pattern#toc_7

# 和其他语言的对比

  • Go语言没有类和继承的概念,因此它不支持传统意义上的继承。在Go中,通过组合和接口来实现类似继承的功能。

# JVM等等:

# 剩余没整的部分:

Java p是用来反编译Java类的文件显示内容的,如果不加任何参数的话,它就只显示类的方法和字段,不会显示其他更多的信息(先不讨论这个,这个等到jvm的时候再弄)

还有的就是关于Java里面比较常用的Java点uto里面的集合源码。还要去看一下比较经典的集合,它是如何用Java语言去实现这些集合算法的

还有就是web服务器如何去理解数据是怎么扭转在客户端以及服务端数据是怎么扭转的

Java的异常处理异常的统一化设计

完善页面 (opens new window)
策略模式
JavaWeb-Base

← 策略模式 JavaWeb-Base→

最近更新
01
JDK
02-23
02
BadTasteCode && 优化
09-11
03
Gradle 实践操作指南及最佳实践
09-11
更多文章>
Theme by Vdoing | Copyright © 2021-2025 Tandy | 粤ICP备2023113440号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式