title: Java学习笔记
date: 2018-05-18 12:00:00
tags:
- Java
- 学习笔记
Perface
因为 Minecraft 接触到 Java,很想写 Minecraft 的插件/MOD,可惜今年寒假才算开始入门,到了现在大一下学期(18 年 5 月)断断续续地学,没有具体的学习安排所以没坚持下来,最近看了这篇文章Java 心得感觉又活过来了,就开始在这里更新学习日记吧做一个长久一点的规划,比如大二上学期要学会什么,下学期要学会什么
Day 1(#0518)
20180518
重读《Java 从入门到精通》,14 年购入,此书较实用
不适合深入学习
因为上学期有 C 基础,快速略读了 1-4 章,漏读位操作符
,需要时再补
晚上在知乎搜Java 项目
时看到这篇文章Java 心得
这不就是我想成为的那种人吗
每天 10 小时写代码...利用好时间
未接触但较为重要的数据结构
算法
数据库
接下来试着做个项目吧,虽然 API 都没怎么看过
啃书吧,不懂就看视频,可以去下个离线视频看
Day 2(#0519 8hrs)
通读第 5 章字符串 String
与第 6 章数组 Arrays
,早上 6 点尿憋醒又睡到 9 点...12 点出发,自习室 8 小时今天睡得比较多,白天都在学也不太困,大概就是晚起的好处...
昨天看了那篇文章后就打算啃书了,也可以坚持下来,看不懂的再去看视频吧~
第 5 章 字符串 String
主要讲了 String 字符串类的使用(java.lang
包)
声明创建,连接字符串
String str = "Hello"; 声明创建
String s = str + " " + str; 连接
获取字符串信息
str.length(); 获取字符串长度
int size = str.indexOf("a"); 查找字符串索引位置
str.charAt(index); 获取字符串索引位置的字符
字符串操作
字符串截取 | 去空格 | 替换 | 判断开头结尾 | 判断相等 | 比较 Unicode 顺序 | 转换大小写 | 分割
str.substring(0,3); 截取字符串
str.trim(); 去除字符串空格
str.replace("a","B"); 字符串替换
str.startsWith(" "); 判断是否字符串的开头/* boolean */
str.endsWith(" "); 判断是否字符串的结尾
str.equals(str2); 判断字符串是否相等
str.compareTo(str2); 比较Unicode值顺序
str.toLowerCase(); 转换为小写字符串
str.toUpperCase(); 转换为大写字符串
str.split(","); 分割字符串
格式化字符串
str.format();
日期时间格式化
import java.util.Date;
Date date = new Date();
String s = String.format("%tc",date); 参考日期|时间|组合|常规转换符表!
使用正则表达式判断格式正误
String RegEx = "\\p......"
if (str.matches(RegEx))
参考正则表达式写法
字符串生成器
通过 StringBuilder 类快速生成字符串,省时间高效率
StringBuilder builder = new StringBuilder();
append(); insert(); delete(); 追加|插入|删除
小结
字符串的创建 | 连接方式 | 获取字符串信息 | 常用字符串操作格式化字符串 | 使用正则表达式 | 字符串生成器
第 6 章 数组 Arrays
数组创建及声明
数组是具有相同数据类型的一组数据的集合创建及声明 | 遍历数组 | Arrays 类的使用(填充|排序|复制|查询)
数组排序算法明天看:p
int[] arr = new int[5];
int[] arr = {1,2,3,4,5};
int[][] arr2 = {{1,2},{5,6}};
遍历数组
Arrays 类的使用
Arrays.fill(arr,8); 填充
Arrays.sort(arr); 排序
Arrays.copyOf(arr,5); 复制
int index = Arrays.binarySearch(arr,0,1,8); 数组查询
明天看数组排序算法
和第7章面向对象
Day 3 (#0520)
通读了数组排序算法
,理解的算不上深刻
学习算法应该多读几遍代码再尝试自己写
数组|数组排序算法 (P114~P120)
冒泡排序|直接选择排序|反转排序
冒泡排序
基本思想是对比相邻的元素值,如果满足条件就交换值,把较小的元素移动到数组前面,反之把达的元素移动到数组后面(也就是交换两个元素的位置),这样较小的元素就像气泡一样从底部上升到顶部。
算法示例:冒泡算法由双层循环实现,外层循环控制排序轮数,一般为要排序的数组长度减一次(因为最后一次循环只剩下一个元素无需再对比了)内层循环主要用于对比数组中的每个临近元素的大小,以确定是否交换位置,对比和交换次数随着排序轮数而减少
public class BubbleSort {
public static void main(String args[]) {
//先创建一个乱序数组
int[] array = {24,56,11,66,32,8};
//创建冒泡排序类的对象
BubbleSort sorter = new BubbleSort();
//调用下面的排序方法
sorter.sort(array);
...
直接选择排序
基本思想是将指定排序位置与其他数组元素分别相比,如果满足条件就交换元素值(不是交换相邻元素),而是把满足条件的元素与指定的排序位置交换,这样好的位置逐渐扩大,最后整个数组都成为已排序好的格式算法示例:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序地放在已排好序的数列的最后,直到全部待排序的数据元素排完
public class SelectSort {...}
反转排序
就是把数组最后一个元素与第一个元素替换,倒数第二个元素与第二个元素替换,以此类推,直到所有数组元素反转替换反转排序是对数组两边的元素进行替换,所以只需要循环数组长度的半数次,如数组长度为 7,那么 for 只要循环 3 次
public class ReverseSort {...}
数据结构与算法是程序员求职路上的必经之路...
学习算法最好通读三四遍,真正理解了之后再尝试自己写
第 7 章 类和对象 Classes and Objects
https://docs.oracle.com/javase/tutorial/java/javaOO/index.html
面向对象设计实质上就是对现实世界的对象进行建模操作
对象 Object
通常对象划分为两个部分,静态部分与动态部分
静态部分,顾名思义就是不能动的部分,这个部分被称为属性,任何对象都会具备其自身属性,如一个人的高矮胖瘦,而这个人可以说话、行走,这些事这个人具备的行为,也就是动态部分
在计算机世界中,面向对象程序设计的思想要以对象来思考问题,首先要将现实世界实体抽象为对象,然后考虑这个对象具备的行为(动态部分)
类 Class
类就是同一类事物的统称,如果将现实世界的一个事物抽象成对象,类就是这类对象的统称在 Java 语言中,类中对象的行为是以方法的形式定义的,对象的属性是以成员变量的形式定义的,而类包括对象的属性和方法
封装 Package
将对象的属性和行为封装起来,其载体就是类,类通常对客户隐藏其实现细节,这就是封装的思想
{...}
继承
继承思想可以缩短软件开发的时间,复用那些已经定义好的类,可以提高系统性能,减少系统在使用过程中出现错误得几率
{...}
多态
{...}
this 关键字
this
关键字代表本类对象的引用
类的构造方法
构造方法是一个与类同名的方法,对象创建就是通过构造方法完成的每当类实例化一个对象时,类都会自动调用构造方法
构造方法没有返回值
构造方法的名称要与本类的名称相同
static 静态
被声明为 static 的变量、常量和方法被称为静态成员,静态成员属于类所有,区别于个别对象,可以在本类或其他类使用类名和.
运算符调用静态成员,语法为:类名.静态类成员在静态方法中不可以使用this 关键字和调用非静态方法
类的主方法
public static void main(String[] args) {...}
主方法是静态的,直接调用方法也必须是静态的,主方法没有返回值,性参为数组,其中 args[0]~args[n]分别代表程序的第一个参数到第 n 个参数,可使用 args.length 获取参数个数
对象
Test test = new Test();
对象被创建出来时,就是一个对象的引用,并在内存中为对象分配了存储空间每个对象都算相互独立的,在内存中占据独立的内存地址,并且每个对象都具有自己的生命周期,当一个对象的生命周期结束时,对象就变成垃圾,由 Java 虚拟机自带的垃圾回收机制处理,不能再被使用
public class CreateObject {
public CreateObject() {
System.out.println("创建对象");
}
public static void main(String args[]) {
new CreateObject();
}
}
在上述实例的主方法中使用 new 操作符创建对象创建对象的同时,将自动调用构造方法中的代码
访问对象的属性和行为
使用对象.类成员
获取对象的属性和行为
对象的比较
使用==
运算符与equals()
方法前者为比较引用地址是否相等
后者为String类
方法,比较内容
对象的销毁
每个对象都有生命周期,当对象的生命周期结束时,分配给给对象的内存地址将会被回收对象引用超过其作用范围,这个对象将被视为垃圾对象赋值为null
总结
本章学习了
面向对象的概念
类的定义
成员方法
类的构造方法
主方法
对象的应用
在此基础上可以编写类
定义类成员
构造方法
主方法
类及类成员可以使用权限修饰符
进行修饰,对象的创建
比较
销毁
十分重要
本章只点到了类和对象,仍需通过编码去深刻理解面向对象 OOP 的概念
第 8 章 包装类
第 9 章 数学类
鉴于此类属于 api 的范畴,先重点学面向对象的特性,这些内容可以以后需要时再补充
Day 4 (#0521)
上午英语课期中考试寫完试卷就来图书馆看书了,周一周二的课又多又无趣
今天看到了焦虑的话题,回想这几天,有了专一的学习目标(Java!)并且充分利用好了时间,完全没有以前那种焦虑的感觉了(以前是目标太分散,又不想玩又不想学,所以很焦虑)
今天学习面向对象的概念不太容易,是否应该边看代码边敲边思考?
第 10 章 继承、多态与接口
本章为 Java 面向对象特性的学习,一下子不太好理解,需要多花点时间琢磨,多回来看看,写代码体验特性
继承 extend
在 Java 中使用extends
关键字来标识两个类的继承关系
class Father {...}
class Son extends Father {...}
这里 Son 类继承了 Father 类(类名不重要)
super 关键字
super()
语句调用父类的构造方法
super
关键字调用父类的成员方法但子类没有权限调用父类中被修饰为privite
的方法,只可调用public
和 protected
的成员方法
重写与重构
重写就是在子类中将父类的成员方法的名称保留,重写成员方法的实现内容,更改成员方法的存储权限,或是修改成员方法的返回值类型
当重写父类方法时,修改方法的修饰权限只能从小的范围到大的范围改变
重构就是子类与父类的成员方法返回值、方法名称、参数类型及个数完全相同,唯一不同的是方法实现内容**
Object 类 所有类的爸爸
在 Java 中,所有的类都直接或间接继承了java.lang.Object
类
Object 类是比较特殊的类,它是所有类的父类,是 Java 类层中最高层类
由于所有的类都是 Object 类的子类,所以任何类都可以重写 Object 类中的方法
getClass()方法
是 Object 类定义的方法,它会返回对象执行时的 Class 实例,然后调用 getName()方法可以取得类的名称
getClass().getname();
可将 getClass()方法与 toString()方法联合使用
toString()方法
是将一个对象返回为字符串形式
equals()方法
==
比较的是两个对象的引用是否相等,而equals()
比较两个对象的实际内容
书中此处有个实例,与上文反道而行之,不太懂
对象类型的转换 向上转型|向下转型
暂未理解
使用instanceof判断对象类型
可使用instanceof
操作符判断是否一个类实现了某个借口,也可判断一个实例对象是否属于一个类
myobject instanceof ExampleClass
表达式返回值为布尔boolean值,true & false,可搭配if等语句使用...
方法的重载
为了让方法名相同而形参不同的构造方法存在,必须用到方法重载
方法的重载就是在同一个类中允许同时存在一个以上的同名方法,只要这些方法的参数个数或类型不同即可
不定长参数方法:
public static int add(int...a) {...}
返回值 方法名(参数数据类型...参数名称)
不定长参数a就是一个数组,可搭配循环语句使用
多态
hmmm...not easy to understand
抽象类 abstract
在解决实际问题时,一般将父类定义为抽象类,需要使用这个父类进行继承与多态处理,继承树越中越是在上方的类越抽象
在Java中设置抽象类不可实例化对象,但它的子类可以
抽象类的语法
public abstract class TestClass{
abstract void testAbstarct(); //定义抽象类方法
}
抽象类没有方法体,这个方法本身没有意义,除非它被重写,而承载这个抽象方法的抽象类必须被继承,抽象类除了被继承之外没有任何意义
只要类中有一个抽象方法,此类就被标记为抽象类
抽象类被继承后需要实现其中所有的抽象方法,也就是保证相同的方法名称、参数列表和相同返回值类型创建出非抽象方法,当然也可以是抽象方法
接口 interface
接口是抽象类的延伸,可以将它看作是纯粹的抽象类,接口中的所有方法都没有方法体
public interface drawInterface{
void draw(); //接口内的方法省略abstract抽象关键字
}
一个类实现一个接口可以使用implements关键字
class PXSbianxing extends Sbianxing implements drawInterface{...}
实现
在接口中定义的方法必须被定义为public或abstract形式,在接口中定义的任何字段都是static和final的
Java中不允许多重继承,但使用接口就可以,可以将所有需要继承的接口放置在implements关键字后并逗号隔开
总结
了解继承与多态的机制,掌握重载类型转换,学会使用接口与抽象类
依然不好懂
Day 5 (#0522)
面向对象的特性确实不易懂,囫囵吞枣地学或者找点视频看,通读几遍概念,过段时间再回来回顾一下应该就可以了
第 11 章 类的高级特性
Java类包 package
Java中提供了一种管理类文件的机制,就是类包
为了防止类名冲突,将两个同名类放置在不同的包中
java.util.Date date = new java.util.Date();
package 包名 //定义包
import 包名 //导入包
导入静态成员并使用
import static java.lang.Math.max;
import static java.lang.System.out;
class ImportTest {
public static void main(String args[]) {
//直接使用静态成员
out.println("1和4的较大值为" + max(1, 4))
}
}
final 变量
final关键字可用于变量声明,设置后不可改变该变量的值,通常final定义的变量为常量
final关键字定义的变量必须在声明时赋值
final double PI = 3.14; //常量名 通常大写
定义为final的数据无论是常量、对象引用还是数组,在主函数中都不可以被改变
final定义的对象引用只能指向一个对象,不可再指向其他对象,但对象本身的值是可以改变的
使用static final
关键字使内存区域的值恒定不变
声明final变量不赋值的,称为空白final,可在构造方法中赋值
构造方法就是和类名相同的方法
final 方法
定义为final
的方法不能被重写
但是父类被定义为private final
的方法似乎可以被子类覆盖
class Parents {
private final void doit() {
System.out.println("First doit");
}
final void doit2() {
System.out.println("First doit2");
}
public void doit3() {
System.out.println("First doit3");
}
}
class Sub extends Parents {
public final void doit() {
System.out.println("Sub doit");
}
//final void doit2() {} //final方法不能覆盖
public void doit3() {
System.out.println("Sub doit3");
}
}
public class Finals {
public static void main(String[] args) {
Sub s = new Sub();
s.doit();
Parents p = s; //向上转型
//p.doit(); //不能调用private方法
p.doit2();
p.doit3();
}
}
可见final方法不能被覆盖,向上转型操作后,对象p只能调用正常覆盖的doit3()方法,却不能调用doit()方法,可见子类中的doit()方法并不是正常覆盖,而是生成一个新的方法
final 类
定义为final的类不能被继承
如果将某个类设置为final形式,则类中的所有方法都被隐式设置为final形式
但是final类中的成员变量可以被定义为final或非final形式
//final class
final class FinalClass {
int a = 3;
void doit() {
}
public static void main(String[] args) {
FinalClass finalClass = new FinalClass();
finalClass.a++;
System.out.println(finalClass.a);
}
}
内部类
如果在类中再定义一个类,称为内部类
成员内部类
在内部类中可以随意使用外部类的成员方法以及成员变量,尽管成员修饰为private
内部类的实例一定要绑定在外部类的实例上,如果从外部类中初始化一个内部类对象,那么内部类对象就会绑定在外部类对象上。
内部类初始化方式与其他类初始化方式相同,都是用new关键字。
//innerClass
class OuterClass {
innerClass in = new innerClass();
public void out() {
in.inf();
}
class innerClass {
innerClass() {
}
public void inf() {
}
int y = 0;
}
public innerClass doit() {
// y = 4;
in.y = 4;
return new innerClass();
}
public static void main(String[] args) {
OuterClass out = new OuterClass();
OuterClass.innerClass in = out.doit();
OuterClass.innerClass in2 = out.new innerClass();
}
}
内部类可以访问它的外部类成员,但内部类成员只有在内部类的范围内是可知的,不能被外部类使用。
在实例化内部类对象时,不能在new操作符之前使用外部类名称实例化对象,而是应该使用外部类的对象来创建其内部类的对象。
内部类向上转型为接口
{...}
使用this关键字获取内部类与外部类的引用
如果在外部类中定义的成员变量与内部类中哦的成员变量名相同,可以使用this关键字
public class TheSameName {
private int x;
private class Inner { //Inner内部类
private int x = 9;
public void doit(int_x) {
x++; //^^^
this.x++; //Inner class
TheSameName.this.x++; //TheSameName class
}
}
}
局部内部类
内部类不仅可以在类中进行定义,也可以在类的局部位置定义,如在类的方法或任意的作用域中均可以定义内部类
如果需要在方法体中使用局部变量,该局部变量需要被设置为fina类型
方法中定义的内部类只能访问方法中final类型的局部变量,这是因为在方法中定义的局部变量相当于一个常量,它的生命周期超出方法运行的生命周期,由于该局部变量被设置为final,所以不能在内部类中改变该局部变量的值
匿名内部类
class OuterClass4 {
public OutInterface2 doit() {
return new OuterInterface2() { //声明匿名内部类
private int i = 0;
public int getValue() {
return i;
}
}; //匿名内部类定义结束分号
}
}
匿名内部类语法如下
return new ClassName() {
//...
};
匿名内部类使用默认构造方法来生成OutInterface2对象
定义结束后要加;分号,代表创建OutInterface2引用表达式
静态内部类
在内部类前添加static
就变为静态内部类了
一个静态内部类中可以声明static成员,但是在非静态内部类中不可声明静态成员
静态内部类的特点:
不可使用外部类的非静态成员(所以静态内部类较为少见)
创建静态内部类的对象,不需要其外部类的对象
内部类的继承
内部类也可以继承但比继承普通类复杂,需设置专门的语法来完成
//extend InClass
class ClassA {
class ClassB {
}
}
class OutClass extends ClassA.ClassB { //继承内部类ClassB
public OutClass(ClassA a) {
a.super();
}
}
在某个类继承内部类时,必须给予这个类一个带参数的构造方法,并且该构造方法的参数为需要继承内部类的外部类的引用,同时在构造方法体中使用a.super()语句,这样才为继承提供了必要的对象引用
总结
本章学习了Java语言的包
final关键字
内部类
学会如何导入包
定义final变量
final方法
final类
内部类的用法
OOP不算很好懂。