java从0到1的学习
基础知识
先讲讲Java语言的几个重要特性
- Java语言是面向对象的语言(oop)
- Java语言是健壮的,Java 的强类型机制、异常处理、垃圾的自动收集等是 Java 程序健壮性的重要保证。
- Java语言是跨平台型的语言
- Java语言是强类型的语言
- Java语言是解释型语言
- 解释型语言:javascript,PHP,java 编译性语言:C/C++
什么是解释性语言?就是编译后的代码不能直接被机器执行的,需要解释器去执行
一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作。
对象和类
- 对象:对象是类的一个实例,有状态和行为。
- 类:类是一个模板,它描述一类对象的行为和状态。
- 方法:方法就是行为,一个类可以有很多方法。逻辑运算、数据修改以及所有动作都是在方法中完成的。
- 变量:变量就是状态,一个类可以有很多变量。类的状态都是由变量去决定的
- 实例变量:每个对象都有独特的实例变量,对象的状态由这些实例变量的值决定。
比如,我们类可以看成是一类动物,行为和状态就指的是动物的一些特点,而对象就可以具体到哪些动物,拿一条狗来举例,它的状态有:名字、品种、颜色,行为有:叫、摇尾巴和跑。这些行为和状态就是可以看成是一个个实例变量和方法,而具体的名字等等就是变量的值,具体的行为就是方法了。在java中状态可以看成是成员属性(变量),而行为就是成员方法
因为之前学过php,所以对这些的理解的话其实大致上是一样的。
程序员的第一个程序必然就是hello world了,那我们先拿这个代码来分析一下
1 | public class HelloWorld { |
类声明
- public:这是一个访问修饰符,表示该类可以被其他类访问。
- class:关键字,用于声明一个类。
- HelloWorld:这是类的名称,必须与文件名相同(HelloWorld.java)。
main主方法:
- public:修饰符,表示该方法可以被任何其他类调用。
- static:关键字,表示该方法属于类,而不是类的实例。程序运行时不需要先创建类的对象。
- void:表示该方法没有返回值。
- main:方法名称,Java 程序的入口点。JVM(Java Virtual Machine)会从这里开始执行程序。
- String[] args:这是一个参数,表示可以接收命令行输入的字符串数组。
输出语句
- System.out:这是 Java 中的一个输出流对象,用于向控制台打印信息。
- println:这是一个方法,用于打印括号内的内容,并在打印后换行。
- **”Hello World”**:这是要输出的字符串。
代码编辑好后运行的话就是在cmd窗口进行操作
javac 是 Java 编译器,它的作用是读取 .java
文件并将其编译成 .class
文件,一旦生成了 .class
文件,就可以使用 java
命令来运行程序
编写 Java 程序时,应注意以下几点:
- 大小写敏感:Java 是大小写敏感的,这就意味着标识符 Hello 与 hello 是不同的。
- 类名和接口名:对于所有的类来说,类名的首字母应该大写。如果类名由若干单词组成,那么每个单词的首字母应该大写,例如 MyFirstJavaClass 。
- 变量名和方法名:所有的方法名都应该以小写字母开头。如果方法名含有若干单词,则后面的每个单词首字母大写。
- 常量名:所有字母都大写。多单词时每个单词用下划线隔开
常量是特殊的变量!
- 源文件名:源文件名必须和类名相同。当保存文件的时候,你应该使用类名作为文件名保存(切记 Java 是大小写敏感的),文件名的后缀为 .java。(如果文件名和类名不相同则会导致编译错误)。
- 主方法入口:所有的 Java 程序由 public static void main(String[] args) 方法开始执行。
java标识符命名规则
Java 所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符
- 开头不能是数字
- 首字符之后可以是字母(A-Z 或者 a-z),美元符($)、下划线(_)或数字的任何字符组合
- 关键字不能用作标识符
- 标识符是大小写敏感的
- 合法标识符举例:age、$salary、_value、__1_value
- 非法标识符举例:123abc、-salary
Java修饰符
和php一样,Java可以使用修饰符来修饰类中方法和属性。主要有两类修饰符
- 一种是可访问修饰符:public(公共),protected(受保护),private(私有),default(默认)
- public(公共)
- 任何其他类都可以访问。没有访问限制。
- 示例:
public class MyClass {}
- protected(受保护)
- 仅限于同一个包中的类以及子类(无论是否在同一个包中)访问。
- 示例:
protected int myVariable;
- default(默认)
- 如果没有指定任何访问修饰符,则为默认访问权限(包私有)。仅限于同一个包中的类访问。
- 示例:
class MyClass {}
- private(私有)
- 仅限于该类内部访问,其他类无法访问。
- 示例:
private int myVariable;
- 一种是非访问修饰符:
- static(静态)
- 表示该成员属于类而不是类的实例,可以通过类名直接访问。
- 示例:
static int myStaticVariable;
- final(最终)
- 用于声明类、方法或变量。
- 类:表示该类不能被继承。
- 示例:
final class MyFinalClass {}
- 方法:表示该方法不能被子类重写。
- 示例:
final void myMethod() {}
- 变量:表示该变量的值不能被改变(常量)。
- 示例:
final int MY_CONSTANT = 10;
- abstract(抽象)
- 用于类和方法。
- 类:表示该类不能被实例化,通常用于为子类提供模板。
- 示例:
abstract class MyAbstractClass {}
- 方法:表示该方法没有实现,子类必须实现该方法。
- 示例:
abstract void myAbstractMethod();
- synchronized(同步)
- 用于方法或代码块,表示该方法或代码块在同一时间只能被一个线程访问,适用于多线程环境下的同步。
- 示例:
synchronized void myMethod() {}
- volatile(易失性)
- 用于变量,表示该变量可能会被多个线程修改,以确保每次读取变量时都从主内存中获取。
- 示例:
volatile int myVariable;
- transient(瞬态)
- 用于变量,表示该变量不应被序列化。当对象被序列化时,瞬态变量的值不会被保存。
- 示例:
transient int myTransientVariable;
java的注释
单行注释:以//开始
多行注释:以/*开始,以*/结束
文档注释:以 /** 开始,每行开头用*号开始以 */ 结束
java的继承
这个可以类似于寄生的过程,在 Java 中,一个类可以由其他类派生。如果你要创建一个类,而且已经存在一个类具有你所需要的属性或方法,那么你可以将新创建的类继承该类。
利用继承的方法,可以重用已存在类的方法和属性,而不用重写这些代码。被继承的类称为超类(super class),派生类称为子类(sub class)。
访问实例变量和方法
1 | /* 实例化对象 */ |
java的数据类型
Java 数据类型分为两大类:基本数据类型和引用数据类型。
基本数据类型:
- 整数类型:
byte
:1 字节,范围从 -128 到 127。short
:2 字节,范围从 -32,768 到 32,767。int
:4 字节,范围从 -2,147,483,648 到 2,147,483,647。long
:8 字节,范围为 -2^63 到 2^63-1。定义变量的时候需要在初始值后加上一个L,例如12345678L
- 浮点类型:
float
:单精度浮点型,4 字节,适合表示小数,范围约为 ±3.40282347E+38(有效位数约为 7 位)。定义变量的时候需要在结尾加上f,例如0.0fdouble
:双精度浮点型,8 字节,适合表示较大或较小的浮点数,范围约为 ±1.79769313486231570E+308(有效位数约为 15 位)。
- 字符类型:
char
:2 字节,表示单个字符,用单引号包裹,支持 Unicode 字符集,范围从'\u0000'
到'\uffff'
。
- 布尔类型:
boolean
:表示两个值之一,true
或false
,通常用于条件判断。
引用数据类型:
引用数据类型用于存储对象的引用,而不是对象本身。主要包括:
- 类(Class):
- Java 中的类可以定义用户自定义数据类型。通过类的实例化可以创建对象。
- 接口(Interface):
- 接口是抽象的一种类型,可以定义方法的签名,通常用于实现多态。
- 数组(Array):
- 数组是相同类型元素的集合,可以是基本数据类型的数组或引用数据类型的数组。
放个具体的例子来实验一下
1 | public class HelloWorld { |
输出结果
这个代码纯属是为了练练手才一个个打出来的,学编程还是建议多动手哈
特别说明一下啊关于这些数据类型的默认值(也就是当我们并没有给这些数据类型的变量进行赋值的时候的默认值)
int
,short
,long
,byte
的默认值是0。char
的默认值是\u0000
(空字符)。float
的默认值是0.0f
。double
的默认值是0.0d
。boolean
的默认值是false
。- 引用类型(类、接口、数组)的默认值是
null
。
说起这个数据类型我们不得不聊到存储的地址,基本数据类型的变量都是直接存储在栈中的,而引用数据类型的变量则分为两个区域,引用(指向堆的地址)存储在栈中,通过访问变量名称读取栈中的地址,进而我们去访问存储的数据
类型转化
类型转换主要分为两种:自动类型转换(隐式转换)和强制类型转换(显式转换)。
- 自动类型转换
小转大
当将一种较小范围的基本数据类型赋值给较大范围的基本数据类型时,Java 会自动进行转换
1 | byte->short,char—> int —> long—> float —> double |
说白了就是大的数据类型的范围可以容纳小的数据类型的所有范围
但是这里的话是没有boolean的,boolean是不能进行转换的
那我们怎么从大的数据类型转化成小的数据类型呢?这就是我们的强制类型转换了
- 强制类型转换
格式:
1 | (type)value |
type就是需要转换的数据类型了,例如从浮点数强制转化成整数,(int)131.4=131,但是要注意我们的值不能超过小类型的范围
声明变量
最好变量名是能清晰体现其用途的,比如我的名字的变量就是myName,用小写字母开头,后面的单词首字母大写
1 | static int a; |
java变量
变量的概念:
- 内存中的一个存储区域,该区域有自己的名称(变量名)和类型(数据类型)
- 和其他语言一样,变量需要先声明后使用
- Java是强类型语言,每个变量在声明的时候必须声明数据类型
- 变量只能作用在作用域内(最近的一对花括号中)
- 定义变量的格式:
1 | 数据类型 变量名 = 初始值(如果没有的话就是null) |
变量的分类(按声明的位置分)
- 局部变量
在方法、构造函数或代码块中声明的变量,只能在该特定方法、构造函数或代码块内访问。(方法中声明的变量)
- 类变量(静态变量)
使用 static
关键字声明的变量,属于类本身,而不是任何特定的实例。所有对象共享同一个类变量(应该就是类似于define常量)
- 由于静态变量是与类相关的,因此可以通过类名来访问静态变量,也可以通过实例名来访问静态变量。
- 常量和静态变量的区别,常量在编译时就已经确定了它的值,而静态变量的值可以在运行时改变。
- 成员变量
在类中声明,但不在方法内的变量,属于类的实例。每个对象都有自己的一份实例变量。(在类中的成员属性)
- 当一个对象被实例化之后,每个成员变量的值就跟着确定。
- 成员变量在对象创建的时候创建,在对象被销毁的时候销毁
这个直接理解成php中的对象和类里面的成员变量就可以了
然后我在教程中还发现了一种变量类型
- 参数变量
参数是方法或构造函数声明中的变量,用于接收调用该方法或构造函数时传递的值,参数变量的作用域只限于方法内部。(说白了就是函数的形参嘛)
前面几个比较好理解,最后一个参数变量我们来稍微讲一下
参数变量的值传递方式有两种:值传递和引用传递。
可以看成是c语言中的函数引用,值传递就是正常的传值,从形参到实参,实参可以是具体的值也可以是一个内存地址,值传递的特点是实参不会变,而引用传递的特点是实参也会改变。下面我会写一个具体的实例去进行讲解
1 | public class HelloWorld{ |
java运算符
- 算术运算符
操作符 | 描述 | 例子 |
---|---|---|
+ | 相加 | A + B 等于 30 |
- | 相减 | A – B 等于 -10 |
* | 相乘 | A * B等于200 |
/ | 相除 | B / A等于2 |
% | 相除后取模 | B%A等于0 |
++ | 自增 | B++ 或 ++B 等于 21 |
– | 自减 | B– 或 –B 等于 19 |
+ | 字符串拼接 | “He”+”llo”=”Hello” |
- 关系运算符
运算符 | 描述 | 例子 |
---|---|---|
== | 检查如果两个操作数的值是否相等,如果相等则条件为真。 | (1 == 0)为假。 |
!= | 检查如果两个操作数的值是否相等,如果值不相等则条件为真。 | (1 != 0) 为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是那么条件为真。 | (0> 1)为假。 |
< | 检查左操作数的值是否小于右操作数的值,如果是那么条件为真。 | (0 < 1)为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。 | (1> = 0)为假。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。 | (0 <= 1)为真。 |
- 位运算符
& | 如果相对应位都是1,则结果为1,否则为0 | (A&B),得到12,即0000 1100 |
---|---|---|
| | 如果相对应位都是 0,则结果为 0,否则为 1 | (A | B)得到61,即 0011 1101 |
^ | 如果相对应位值相同,则结果为0,否则为1 | (A ^ B)得到49,即 0011 0001 |
〜 | 按位取反运算符翻转操作数的每一位,即0变成1,1变成0。 | (〜A)得到-61,即1100 0011 |
<< | 按位左移运算符。左操作数按位左移右操作数指定的位数。 | A << 2得到240,即 1111 0000 |
>> | 按位右移运算符。左操作数按位右移右操作数指定的位数。 | A >> 2得到15即 1111 |
>>> | 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。 | A>>>2得到15即0000 1111 |
- 逻辑运算符
操作符 | 描述 | 例子 |
---|---|---|
& | 称为逻辑与运算符。无论真假都会执行右边运算 | 0<1&x=6结果是x=6 |
| | 称为逻辑或操作符。如果任何两个操作数任何一个为真,条件为真。 | (1 | 0)为真。 |
! | 称为逻辑非运算符。用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将得到false。 | !0为真。 |
&& | AND(短路)当且仅当两个操作数都为真,条件才为真。 | 一真为假 |
|| | OR(短路) | 一真为真 |
^ | 异或 | (1^1)为假 |
&和&&的区别:
- 单&时,左边无论真假,右边都会执行
- 双&时,如果左边为真则执行右边运算,如果为假则不执行
- 和”||“的区别同理,双|时左边为真右边则不执行
异或(“^”)”和(“|“)不同的是,对御^而言,左右结果为true时,结果为false
- 赋值运算符
= | 简单的赋值运算符,将右操作数的值赋给左侧操作数 | C = A + B将把A + B得到的值赋给C |
---|---|---|
+ = | 加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数 | C + = A等价于C = C + A |
- = | 减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数 | C - = A等价于C = C - A |
* = | 乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数 | C * = A等价于C = C * A |
/ = | 除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数 | C / = A,C 与 A 同类型时等价于 C = C / A |
(%)= | 取模和赋值操作符,它把左操作数和右操作数取模后赋值给左操作数 | C%= A等价于C = C%A |
<< = | 左移位赋值运算符 | C << = 2等价于C = C << 2 |
>> = | 右移位赋值运算符 | C >> = 2等价于C = C >> 2 |
&= | 按位与赋值运算符 | C&= 2等价于C = C&2 |
^ = | 按位异或赋值操作符 | C ^ = 2等价于C = C ^ 2 |
| = | 按位或赋值操作符 | C | = 2等价于C = C | 2 |
值得注意的是,在我们的变量为一个对象的时候,关系运算符比较的是两个变量的地址而不是字符串
其他运算符:三目运算符
格式
1 | 布尔表达式?执行语句1:执行语句2 |
若表达式为真则执行语句1,为假则执行语句2
java循环语句
分为三种:for循环,while循环,do…while循环
for循环
1 | for(初始化; 布尔表达式; 更新) { |
开始循环前有初始化值,每次循环开始前都会进行布尔表达式的判断,true则进入循环,false则结束循环,每次循环结束都会执行更新语句
while循环
1 | while( 布尔表达式 ) { |
如果布尔表达式的值为 true,则语句块一直执行,直到布尔表达式的值为 false。
do…while循环
1 | do { |
和while循环语句一样,但是由于布尔表达式在循环体的后面,do…while循环语句在进行进入循环前都会先进行一次代码语句。如果布尔表达式的值为 true,则语句块一直执行,直到布尔表达式的值为 false。
break关键字
主要在循环语句和控制语句中,可以跳出最里层的循环,并且继续执行该循环下面的语句。
continue关键字
continue 适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环的迭代
在for语句中continue会直接结束当前循环进入下一循环而不是跳出循环
在 while 或者 do…while 循环中,continue会立即跳转到布尔表达式的判断语句。
java条件语句
if语句
1 | if(布尔表达式) |
如果布尔表达式的值为 true,则执行 if 语句中的代码块,否则不执行
if…else语句
1 | if(布尔表达式){ |
如果布尔表达式的值为 true,则执行 if 语句中的代码块,否则执行 else 语句块后面的代码。
if…else if…else 语句
1 | if(布尔表达式 1){ |
一个if语句只能有一个else语句,else语句都会在末尾,在所有的 else if 语句之后。一个if语句可以有若干个else if语句。一旦其中一个 else if 语句检测为 true,其他的 else if 以及 else 语句都将跳过执行。
嵌套的 if…else 语句
1 | if(布尔表达式 1){ |
当然也可以向上面一样嵌套if ..else if语句
1 | if(布尔表达式 1){ |
java控制语句
switch case语句
switch case 语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。
1 | switch(expression){ |
- 当变量的值与 case 语句的值相等时,那么 case 语句之后的语句开始执行,直到 break 语句出现才会跳出 switch 语句。
- 当遇到 break 语句时,switch 语句终止。程序跳转到 switch 语句后面的语句执行。case 语句不必须要包含 break 语句。如果没有 break 语句出现,程序会继续执行下一条 case 语句,直到出现 break 语句。
注意控制语句的case只能是具体的常量而不能是布尔表达式
关于java的那些结构语句的话其实和c语言差不多,我就不赘述了
java接口
接口简单来说就是一个抽象类型,是抽象方法的集合,通常以interface来声明。一个类通过实现继承接口的方式去继承接口的抽象方法。
但是接口和类不同的是,类是用于描述对象的属性和方法,而接口则是包含类要实现的方法,但是接口不提供这些方法的具体实现,无法被实例化。
接口的几个特点
接口不能被实例化成对象
接口的方法都是抽象方法
接口中每个方法都是隐式抽象的,会被隐式的指定为public abstract
接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量
定义接口
1 | [修饰符] interface [接口名称] { |
java数组
数组简单来说就是相同类型的数的一个集合
- 声明数组变量
1 | dataType[] arrayRefVar; // 首选的方法 |
java中声明数组 时候不能指定数组长度,例如int class[40];
数组属于引用类型,数组型数据是对象,数组中每个元素相当于该对象的成员变量,所以数组在使用前需要先创建
- 创建数组
1 | arrayRefVar = new dataType[arraySize]; |
注意:数组需要声明长度并且长度不可变
当然,我们声明数组和创建数组可以一起完成
1 | dataType[] arrayRefVar = new dataType[arraySize]; |
- 数组的引用
数组的元素是通过索引访问的。数组索引从 0 开始,所以索引值从 0 到 arrayRefVar.length-1。
数组的下标可以是整形常量也可以是表达式,但是切记需要在数组长度的取值范围内去引用,不然会导致出错
可以用length属性去获取数组的长度,例如class.length可以指向class数组的长度
数组初始化
和我们基本数据类型的初始值是一样的
int
,short
,long
,byte
的默认值是0。char
的默认值是\u0000
(空字符)。float
的默认值是0.0f
。double
的默认值是0.0d
。boolean
的默认值是false
。- 引用类型(类、接口、数组)的默认值是
null
。
我们定义什么类型的数组,数组的初始化值就是什么样的
接下来我们写个一维数组感受一下
1 | public class HelloWorld{ |
打印出的结果就是各个元素的名字
通常我们在处理数组或者引用数组的时候都会搭配循环去进行使用
- 数组作为函数的参数的使用