Java学习笔记(1)——基础
教程
基础
注释
//单行注释 |
标识符和关键字
关键字
标识符
以字母、美元符、下划线开头。大小写敏感。
数据类型
类型 | 大小 | 备注 |
---|---|---|
byte | 1字节 | |
short | 2字节 | |
int | 4字节 | |
long | 8字节 | 以L结尾 |
float | 4字节 | 以F结尾 |
double | 8字节 | |
char | 2字节 | 用单引号修饰 |
boolean | 1位 | true or false |
整数扩展
二进制0b,八进制0,十六进制0x。
浮点数扩展
最好完全避免使用浮点数进行比较。
字符扩展
所有字符的本质还是数字。
Unicode前缀’\u’。
对象,从内存分析。
类型转换
从低到高,byte, short, char -> int -> long -> float -> double。不同数据类型运算,先转换为同一种。
强制类型转换:(类型)变量名。自动类型转换,低到高。
注意:不能对boolean进行转换,不能把对象类型转换为不相干的类型,把高容量转换到低容量的时候是强制转换,转换的时候可能出现精度问题或者内存溢出。
如果你在Java源码中要处理大数字,你可以在数字中加入下划线来提高可读性。使用的时候要注意:在字面常量数字里加下划线是有一定规则的,下划线只能在数字之间,在数字的开始或结束一定不能使用下划线。比如把长整型数字比如10000000000写成一个更具可读性10_000_000_000。
变量、常量、作用域
Java是强类型语言,每个变量都必须声明类型。
声明变量: 数据类型 变量名 = 值;
按作用域分:类变量、实例变量、局部变量。
实例变量从属于对象,如果不自行初始化,就是默认值:0、0.0、false。除了基本类型,其余都是null。
类变量关键字static
。
常量可以理解为一种特殊变量。声明:final 常量名 = 值;
常量名一般用大写字符。
命名规范
类成员变量、局部变量、方法名:首字母小写和驼峰原则,即除了第一个单词外,后面的单词首字母大写,如lastName、reRun()。
常量:大写字母和下划线,如MAX_VALUE。
类名:首字母大写和驼峰原则,如GoodMan。
运算符
运算符包括算数运算符、赋值运算符、关系运算符、逻辑运算符、位运算符、条件运算符、扩展赋值运算符。
注意除法运算中的变量类型问题。
不存在幂运算符^
,幂运算可以使用Math工具类,Math.pow()
。^
表示异或运算。可以用左移位运算实现乘方。
有三目运算符 ? :
包机制
package语句放最前面,import语句在其之后。一般使用公司域名倒置作为包名。
JavaDoc生成文档
JavaDoc可以写在类上面和方法上面。
执行命令javadoc xxx.java即可,也可以使用IDEA的JavaDoc生成功能,在菜单 Tools->Generate JavaDoc项里面。
流程控制
用户交互Scanner
// 基本语法 |
next()
:读取到有效字符后才可以结束输入,将有效字符后面的空白作为分隔符或者结束符,不能得到带有空格的字符串。
nextLine()
:读取输入回车之前的所有字符,可以获得空白。
还有各种类型的nextxxxx()
和hasNextxxxx()
方法。
选择结构
// if选择结构 |
// switch选择结构,匹配一个具体的值 |
IDEA可以反编译class文件,如下图。
循环结构
// while循环 |
// do……while循环 |
// for循环 |
// 增强for循环 |
break
用于强行跳出循环,不再执行剩余语句。
continue
用于终止某次循环过程,接着进行下一次循环是否执行的判定。
goto
仍是java的一个保留字,但并未在语言中得到正式使用,在带标签的break和continue中有它的影子。
outer: |
方法
何为方法
- 方法是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中创建,在其他地方被引用
- 最好保持方法的原子性,即一个方法只完成一个功能,便于后期扩展
修饰符 返回值类型 方法名(参数类型 参数名){ |
调用方法:对象名.方法名(实参列表)
方法重载
在一个类中,有相同的函数名称,但形参不同的函数。
规则:
- 方法名称必须相同
- 参数列表必须不同(个数、类型、参数排列顺序不同)
- 返回类型可同也可不同
- 仅仅返回类型不同,不足以构成重载
命令行传参
// example |
运行java HelloWorld.java this is
# output |
可变参数
在方法声明中,在指定类型后加一个三个点...
。一个方法只能有一个可变参数,必须是方法的最后一个参数。
// example |
数组
创建数组
// 声明并创建一个数组 |
- 通过索引访问,索引从0开始。
- 长度固定,一旦创建,不可改变。
- 可以是任何类型,但不允许混合类型。
- 数组变量属于引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。
- 数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
内存分析
Java内存:
- 堆:存放new的对象和数组,可以被所有的线程共享,不会存放别的对象引用。
- 栈:存放基本变量类型(会包含具体数值),引用对象的变量(会存放这个引用在堆里面的具体地址)。
- 方法区:可以被所有线程共享,包含了所有的class和static变量。
三种初始化
默认初始化:数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
多维数组
即数组的数组。
int[][] array = {{1,2},{2,3},{3,4}}; |
Arrays类
数组工具类java.util.Arrays中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用。而不用(不是不能)使用对象来调用。看文档了解常用的fill
、toString
、sort
等方法。
稀疏数组
当一个数组中大部分为同一值时,可以使用稀疏数组来保存该数组。把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模。
上图中第一行row表示原矩阵行数,col表示原矩阵列数,value=8表示共有8个有效值,稀疏数组长度为8+1=9。
面向对象
对于描述复杂事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
面向对象编程(OOP)本质是以类的方式组织代码,以对象的形式封装数据。
三大特性:封装,继承,多态。
静态方法和非静态方法
static
静态方法,和类一起加载的。非静态方法需要类实例化之后才存在,才能使用。
值传递和引用传递
// 引用传递:对象,本质还是值传递。 |
# output |
类和对象
类是对某一类事物整体的描述/定义,但是并不能代表某一个具体的事物。
对象是抽象概念的具体实例。
创建的时候,使用new
关键字,会分配内存空间,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
一个项目应该只有一个main方法。
构造器
类中的构造器又称构造方法,必须和类的名字同名,必须没有返回类型,也不能写void
。
class Person { |
// example |
# output |
定义有参构造之后,如果想使用无参构造,显式地定义一个无参的构造。
内存分析
封装
高内聚,低耦合:内部数据操作细节自己完成,仅暴露少量的方法给外部使用。
封装(数据的隐藏):通常应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问、
属性私有:private
关键字。通常提供一些可以操作这个属性的方法,例如public
的get、set方法。
class Person { |
// example |
# output |
总结:属性私有,get/set。
属性级别:public
、protected
、default
、private
。
继承
继承是类和类之间的一种关系。子类继承父类(包括父类的所有方法),使用关键字extend
来表示。
在Java中,所有类都默认直接或者间接继承Object。
Java中只有单继承,没有多继承。
// example |
使用super
调用父类的属性和方法。私有的东西无法被继承,即super
不能调用父类的private
方法。
new一个子类对象时,会先执行super()
,调用父类的无参构造。即super()
方法是调用父类的构造器,必须要在子类构造器的第一行。默认调用的是父类的无参构造,如果父类没有无参构造,就会报错。super
和this
不能同时调用构造方法。
多态
重写
重写都是方法的重写,和属性无关。
父类的引用可以指向子类。例如Person you = new Student();
。
静态方法是类的方法,非静态方法是对象的方法。对于上例而言,因为you
是Student
new出来的对象,因此在有static
时,you
调用了Person
类的方法,没有static
时,you
调用的是对象的方法,即Student
的方法。
public class HelloWorld { |
重写注意事项
- 重写的方法可以使用 @Override 注解来标识。
- 构造方法不能被重写。
- 声明为 final 的方法不能被重写。
- 子类和父类在同一个包中时,子类可以重写父类除了声明为 private 和 final 方法的其他方法。
- 子类和父类不在同一个包中时,子类只能重写父类的声明为 public 和 protected 的非 final 方法。
- 如果不能继承一个方法,则不能重写这个方法。重写是在继承的基础上,如果方法无法被继承那么就无法重写
- 方法名、参数列表必须相同
- 修饰符:范围可以扩大,不能缩小:public>protected>default>private
- 抛出的异常:范围可以被缩小,不能被扩大:ClassNotFound –> Exception
为什么需要重写:父类的功能,子类不一定需要,或者不一定满足。
instanceof和类型转换
对象能执行哪些方法,主要看对象左边的类型,和右边关系不大。
子类能调用的方法,都是自己的或者继承父类的。父类不能调用子类独有的方法。
多态注意事项
- 多态是方法的多态,属性没有多态
- 父类和子类有联系,类型转换异常为ClassCastException
- 存在条件:继承关系,方法需要重写(but有些方法不能被重写,见上文),父类引用指向子类对象
Father f1 = new Son();
instanceof
判断一个对象是否是特定类的一个实例。
// example |
# output |
System.out.println(X instanceof Y);
能不能编译通过,就看X和Y之间有没有父子关系。
类型之间的转换:父对象可以使用括号强制转换为子对象。子类转换为父类不用强制转换,但可能丢失一些自己本来的方法。可以方便方法的调用,减少重复的代码!
static关键字详解
静态代码块
// example |
# output |
可见,执行顺序是静态代码块、父类构造方法、匿名代码块,子类构造方法。且静态代码块只最初执行一次。
静态导入包
import static java.lang.Math.random; |
如此,使用random方法时,就不用写Math.random()
,而是可以直接写random()
。
被final修饰的类不能再有子类。
abstract抽象类
抽象方法:只有方法名字,没有方法的实现。
抽象类的所有方法,继承了它的子类,都必须要实现它的方法,除非子类也是抽象类。
特点:不能new这个抽象类,只能靠子类去实现,它是一种约束!一旦类里面有抽象方法,则类必须是抽象类。抽象类里面可以写普通方法。
存在的意义:抽象出来,提高开发效率,提高可扩展性。
interface接口
普通类只有具体实现,抽象类有具体实现和规范(抽象方法),接口则只有规范,自己无法写方法。
接口的本质是契约。接口中的所有定义其实都是抽象的public abstract
。所有变量其实都是public static final
。
类可以实现接口,关键字implements
。类实现了接口,就必须重写接口中的方法。
作用:约束;定义一些方法让不同的人实现。
接口不能被实例化,接口中没有构造方法。
extends
只有单继承,但是可以implements
可以多继承。
// UserService.java |
// TimeService.java |
// UserServiceImpl.java |
内部类
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
public class Outer { |
// 测试成员内部类 |
异常
软件程序在运行过程中,经常遇到各种异常或意外。这些Exception,让我们写的程序做出合理的处理,而不至于程序崩溃。
- 检查性异常:最具代表性的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在的文件时。这些异常在编译时不能被简单忽略。
- 运行时异常:可能被程序员避免的异常。这些异常在编译时可以被忽略。
- 错误ERROR:错误不是异常,而是脱离程序员控制的问题。例如栈溢出。
Java把异常当作对象来处理,定义基类java.lang.Throwable作为所有异常的超类。分为两大类:错误Error和异常Exception。出现前者时,JVM一般终止线程;后者则是通常情况下可以被程序处理,并且在程序中应该尽可能的去处理。
异常处理
五个关键字try
、catch
、finally
、throw
、throws
。
// example |
catch
里面的参数是想要捕获的异常类型,catch
可以写多个,层层递进,范围最大的在最后。
public class Demo01 { |
自定义异常
用户自定义异常类,只需继承Exception类即可。
public class MyException extends Exception { |
// test |
# output |
经验总结:
- 采用逻辑去合理规避同时辅助try-catch处理。
- 多重catch后面,加一个catch(Exception)来处理可能被遗漏的异常。
- 不确定的代码,也可以加上try-catch来处理潜在异常。
- 尽量去处理异常,切忌只是简单的printStackTrace去打印输出。
- 具体如何处理,根据业务需求去决定。
- 尽量添加finally语句块去释放占用的资源。
其它
IDEA快捷操作
- 输入一个数字,再输入
.
,即可快捷生成for循环语句。输入fori
也可以。 - Ctrl+D可以将当前行复制到下一行。
- 类中,Alt+Insert快捷生成构造器,以及Getter和Setter,以及重写方法。或者鼠标右键,选择Generate。
- 选中多行代码后,Ctrl+/为快捷注释,Tab为整体缩进右移,Tab+Shift为整体缩进左移。
- 光标移动到某个类,Ctrl+H快捷键查看其继承关系。或点击侧边栏Hierarchy。
- 选中某部分代码,Ctrl+Alt+T可以使选中代码surround with,生成while、if、try等。好像和QQ冲突了,可以改快捷键。
递归小心爆栈。