这篇Java基础快速入门学习教程,让我至少少走3个月弯路

作为刚刚接触java的小白,今天这篇文章的目的是帮助大家快速入门java,少走弯路

Java 基本语法、Java 平台应用、Java的核心概念:JVM、JDK、JRE以及Java面向对象思想,同时要会学到如何在系统中搭建Java开发环境,以及如何利用第三方工具进行Java程序的开发。

还有记住学习Java语言最重要的是两点:

  1. 学习步骤/方法
  2. 学习资源

找到适合自己的学习方式,找到适合自己现阶段的学习资料,学习的过程中最好记笔记,因为好记性不如烂笔头。

推荐Java基础学习教程

https://www.bilibili.com/video/BV1Rx411876f

从中我们可以学习到很多类型的设计模式,其中包括工厂模式、抽象工厂模式、单例模式、适配器模式、观察者模式、装饰者模式等等。

建立起来环境了,最重要的是练习,熟能生巧,在不断的练习中去加深自己对程序语言的理解。

作为新手你可以去找一本比较好的经典的入门书籍,现在网络上也有非常多的资料,图文或者视频都可以,根据个人喜好选择来练习。

做Java开发的话,你需要了解这三个术语,叫SDK、API跟Lib,分别表示软件开发套件,应用编程接口和库。这三者之间其实有一定的联系,或者是交叉。

总体来说,它们都是给我们提供的一些封装了底层功能的基础设施。这些东西通常体现为我们所经常说的“框架”。事实上要成为一个资深的Java开发者,对各种API和框架的学习,可能是花时间最多的一个地方。

Java Web全栈开发的推荐学习内容,简单总结一下,大概包括下面这些内容。

每一部分都可以细化成很多知识点,这只是一个粗略的罗列。把它当做技术地图就好了。

开发环境的建立与项目管理:

Eclipse、IDEA、Maven和Git

Java编程基础:

Java基础无非就是需要知道Java概述、Java语言基础、面向对象、异常处理、常用类、数组和集合、IO流、线程、反射等。

● Java概述:你要知道Java一些基本的知识,比如优点,什么时候诞生的,目前的发展状况如何。

● Java语言基础:要学会一些标识符、变量、数据类型、运算符、控制语句、方法等知识。

● 面向对象:Java是一门面向对象开发的编程语言。

● 异常处理:计算机虽然不会出错,但毕竟是人类制造出来的,所以在编写代码的时候可能会出现一些异常错误,出了异常之后,需要程序员去进行处理。

● 常用类:Java给程序员提供了强大的API,使我们在开发的时候变得轻松许多,Java为我们提供的那些类,常用的那些,你一定要掌握。

● 数组和集合:这块内容在以后工作的时候100%会用到,所以一定要作为重点来学习。

● IO流:使用Java读取或者传输文件的时候会用到IO流,举个例子,你从网上买了一辆自行车,商家给你邮寄过来的应该是一些零件(组装好的自行车不利于邮寄),你需要自己动手去组装,同样,如果你想把某个文件从一个地方读取到另一个地方,使用IO流会极大的方便你的操作。

● 线程:通过线程,可以让程序更高效的工作,当然,如果使用不当,也会造成一堆问题。

● 反射:想要以后自己写一些框架,反射知识必不可少。

一般把以上的内容学会之后,Java基础的知识也就掌握了。

前端开发技术:

HTML、CSS、JavaScript基础

数据库:

数据库知识是程序员必须掌握的,包括建库、建表、增删改查、存储过程编写等等,熟悉并掌握sql语言的使用对程序员来说是非常重要的。

JDBC

JDBC是Java操作数据库的API,通过JDBC能让Java建立与数据库的沟通,掌握JDBC是Java程序员的必修内容。这部分内容包括驱动程序管理器(DriverManager)、连接(Connection)、容器(Statement、PreparedStatement、CallableStatement)、结果集(ResultSet)等类和接口的使用。

另外要掌握Java操作数据库的结构划分,掌握DAO框架的使用。

Spring基础:

依赖注入IoC、面向切面编程AOP、SpringBoot

框架:

Spring MVC、mybatis、Struts等,包括URL路由、模板、表单、Session、等知识

还有专门提一下JSP和Servlet,虽然现在各种成熟的MVC框架已经让Java Web开发基本很少使用JSP和Servlet的原生功能了,基本都做了一层封装。但是这部分基础知识建议初学者还是要认真学习。

Java自己核心的一些包和技术无非是:集合,泛型,IO,多线程,类加载机制,反射,代理。

掌握这些,Java就算入门了。从Java零基础快速入门学好Java语言。初学者最重要的就是不要懒!

三十分钟入门基础Go(Java小子版)

Go(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态、强类型、编译型语言。Go 语言语法与 C 相近,但功能上有:内存安全,GC,结构形态及 CSP-style 并发计算。

本篇文章适用于学习过其他面向对象语言(Java、Php),但没有学过Go语言的初学者。文章主要从Go与Java功能上的对比来阐述Go语言的基础语法、面向对象编程、并发与错误四个方面。

Go语言的基础语法与常规的编程语言基本类似,所不同的有声明变量的方式,数组、切片、字典的概念及功能与Java不太相同,不过Java中这些数据结构都可以通过类比功能的方式在Go中使用。

Go语言中有两种方式

1.使用var关键字声明,且需要注意的是,与大多数强类型语言不同,Go语言的声明变量类型位于变量名称的后面。Go语句结束不需要分号。

var num int

var result string = \”this is result\”

2.使用:=赋值。

num := 3 等同于 var num int = 3

其中变量的类型会根据右侧的值进行匹配,例如\”3\”会匹配为int,\”3.0\”会匹配为float64,\”result\”会匹配为string。

使用const来声明一个常量,一个常量在声明后不可改变。

const laugh string = \”go\”

只声明未赋值的变量,其值为nil。类似于java中的“null”

没有明确初始值的变量声明会被赋予它们的 零值

零值是:

  • 数值类型为 0,
  • 布尔类型为 false,
  • 字符串为 \”\”(空字符串)。

使用func关键字来定义一个方法,后面跟方法名,然后是参数,返回值(如果有的话,没有返回值则不写)。

func MethodName(p1 Parm, p2 Parm) int{}

Go 函数与其他编程语言一大不同之处在于支持多返回值,这在处理程序出错的时候非常有用。例如,如果上述 add 函数只支持非负整数相加,传入负数则会报错。

在 Go 语言中,无论是变量、函数还是类属性和成员方法,它们的可见性都是以包为维度的,而不是类似传统面向编程那样,类属性和成员方法的可见性封装在所属的类中,然后通过 private、protected 和 public 这些关键字来修饰其可见性。

Go 语言没有提供这些关键字,不管是变量、函数,还是自定义类的属性和成员方法,它们的可见性都是根据其首字母的大小写来决定的,如果变量名、属性名、函数名或方法名首字母大写,就可以在包外直接访问这些变量、属性、函数和方法,否则只能在包内访问,因此 Go 语言类属性和成员方法的可见性都是包一级的,而不是类一级的。

假如说一个名为domain的文件夹下有3个.go文件,则三个文件中的package都应为domain,其中程序的入口main方法所在的文件,包为main

对于学过C语言来说,指针还是比较熟悉的,我所理解的指针,其实就是一个在内存中实际的16进制的地址值,引用变量的值通过此地址去内存中取出对应的真实值。

与Java语言的if基本相同

数组功能与Java语言类似,都是长度不可变,并且可以使用多维数组,也可以通过arrays[i]来存储或获取值。

数组使用较为简单,但是存在着难以解决的问题:长度固定

例如当我们在程序中需要一个数据结构来存储获取到的所有用户,因为用户数量是会随着时间变化的,但是数组其长度却不可改变,所以数组并不适合存储长度会发生改变的数据。因此在Go语言中通过使用切片来解决以上问题。

切片相比于Java来说是一种全新的概念。在Java中,对于不定长的数据存储结构,可以使用List接口来完成操作,例如有ArrayList与LinkList,这些接口可以实现数据的随时添加与获取,并没有对长度进行限制。但是在Go中不存在这样的接口,而是通过切片(Slice)来完成不定长的数据长度存储

切片与数组最大的不同就是切片不用声明长度。但是切片与数组并非毫无关系,数组可以看作是切片的底层数组,而切片则可以看作是数组某个连续片段的引用。切片可以只使用数组的一部分元素或者整个数组来创建,甚至可以创建一个比所基于的数组还要大的切片:

切片的长度就是它所包含的元素个数。

切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。

切片 s 的长度和容量可通过表达式 len(s) 和 cap(s) 来获取。

切片的长度从功能上类比与Java中List的size(),即通过len(slice)来感知切片的长度,即可对len(slice)进行循环,来动态控制切片内的具体内容。切片的容量在实际开发中运用不多,了解其概念即可。

模拟上述提到的问题使用切片解决方案

字典也可称为 ‘键值对’ 或 ‘key-value’,是一种常用的数据结构,Java中有各种Map接口,常用的有HashMap等。在Go中通过使用字典来实现键值对的存储,字典是无序的,所以不会根据添加顺序来保证数据的顺序。

众所周知,在面向对象的语言中,一个类应该具有属性、构造方法、成员方法三种结构,Go语言也不例外。

Go语言中并没有明确的类的概念,只有struct关键字可以从功能上类比为 面向对象语言中的“类” 。比如要定义一个学生类,可以这么做:

Go中的成员方法声明与其他语言不大相同。以Student类为例,

接口在 Go 语言中有着至关重要的地位,如果说 goroutine 和 channel 是支撑起 Go 语言并发模型的基石,那么接口就是 Go 语言整个类型系统的基石。Go 语言的接口不单单只是接口,下面就让我们一步步来探索 Go 语言的接口特性。

和类的实现相似,Go 语言的接口和其他语言中提供的接口概念完全不同。以 Java、PHP 为例,接口主要作为不同类之间的契约(Contract)存在,对契约的实现是强制的,体现在具体的细节上就是如果一个类实现了某个接口,就必须实现该接口声明的所有方法,这个叫「履行契约」:

这个时候,如果有另外有一个接口 iTemplate2 声明了与 iTemplate 完全一样的接口方法,甚至名字也叫 iTemplate,只不过位于不同的命名空间下,编译器也会认为上面的类 Template 只实现了 iTemplate 而没有实现 iTemplate2 接口。

这在我们之前的认知中是理所当然的,无论是类与类之间的继承,还是类与接口之间的实现,在 Java、PHP 这种单继承语言中,存在着严格的层级关系,一个类只能直接继承自一个父类,一个类也只能实现指定的接口,如果没有显式声明继承自某个父类或者实现某个接口,那么这个类就与该父类或者该接口没有任何关系。

我们把这种接口称为侵入式接口,所谓「侵入式」指的是实现类必须明确声明自己实现了某个接口。这种实现方式虽然足够明确和简单明了,但也存在一些问题,尤其是在设计标准库的时候,因为标准库必然涉及到接口设计,接口的需求方是业务实现类,只有具体编写业务实现类的时候才知道需要定义哪些方法,而在此之前,标准库的接口就已经设计好了,我们要么按照约定好的接口进行实现,如果没有合适的接口需要自己去设计,这里的问题就是接口的设计和业务的实现是分离的,接口的设计者并不能总是预判到业务方要实现哪些功能,这就造成了设计与实现的脱节。

接口的过分设计会导致某些声明的方法实现类完全不需要,如果设计的太简单又会导致无法满足业务的需求,这确实是一个问题,而且脱离了用户使用场景讨论这些并没有意义,以 PHP 自带的 SessionHandlerInterface 接口为例,该接口声明的接口方法如下:

用户自定义的 Session 管理器需要实现该接口,也就是要实现该接口声明的所有方法,但是实际在做业务开发的时候,某些方法其实并不需要实现,比如如果我们基于 Redis 或 Memcached 作为 Session 存储器的话,它们自身就包含了过期回收机制,所以 gc 方法根本不需要实现,又比如 close 方法对于大部分驱动来说,也是没有什么意义的。

正是因为这种不合理的设计,所以在编写 PHP 类库中的每个接口时都需要纠结以下两个问题(Java 也类似):

  1. 一个接口需要声明哪些接口方法?
  2. 如果多个类实现了相同的接口方法,应该如何设计接口?比如上面这个 SessionHandlerInterface,有没有必要拆分成多个更细分的接口,以适应不同实现类的需要?

接下我们来看看 Go 语言的接口是如何避免这些问题的。

在 Go 语言中,类对接口的实现和子类对父类的继承一样,并没有提供类似 implement 这种关键字显式声明该类实现了哪个接口,一个类只要实现了某个接口要求的所有方法,我们就说这个类实现了该接口

例如,我们定义了一个 File 类,并实现了 Read()、Write()、Seek()、Close() 四个方法:

假设我们有如下接口(Go 语言通过关键字 interface 来声明接口,以示和结构体类型的区别,花括号内包含的是待实现的方法集合):

尽管 File 类并没有显式实现这些接口,甚至根本不知道这些接口的存在,但是我们说 File 类实现了这些接口,因为 File 类实现了上述所有接口声明的方法。当一个类的成员方法集合包含了某个接口声明的所有方法,换句话说,如果一个接口的方法集合是某个类成员方法集合的子集,我们就认为该类实现了这个接口。

与 Java、PHP 相对,我们把 Go 语言的这种接口称作非侵入式接口,因为类与接口的实现关系不是通过显式声明,而是系统根据两者的方法集合进行判断。这样做有两个好处:

  • 其一,Go 语言的标准库不需要绘制类库的继承/实现树图,在 Go 语言中,类的继承树并无意义,你只需要知道这个类实现了哪些方法,每个方法是干什么的就足够了。
  • 其二,定义接口的时候,只需要关心自己应该提供哪些方法即可,不用再纠结接口需要拆得多细才合理,也不需要为了实现某个接口而引入接口所在的包,接口由使用方按需定义,不用事先设计,也不用考虑之前是否有其他模块定义过类似接口。

这样一来,就完美地避免了传统面向对象编程中的接口设计问题。

对于任何一个优秀的语言来说,并发处理的能力都是决定其优劣的关键。在Go语言中,通过Goroutine来实现并发的处理。

Go语言中没有像Java那么多的锁来限制资源同时访问,只提供了Mutex来进行同步操作。

多协程之间通过Channel进行通信,从功能上可以类比为Java的volatile关键字。

ch := make(chan int) 声明一个int型的Channel,两个协程之间可以通过ch进行int数据通信。

通过Channel进行数据传输。

Go 语言错误处理机制非常简单明了,不需要学习了解复杂的概念、函数和类型,Go 语言为错误处理定义了一个标准模式,即 error 接口,该接口的定义非常简单:

其中只声明了一个 Error() 方法,用于返回字符串类型的错误消息。对于大多数函数或类方法,如果要返回错误,基本都可以定义成如下模式 —— 将错误类型作为第二个参数返回:

然后在调用返回错误信息的函数/方法时,按照如下「卫述语句」模板编写处理代码即可:

非常简洁优雅。

defer用于确保一个方法执行完成之后,无论执行结果是否成功,都要执行defer中的语句。类似于Java中的try..catch..finally用法。例如在文件处理中,无论结果是否成功,都要关闭文件流。

Go语言中没有太多的异常类,不像Java一样有Error、Exception等错误类型,当然也没有try..catch语句。

Panic(恐慌),意味在程序运行中出现了错误,如果该错误未被捕获的话,就会造成系统崩溃退出。例如一个简单的panic:a := 1/0。

就会引发panic: integer divide by zero。

其中第一行表示出问题的协程,第二行是问题代码所在的包和函数,第三行是问题代码的具体位置,最后一行则是程序的退出状态,通过这些信息,可以帮助你快速定位问题并予以解决。

当有可以预见的错误时,又不希望程序崩溃退出,可以使用recover()语句来捕获未处理的panic。recover应当放在defer语句中,且该语句应该在方法中前部,避免未能执行到defer语句时就引发了系统异常退出。

可以看到,虽然会出现异常,但我们使用recover()捕获之后,就不会出现系统崩溃退出的情形,而只是将该方法结束。其中fmt.Printf(\”%d / %d = %d\\n\”, i, j, k)语句并没有执行到,因为代码执行到他的上一步已经出现异常导致该方法提前结束。4 recover

当有可以预见的错误时,又不希望程序崩溃退出,可以使用recover()语句来捕获未处理的panic。recover应当放在defer语句中,且该语句应该在方法中前部,避免未能执行到defer语句时就引发了系统异常退出。

可以看到,虽然会出现异常,但我们使用recover()捕获之后,就不会出现系统崩溃退出的情形,而只是将该方法结束。其中fmt.Printf(\”%d / %d = %d\\n\”, i, j, k)语句并没有执行到,因为代码执行到他的上一步已经出现异常导致该方法提前结束。

通过以上的学习,大家可以以使用为目的的初步了解到go的基础语法,但是仅凭本文想要学明白go是完全不够的。例如go的最大优势之一“协程”,由于文章目的就没有特别详细展开,有兴趣的同学可以继续学习。

本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com

点赞 0
收藏 0

文章为作者独立观点不代本网立场,未经允许不得转载。