Java 学习笔记
Posted 王睿丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 学习笔记相关的知识,希望对你有一定的参考价值。
文章目录
- 1、简介:
- 2、开发技巧
- 3、官方不推荐写法
- 4、异常总结
- 5、疑问及解决
- 6、易理解混淆
- 一丶变量名词繁多:全局变量、成员变量、局部变量、静态变量、实例变量、类变量
- 二丶数据类型转换
- 三丶Java 中一句相连的字符串不能分开在两行中写,要换行写需要用‘+’连接
- 四、比较两个字符串
- 五丶compareTo() 与 equals()区别
- 六丶字符串分割
- 七丶数组和String不是数据类型,它们都为对象
- 八丶遍历二维数组时,得到的每一个元素都是一个一维数组
- 九丶数组的基类(数组的操作类)是Arrays
- 十丶访问权限问题
- 十一丶两个对象的产生是相互独立的
- 十二丶静态成员变量可以改变值
- 十三丶引用只是存放一个对象的内存地址,并非存放一个对象。
- 十四丶对象的比较
- 十五丶数字格式化
- 十六丶继承
- 十七丶对象类型转换
- 十八丶final与staic final的区别
- 十八丶异常
- 十九丶集合的架构
- 二十丶输入流:InputStream 和 Reader 区别
- 二十一丶输出流:OutputStream 和 Writer 区别
- 二十二丶I/O流
- 7、类
- 8、注意
喜欢记得点个赞哟,我是王睿,很高兴认识大家!
1、简介:
本文为作者当初在学Java时留下的笔记,会从7个部分去讲解:《开发技巧》、《官方不推荐写法》、《异常总结》、《疑问及解决》、《易理解混淆》、《类》、《注意》。
2、开发技巧
一:分隔符
没有统一的对字符进行分割的符号,如果向定义多个分隔符,可使用符号“|”,例如,“,|=”表示分隔符分别为“,”和 “=”。
二:super 关键字
1、在子类中调用父类构造方法
2、在子类中调用父类成员方法(除了private修饰的都可以)
三:重写父类的方法可以实现
1、修改方法体内容
2、更改成员方法的存储权限
3、修改成员方法的返回值类型
四:继承后的垃圾清理
如果使用 finalize()方法对对象进行清理,需要确保子类 finalize()方法的最后一个动作是调用父类的 finalize()方法,以保证当垃圾回收对象占用内存时,对象的所有部分都能被正常终止。
五:接口进行向上转型操作的方式
用一段源代码来表示:
package chapter10;
interface drawTest{ //定义接口
public void draw(); //定义方法
}
//定义平行四边形类,该类继承了四边形类,并实现了 drawTest 接口
class ParallelogramgleUselnterface extends QuadrangleUselnterface implements drawTest{
public void draw() { //由于该类实现了接口,所以需要覆盖draw()方法
System.out.println("平行四边形.draw()");
}
}
//定义正方形类,该类继承了四边形类,并实现了 drawTest 接口
class SquareUselnterface extends QuadrangleUselnterface implements drawTest{
public void draw() {
System.out.println("正方形.draw()");
}
void doAnyThing() {
}
}
class AnyThingUselnterface extends QuadrangleUselnterface{
void doAnyThing() {
}
}
public class QuadrangleUselnterface{ //定义四边形类
public void doAnyTthing() {
}
public static void main(String[] args) {
/* 精彩的部分开始 */
//接口也可以进行 向上转型 操作
drawTest[] d = {new SquareUselnterface(),new ParallelogramgleUselnterface()};
//相当于
//drawTest d2 = new SquareUselnterface();
//drawTest d3 = new ParallelogramgleUselnterface();
/* 精彩的部分结束 */
for(int i=0;i<d.length;i++) {
d[i].draw(); //调用 draw()方法
}
}
}
我说一下我为什么能理解并想出跟下面两行代码是等价的:
还记得接口的概念吗,接口可以实现多重继承,那么其实实现了接口的类,那么这个类就是子类,而对接口而言他是这个类的父类
也就是说,接口就是里面这两个类的父类,所以它可以直接进行向上转型。
这里利用了多态特性和向上转型的原理,不会的一定要去好好搜一下资料理解一下,其实这里你理解了后会很有成就感真的,哇我现在就好爽!
所以说,你只要能理解下面两行代码可以向上转型给接口,就能理解上面那一行代码了。
六:使用 this 关键字获取内部类与外部类的引用
在类中,如果遇到内部类与外部类成员变量重名的情况,可以使用 this 关键字进行处理。
源代码:
public class TheSameName {
private int x;
private class Inner{
private int x = 9;
public void doit(int x) {
x++; //调用的是形参 x
this.x++; //调用内部类的变量x
TheSameName.this.x++; //调用外部类的变量x
}
}
}
七:创建自定义异常的步骤:
1、创建自定义异常
2、在方法中通过throw 关键字抛出异常对象
3、如果在当前抛出异常的方法中处理异常,可以使用 try-catch 语句块捕获并处理,否则在方法的声明处通过 throws 关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
4、在出现异常方法的调用者中捕获处理异常
源代码举例:
class MyException extends Exception{
public MyException(String s) { //构造方法
super(s); //父类构造方法
}
}
public class Tran { //创建类
static int avg(int number1,int number2) throws MyException{ //定义方法,抛出异常
if(number1<0 || number2<0) { //判断方法中参数是否满足指定条件
throw new MyException("不可以使用负数"); //错误信息
}
if(number1>100 || number2>100) { //判断方法中参数是否满足指定条件
throw new MyException("数值太大了"); //错误信息
}
return (number1 + number2) / 2; //将参数的平均值返回
}
public static void main(String[] args) {
try {
int result = avg(102,150);
System.out.println(result);
}catch(MyException e) {
System.out.println(e);
}
}
}
八:随机获取集合中的某个元素
int i = (int)(Math.random()*list.size()); //获得0~2之间对的随机数
此时i 代表了一个随机索引,然后利用list.get(i)就可以获取随机元素了
九:反射机制实现创建私有构造方法对象
Constructor 类中有两个方法
newInstance(Object…initargs):通过该构造方法利用指定参数创建一个该类的对象,如果未设置参数则表示采用默认无参数的构造方法
setAccessible(boolean flag):如果该构造方法的权限为 private,默认不允许通过反射利用 newInstance(Object…initargs)方法创建对象。如果先执行该方法,并将入口参数设为 true,则允许创建。
结合以上两个方法即可实现,例子如下:
try {
//通过执行默认没有参数的构造方法创建对象
if(i==2)
example = (Example_01) constructor.newInstance();
else if(i == 1)
//通过执行具有两个参数的构造方法创建对象
example = (Example_01) constructor.newInstance("7",5);
else {
//通过执行具有可变数量参数的构造方法创建对象
Object[] parameters = new Object[] {new String[] {"100","200","300"}};
example = (Example_01) constructor.newInstance(parameters);
}
}catch(Exception e) {
System.out.println("在创建对象时抛出异常,下面执行 setAccessible()方法");
constructor.setAccessible(true); //设置允许访问
}
十丶泛型类型限制
泛型类型限制除了可以向下限制之外,还可以进行向上限制,只要在定义时使用 super 关键字即可。
举例:
Test<? super List> b = null;
这样定义后,对象a只接受List接口或上层父类类型。
如: b = new Test<Object>();
3、官方不推荐写法
一:变量命名
在 Java 语言中允许使用汉字或其他语言文字作为变量名,如“int 年龄 = 21”,在程序运行时不会出现错误,但建议读者尽量不要使用这些语言文字作为变量名。
二:赋值运算符
在 Java 中可以把赋值运算符连在一起使用,如:
x = y = z = 5
在这个语句中,变量 x、y、z 都得到同样的值5。但在实际开发中不建议使用
三:静态成员和非静态成员
虽然静态成员也可以使用“对象.静态成员”的形式进行调用,但通常不建议用这样的形式,因为这样容易混淆静态成员和非静态成员。
四:异常
有时为了编程简单会忽略 catch 语句后的代码,这样 try-catch 语句就成了一种摆设,一旦程序在运行过程中出现了异常,就会导致最终运行结果与期望的不一致,而错误发生的原因很难查找。因此要养成良好的编程习惯,最好在 catch 代码块中写入处理异常的代码。
五:异常
Java 中的异常处理时通过 try-catch 语句来实现的,也可以使用throws 语句向上抛出。但建议读者不要将异常抛出,应该编写异常处理语句。
六:I/O流
如果使用 writeChars() 和 writeBytes() 方法写入字符串后,在读取回来就不容易了。
推荐使用 writeUTF()写入字符串,再用readUTF()读取字符串。
4、异常总结
一:常见的异常类:
ClassCastException:类型转换异常
ClassNotFoundException:未找到相应类异常
ArithmeticException:算术异常
ArrayIndexOutOfBoundsException:数组下标越界异常
ArrayStoreException:数组中包含不兼容的值抛出的异常
SQLException:操作数据库异常类
NullPointerException:空指针异常
NoSuchFieldException:字段未找到异常
NoSuchMethodException:方法未找到抛出的异常
NumberFormatException:字符串转换为数字抛出的异常
NegativeArraySizeException:数组元素个数为负数抛出的异常
StringIndexOutOfBoundsException:字符串索引超出范围抛出的异常
IOException:输入输出异常
IllegalAccessException:不允许访问某类异常
InstantiationException:当应用程序试图使用 Class 类中的 newInstance() 方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常
EOFException:文件已结束异常
FileNotFoundException:文件未找到异常
二:RuntimeException 异常的种类:
NullPointerException 空指针异常
ArrayIndexOutOfBoundsException 数组下标越界异常
ArithmeticException 算术异常
ArrayStoreException 数组中包含不兼容的值抛出的异常
IllegalArgumentException 非法参数异常
SecurityException 安全性异常
NegativeArraySizeException 数组长度为负异常
三:开发中遇到的异常:
ArithmeticException:
在进行除法运算时,0不能做除数。例如,对于语句“int a = 5/0”。
ArrayIndexOutOfBoundsException:
当指定的索引位置大于或等于要进行填充的数组的长度,就会报错
NumberFormatException:
要用数值型 String 变量作为参数,如123。不能为“abc”,否则将抛出:NumberFormatException异常
IllegalArgumentException:
格式化模板中“#”不可以和“0”同时出现,举例:
pattern = “####0,##.###”; //错误的格式化模板,运行会导致异常
IllegalArgumentException
由 枚举类型的成员A.compareTo(枚举类型成员B) ,其中 枚举类型成员B 不存在,并没有定义在枚举类型中,所以报错
5、疑问及解决
一:static 为什么不能定义在方法里
解答:
第一个方面:
static是成员变量及方法的修饰符,是属于类本身的数据字段
第二个方面:
在方法体中定义的变量称之为局部变量,方法体执行结束后,局部变量会自动销毁。
而static 定义的变量是一个静态的变量,它的作用肯定是为了让这个变量内外界都能被访问或读写,所以我们只能在类中去使用static 关键字
结论:
static关键字,只能用来定义成员变量和成员方法。
不能定义局部变量
二:“&&”与 “&”都表示”逻辑与“,那么它们之间的区别在哪里呢?
解答:
“&”会判断两边表达式是否都为true或flase,才会得出最终结果,被称为“非短路”运算符。
“&&”当第一个表达式为 false 时,则不会去判断第二个表达式,被称为“短路”运算符。
三:三元运算符的好处体现在哪里?
解答: 拿三元与 if 代码做比较如下
【1】
boolean b = 20<45?true:false;
【2】
if(20<45)
System.out.println(“true”);
else
System.out.println(“false”);
一行代码就解决了四行代码解决的问题
四:String-Builder与String 区别
“+”虽然可以附加新字符或字符串,但“+”会产生一个新的 String 实例,会在内存中创建新的字符串对象。如果重复地对字符串进行修改,将极大地增加系统开销。
那么我们要反复进行修改字符串,且不想大量消耗系统时该怎么做?
解决办法: 使用 String-Builder类,大大提高了频繁增加字符串的效率
五:Java 虚拟机内存消耗待尽,如何解决?
如果Java 虚拟机内存消耗待尽,它将不会执行垃圾回收处理,这种时候该怎么办呢?
解决: Java 提供了 System.gc() 方法来强制启动垃圾回收器
六:异常
class MyException extends Exception{ //创建自定义异常类
String message; //定义 String 类型变量
public MyException(String ErrorMessage) { //父类方法
message = ErrorMessage;
}
public String getMessage() {
return message;
}
}
public class Captor { //创建类
static int quotient(int x,int y)throws MyException{ //定义方法抛出异常
if(y<0) { //判断参数是否小于0
throw new MyException("除数不能是负数"); //异常信息
}
return x/y;
}
public static void main(String[] args) {
try { //try 语句包含可能发生异常的语句
int result = quotient(3,0);
}catch (MyException e) { //处理自定义异常
System.out.println(e.getMessage());
}catch(ArithmeticException e) { //处理 ArithmeticException 异常
System.out.println("除数不能为0");
}catch (Exception e) { //处理其他异常
System.out.println("程序发生了其他的异常");
}
}
}
提问: 我不太能理解,为什么我调用quotient()方法并传递3和0两个参数进去后,该方法明明是针对抛出异常交给 MyException 来进行处理
那么当经过代码 return x/y 时,会发生异常,但为什么却是交给 catch(ArithmeticException e) 这个语句块里执行,不太明白,明明不是抛出给MyException 来进行处理吗。
经过我自己的思考后,我是这么理解的:
角度一:
抛出的异常类型为 ArithmeticException 所以会交给catch(ArithmeticException e)来执行
角度二:
在代码执行中,若出现了系统自带的异常,则优先处理系统自带的,而不会交给抛出的指定异常类才处理。
角度三:
return x/y; 这条代码发生了异常,它并没有抛出给方法外给 MyException 来处理,而是由系统直接拦截后锁定为 ArithmeticException 异常类型后,所以会由catch(ArithmeticException e)来执行
七:集合与数组区别
1、数组的长度是固定的,集合的长度是可变的
2、数组用来存放基本类型的数据,集合用来存放对象的引用
八:为何需要实现Comparable接口,Comparable 接口的意义和用法
为何需要实现Comparable接口,Comparable 接口的意义和用法(这篇博客写的淋淋尽致,感谢博主分享)
九:java中System.in.read();是什么意思
System.in.read()可以实现输入字符,返回字符的Unicode码,但是缺点是只能输入一个字符
System.in.read() 返回的是输入数值的 ASKII 码(一个 int 整数)。
十:getClass()的作用
getClass() 返回此 Object 的运行时该对象的类. 该方法返回一个Class对象, 可以通过该对象可以获取某个类的相关信息, 如构造方法 属性 方法 等。
举例:
class Student{
…
}
那么:
Student s = new Student();
s.getClass() 得到的是内存中实实在在存在的Student 这个类
6、易理解混淆
一丶变量名词繁多:全局变量、成员变量、局部变量、静态变量、实例变量、类变量
全局变量(成员变量)
局部变量
成员变量 => 【静态变量(类变量)、实例变量】
类变量的作用:
对于静态变量,除了能在定义它的类内存取,还能直接以“类名.静态变量”的方式在其他类内使用。
二丶数据类型转换
隐式类型转换:
从低级类型向高级类型的转换,系统自动执行,无需进行任何操作。
显示类型转换(强制类型转换):
当把高精度的变量的值赋给低精度的变量时,必须使用显示类型转换运算。
格式:
(类型名)要转换的值,例如:int a = (int)45.23;
三丶Java 中一句相连的字符串不能分开在两行中写,要换行写需要用‘+’连接
举例:
【×】
System.out.println("I like
Java)
【√】
System.out.println(“I like”+
“Java”)
四、比较两个字符串
“==”,比较的是两个字符串的地址,即使值相同,仍然会返回 false;
“equals()”,比较的是两个字符串的值是否相同,相同则返回 true,严格区分大小写;
“equalsIgnoreCase()”,比较的是两个字符串的值是否相同,相同则返回 true,忽略大小写;
五丶compareTo() 与 equals()区别
compareTo()方法只有在equals(Object)方法返回 true 时,才会返回0
特殊情况:str1.compareTo(str2)相等时,则会返回0
正常情况:str1.compareTo(str2),若str1在字典顺序上位于str2之前,返回负数,若在之后返回正数
六丶字符串分割
split(String sign,int limit)
参数一:sign为分隔符
参数二:limit为分割次数
最终分割的次数是 limit-1次
七丶数组和String不是数据类型,它们都为对象
八丶遍历二维数组时,得到的每一个元素都是一个一维数组
例如,foreach遍历一个二维数组:
for(int x[]:arr) {
for(int e:x) {
System.out.print(e);
}
}
九丶数组的基类(数组的操作类)是Arrays
十丶访问权限问题
class AnyClass{
public void doString(){
...//方法体
}
}
虽然 doString()方法被设置为 public 访问权限,但实际上doString()方法访问权限依然与AnyClass 类的访问权限相同
结论: 类的权限设定会约束类成员的权限设定
十一丶两个对象的产生是相互独立的
int i = 0;
public static void main(String[] args){
Five f1 = new Five();
Five f2 = new Five();
f1.i = 60;
}
f1.i的值被改变,不会影响到f2.i的值
结论: 两个对象的产生是相互独立的,两个对象的成员变量存储(指向)的内存区域也是不同的。
十二丶静态成员变量可以改变值
使用两个对象对同一个静态成员变量操作,依然可以改变静态成员变量的值,因为在内存中两个对象同时指向同一块区域
十三丶引用只是存放一个对象的内存地址,并非存放一个对象。
严格地说,引用和对象是不同的,但是可以将这种区别忽略,如可以简单地说book是Book类的一个对象,而事实上应该是book包含Book对象的一个引用。
十四丶对象的比较
“==”运算符,比较的是两个对象引用的地址是否相等。
equals() 方法,比较的是两个对象引用所指的内容是否相等。
十五丶数字格式化
“#”数字有就显示,多了也会显示
“0”数字有就显示,没有就补0(正数在开头补0,负数在末尾补0)。
十六丶继承
在实例化子类对象时,父类无参构造方法将被自动调用。有参构造方法不能被自动调用,用户只能使用 super 关键字显示地调用父类的构造方法。
十七丶对象类型转换
向上转型:把子类对象赋值给父类类型的变量。简单来说就是:从一个比较具体的类到较抽象的转换。
向下转型:将较抽象的类转换为较具体的类。
注意:在做向下转型时,必须使用【显式类型转换】,向编译器指明要将父类对象转换为哪一种类型的子类对象。
十八丶final与staic final的区别
一个被定义为 final 的对象引用只能指向唯一一个对象,不可以将它再指向其他对象。但由于一个对象本身的值是可以改变的,因此为了使一个常量真正做到不可更改,可以将声明常量为 static final。
十八丶异常
如果是 Error、RuntimeException 或它们的子类,可以不使用 throws 关键字来声明要抛出的异常,编译仍能顺利通过,但在运行时会被系统抛出。
十九丶集合的架构
Collection 接口(父类):Set 集合(子类)、List 集合(子类)
Set 集合(父类):HashSet(子类)、TreeSet(子类)
List 集合(父类):ArrayList(子类)、LinkedList(子类)
Map集合(父类):HashMap(子类)、TreeMap(子类)
二十丶输入流:InputStream 和 Reader 区别
InputStream 字节输入流抽象类,是所有字节输入流的父类,用来处理字节的。
Reader 字符输入流抽象类,是所有字符输入流的父类,用来处理字符文本的。
二十一丶输出流:OutputStream 和 Writer 区别
OutputStream 字节输出流抽象类,是所有字节输出流的父类,用来处理字节。
Writer 字符输出流抽象类,是所有字符输出流的父类,用来处理字符文本的。
二十二丶I/O流
输入流:
InputStream 字节-输入流
Reader 字符-输入流
OutputStream 字节-输出流
Writer 字符-输出流
FileInputStream 字节-文件输入流
FileOutputStream 字节-文件输出流
FileReader 字符-文件输入流
FileWriter 字符-文件输出流
BufferedInputStream 字节-缓存输入流
BufferedOutputStream 字节-缓存输出流
BufferedReader 字符-缓存输入流
BufferedWriter 字符-缓存输出流
DataInputStream 字节-数据输入流
DataOutputStream 字节-数据输出流
ZIPOutputStream 字节-压缩输出流
ZIPInputStream 字节-压缩输入流
7、类
一丶String 类(字符串操作类)
二丶StringBuilder (字符串生成器)
三丶Arrays(数组操作类)
四丶Integer(整数int 包装类)
五丶Boolean(布尔boolean 包装类)
六丶Byte(整数byte 包装类)
七丶Character(字符char 包装类)
八丶Double(浮点数double 包装类)
九丶Float(浮点数float 包装类)
十丶Number(抽象类,是基本类型包装类的父类)
十一丶DecimalFormat(格式化十进制数字,是 NumberFormat 的子类)
十二丶Math(数学基本运算、伪随机数)
十三丶Random(随机数生成器)
十四丶Biglnteger(支持任意精度的整数,操作数学计算)
十五丶Exception (所有异常类的父类)
十六丶Object(所有类的父类)
十七丶ArrayList、LinkedList (List 集合实现类)
十八丶HashSet、TreeSet (Set 集合实现类)
十九丶HashMap、TreeMap (Map 集合实现类)
8、注意
一丶InputStream
并不是所有的 InputStream 类的子类都支持 InputStream 中定义的所有方法,如 skip()、mark()、reset()等方法只对某些子类有用。
二丶FileOutputStream
可以指定不存在的文件名,但此文件名不能是一个已被其他程序打开的文件
三丶反射
在反射中执行具有可变数量的参数的构造方法时,需要将入口参数定义成二维数组
例如:
可变数量的参数构造方法:
private String privateMethod(String...strings) {
...;
...;
}
需要将入口参数定义成二维数组:
Object[] parameters = new Object[] {new String[] {"M","W","Q"}};
System.out.println("返回值为:" + method.invoke(example_03, parameters));
喜欢记得点个赞哟,我是王睿,很高兴认识大家!
以上是关于Java 学习笔记的主要内容,如果未能解决你的问题,请参考以下文章