针对how2j的JAVA基础做的个人笔记,若有帮助不胜荣幸
学习网址请点击:https://how2j.cn?p=162023
慢慢来,理解的越多,就越不需要死记硬背
别只是看过去,要停下来思考,就当做真的有人来问你问题。
你越强迫大脑思考,你就越有机会学习与记忆。
做习题,写笔记
许多证据都能证明练习活动能够提高学习效率
认真阅读,书上没有蠢问题
不要只是一种姿势
站起来,伸展一下,到处走走。这样会让你的大脑有不同的感觉,
并能防止学习过程与特定地点产生过多联系。
把本书当作睡前读物,不然至少当做每天的最后一项挑战
放下书本后的时间也是学习的一部分,大脑需要自己的时间来处理,
如果在处理过程中还有其他输入,多少会丢失点东西
多喝水
大脑在水分充足的情况下运作最好,失水会降低人的认知能力
大声说出来
说话活动会用到大脑的其他部分,如果你要了解某些东西,或者增加记忆度,
你需要大声说出来
倾听大脑的声音
注意是否负载过重,如果你感觉昏昏沉沉的,过目即忘,那就休息一下
感受内容
必须要让大脑知道,进入故事的情境中。
自己编写程序并执行
输入范例程序并跑跑看,Head First Java范例程序可以从https://github.com/bethrobson/Head-First-Java下载
类是对象的抽象,对象是类的实现或实例化。
java要求一定要处理返回值,如果没有返回值就要标明void,否则就必须要有对应类型的返回值!
next在输入有效字符之前输入的空格,换行,tab都是无效的,在输入有效字符之后输入的空格,换行,tab都是它的结束符
nextline的开始结束都只有换行,中间输入的空格,tab都会照常输出
别问,问了就是不知道,先学完基础和中级再搞JVM
primitive主数据类型判断是否相等用==即可,==还能判断两个引用是否指向同一个对象
int a=3;
byte b=3;
if(a==b) //true
Foo a=new Foo();
Foo b=new Foo();
Foo c=a;
if(a==b) //false
if(a==c) //true
if(b==c) //false
判断两个对象是否相等使用equals(),例如字符串。
String a="wocao";
if(a=="wocao") //false
if(a.equals("wocao")) //true
public class test {
public static void main(String[] args) {
int a=Integer.parseInt("123");
System.out.println(a);
double b=Double.parseDouble("3.14");
System.out.println(b);
}
}
长得像,但他其实是一个对象,主数据类型的数组比ArrayList快,但是ArrayList用起来舒服,而且性能差异不大。
有的时候发现写不写接口都是可以的,要真正理解接口在面向对象的价值,需要学习多态之后才能深入理解。
包含的内容有:for循环、while循环、switch语句,if语句
public static void main(String[] args) {
int a=0;
for (int i = 0; i <10 ; i++) {
a+=1;
}
while (a>0){
if(a%2==0){
System.out.println(a+"是偶数");
}
else{
System.out.println(a+"是奇数");
}
a-=1;
}
switch(a){
case 0:
System.out.println("a是"+0);
break;
case 1:
System.out.println("a是"+1);
break;
}
}
primitive主数据类型+引用=变量
类型 | 位数 | 值域 |
---|---|---|
boolean | JVM决定 | true或false |
char | 16 bits | 0~65535 |
byte | 8 bits | -128~127 |
short | 16 bits | -32768~32767 |
int | 32 bits | ±2147483648 |
long | 64 bits | - 很大 ~ + 很大 |
float | 32 bits | 范围规模可变 |
double | 64 bits | 范围规模可变 |
注意,整数默认为int类型,小数默认为double类型,在创建其他类型变量以及运算时要标明。
float a=1.5f;//这个f不写则1.5默认为double,然后由double转为float
当大杯转小杯时可能会导致数据溢出,因此要注意数据的范围,以此来选择数据类型。
当编译器无法识别能否进行数据转化时,需要进行强制转换。
public class test {
public static void main(String[] args) {
long a=123;
//int b=a;会报错,编译不通过
int b=(int) a;
System.out.println(a);
}
}
自动强制转换的规则:
如果一个变量是类类型,而非基本类型,那么该变量又叫引用。
可以把实例化的对象的reference当做一个遥控器,远程遥控其他的行为。
当实例化一个对象的时候,会创建一个遥控器,遥控器在栈区,对象在堆区。
Book b=new Book();//new Book();只是创建一个对象,前面的b表示引用指向他,等号表示指向
Book c=new Book();
Book d=c;//这时候c和d两个遥控器遥控一个对象
c=b;//这时候c和b遥控同一个对象,但是d仍然遥控自己的那个对象
当一个变量被final修饰的时候,该变量只有一次赋值的机会
即使参数是final修饰的,也只能赋值一次
运算符 | 描述 |
---|---|
&& | 与 |
|| | 或 |
!= | 不等于 |
! | 非 |
短运算符
比如&&,当两端都为真才得到真,当左边为假便不会再计算右边
长运算符
比如&,强制虚拟机必须做两端的操作
符号 | 描述 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取余 |
++ | 自增 |
– | 自减 |
符号 | 描述 |
---|---|
> | 大于 |
>= | 大于或等于 |
< | 小于 |
<= | 小于或等于 |
== | 是否相等 |
!= | 不等于 |
参见ACM——位运算符整理
用的不多,用来提高运算速度,可以忽略不学。
符号 | 描述 |
---|---|
+= | a=a+x |
-= | a=a-x |
*= | a=a*x |
/= | a=a/x |
%= | a=a%x |
&= | a=a&x |
|= | a=a|x |
^= | a=a^x |
>>= | a=a>>x |
<<= | a=a< |
(判断)?A:B;
当判断的内容为真时返回A,否则返回B
int k = i < j ? 99 : 88;
数组是一个固定长度,包含相同类型数据的容器,具有默认值
public class demo extends test{
public static void main(String[] args) {
int []a=new int[5];//或者是写int a[]=new int[5];
int []b = new int[]{100,102,444,836,3236};
a[0]=15;
System.out.println(a[0]);
System.out.println(a.length);
}
}
或者使用Arrays类的方法,或者是
复制数组: System.arraycopy(src, srcPos, dest, destPos, length)
public static void main(String[] args) {
int a [] = new int[]{18,62,68,82,65,9};
int b[] = new int[3];//分配了长度是3的空间,但是没有赋值
//通过数组赋值把,a数组的前3位赋值到b数组
System.arraycopy(a, 0, b, 0, 3);
//把内容打印出来
for (int i:b) {
System.out.print(b[i] + " ");
}
}
public static void main(String[] args) {
//初始化二维数组,
int[][] a = new int[2][3]; //有两个一维数组,每个一维数组的长度是3
a[1][2] = 5; //可以直接访问一维数组,因为已经分配了空间
//只分配了二维数组
int[][] b = new int[2][]; //有两个一维数组,每个一维数组的长度暂未分配
b[0] =new int[3]; //必须事先分配长度,才可以访问
b[0][2] = 5;
//指定内容的同时,分配空间
int[][] c = new int[][]{{1,2,4}, {4,5}, {6,7,8,9}};
}
格式:
for (int each : values) {
System.out.println(each);//do something
}
包:import java.util.Arrays;
常用方法:
方法 | 描述 | 作用 |
---|---|---|
int[] b = Arrays.copyOfRange(a, 0, 3); | a是原数组,0取的到,3取不到 | 数组复制 |
String content = Arrays.toString(a); | a是数组,得到[18, 62, 68, 82, 65, 9] | 转换为字符串 |
Arrays.sort(a); | a是数组 | 升序排序 |
Arrays.binarySearch(a, 62 ): |
62是要搜索的元素 | 搜索,前提是升序排列了,不存在返回负数 |
Arrays.equals(a, b) | ab为两个数组 | 判断两个数组是否相同 |
Arrays.fill(a, 5 ); |
填充a数组全为5 | 填充(初始化) |
动态的,长度不限。
ArrayList<String> mystr=new ArrayList<String>();
常用方法
方法 | 描述 |
---|---|
add(Obgect elem) | 向list加入对象 |
remove(index x) | 根据索引移除对象 |
remove(Obgect elem) | 移除该对象 |
contains(Object elem) | 包含返回"true" |
isEmpy() | list中没元素返回"true" |
indexof(Object elem) | 返回对象的索引 |
size() | 返回list的成员个数 |
get(int index) | 返回当前索引的值 |
Dog[] myDogs=new Dog[3];
myDogs[0]=new Dog();//放咖啡的杯子就只能放咖啡
myDogs[0].name="Fido";
myDogs[0].bark();
在创建数据时,标明private,否则实例化的对象可以直接修改对应的值,把内裤给别人看了就挺尴尬的…
可以创建对应的方法来获取或者设置相应数据,比如
public void setname(String newname){
name=newname+getname();
}
当你仅仅只是声明一个变量,但是不初始化的时候,java会默认给你赋一个值
数据类型 | 默认值 |
---|---|
integers | 0 |
floating points | 0.0 |
boolean | false |
references | null |
实例变量是声明在类里面的,局部变量是声明在类的方法里的,局部变量在使用前必须要先赋值,否则编译器会报错。
关键字:extends
一个父类可以被多个子类继承,但是一个子类只能继承一个父类
同名函数,参数相同时,子类覆盖父类,参数不同,名字相同没关系
在参数位置加三个点,例如
public void attack(Hero ... heros){
for (Hero:heros) {
//do something
}
}
//传参时参数用逗号隔开
声明为public,构造函数可以重载哦,注意别写void ,否则就成了普通方法
class demo {
public demo(String a){
System.out.println("调用了构造函数参数是"+a);
}
public demo(){
System.out.println("调用了默认构造");
}
public static void main(String[] args) {
demo test1=new demo("草");
demo test2=new demo();
}
}
指向当前类本身的元素,类似c++,即使是同名的,this.name=name;也可以赋值,隐式调用。
但是只要和属性不同名,直接赋值也OK的
this还能调用现成的构造方法
要访问别的class用import导入哦,import package.class
标黄了就表示不能
自身 | 同包子类 | 不同包子类 | 同包类 | 其他类 | |
---|---|---|---|---|---|
private | 访问 | 继承 | 继承 | 访问 | 访问 |
protected | 访问 | 继承 | 继承 | 访问 | 访问 |
public | 访问 | 继承 | 继承 | 访问 | 访问 |
package | 访问 | 继承 | 继承 | 访问 | 访问 |
所有的饮用都能访问,用static修饰,到时候直接用 类+原点操作符 就能直接调用
例如Math库的Pi,math.pi
对象属性初始化有3种
String name = "some hero"
;接口就像约定,接口定义某些方法,交给某个类去实现,一个类可以实现多个接口 用逗号隔开就行
接口定义关键字:interface
public interface AD{
public void physicAttack();
}
类去实现接口的关键字:implements
public class ADHero extends Hero implements AD{
public void physicAttack(){
System.out.println("发起进攻");
}
}
注意,假如类不实现接口约定的方法,这个类会报错。
接口有啥意义?啥时候需要接口?
有的时候发现写不写接口都是可以的,要真正理解接口在面向对象的价值,需要学习多态之后才能深入理解。
instanceof判断引用是否指向对象
ADHero引用转Hero引用是完全没问题的
需要用到子类的类名进行强制转化,为什么要加呢,因为不知道子类的引用指向的对象是谁,
不过父类转子类之后再转子类可能会报错
要实现类的多态,需要加以下条件
LifePotion(血瓶)和MagicPotion(魔瓶)都继承于Item,当使用effect方法时只需要传入Item对象即可,
不用再写useLifePotion和useMagicPotion两个方法
package charactor;
import property.Item;
import property.LifePotion;
import property.MagicPotion;
public class Hero {
public String name;
protected float hp;
public void useItem(Item i){
i.effect();
}
public static void main(String[] args) {
Hero garen = new Hero();
garen.name = "盖伦";
LifePotion lp =new LifePotion();
MagicPotion mp =new MagicPotion();
garen.useItem(lp);
garen.useItem(mp);
}
}
子类隐藏父类的方法
与重写类似,方法的重写是子类覆盖父类的对象方法
隐藏,就是子类覆盖父类的类方法
其实很类似,就是多了个static修饰词,表示静态的
实例化子类的时候,会先调用父类的构造方法,当多个构造方法时,默认调用父类无参构造方法
如果想调用父类带参构造,需要用super,例如
super(name);//在ADHero带参构造下写,这个相当于调用参数为name的父类构造方法
super.speed;//父类的属性
super.useItem();//父类的方法
Object类是所有类的父类
得不到有效信息就要重写这个方法
垃圾回收时调用
垃圾回收的条件:垃圾很多的时候再回收
判断是否相等,可以考虑重写
返回一个对象的哈希值
wait()
notify()
notifyAll()
涉及反射机制
修饰类。表示Hero不能够被继承
修饰方法。方法不能够被重写
修饰基本类型变量。该变量只有一次赋值机会
修饰引用。表示该引用只有1次指向对象的机会
修饰常量。表示可以直接访问当不能修改的常量
public static final int itemTotalNumber = 6;
在类中声明一个方法,这个方法没有实现体,是一个“空”方法 ,即抽象方法。
一个类有抽象方法,就必须声明为抽象类。一个抽象类可以没有抽象方法。
抽象类不能直接实例化,只能通过子类来实例化
一个子类继承了抽象类就必须重写抽象方法,重写的时候就不用写abstract了
区别1:
区别2:
抽象类可以定义
public,protected,package,private
静态和非静态属性
final和非final属性
但是接口中声明的属性,只能是
public
静态
final的
即使你没有特意声明
内部类:java文件的class里面的类,属性和方法平等的位置
内部类可以直接访问外部类的属性和方法
BattleScore类是Hero的内部类
Hero garen = new Hero();
// 实例化内部类
// BattleScore对象只有在一个英雄对象存在的时候才有意义
// 所以其实例化必须建立在一个外部类对象的基础之上
BattleScore score = garen.new BattleScore();
//然后使用内部类的方法
static修饰,就不用使用外部类了
Hero.EnemyCrystal crystal = new Hero.EnemyCrystal();
Hero是一个抽象类(abstruct),可以在main里直接实例化实现抽象方法,虚拟机会自动创建一个类
Hero h = new Hero(){
//当场实现attack方法
public void attack() {
System.out.println("新的进攻手段");
}
};
本地类可以理解为有名字的匿名类
可以直接在方法里创建一个类
jdk1.8之后的新特性
接口中的实现方法,可以在实现的类中直接调用
所有基本类型都有对应的类类型,例如int=>integer
数字封装类有
Byte,Short,Integer,Long,Float,Double
这些类都是抽象类Number的子类
int i = 5;
//基本类型转换成封装类型
Integer it = new Integer(i);
int i = 5;
//基本类型转换成封装类型
Integer it = new Integer(i);
//封装类型转换成基本类型
int i2 = it.intValue();
不需要调用构造方法,通过=符号自动把 基本类型 转换为 类类型 就叫装箱
int i = 5;
Integer it2 = i;
不需要调用Integer的intValue方法,通过=就自动转换成int类型,就叫拆箱
int i = 5;
Integer it = new Integer(i);
//自动转换就叫拆箱
int i3 = it;
//int的最大值
System.out.println(Integer.MAX_VALUE);
//int的最小值
System.out.println(Integer.MIN_VALUE);
字符串=>数字(第二种方式不介绍了)
String str = String.valueOf(5);
字符串转数字
int i= Integer.parseInt("15");
java.lang.Math提供了一些常用的数学运算方法,并且都是以静态方法的形式存在
package digit;
public class TestNumber {
public static void main(String[] args) {
float f1 = 5.4f;
float f2 = 5.5f;
//5.4四舍五入即5
System.out.println(Math.round(f1));
//5.5四舍五入即6
System.out.println(Math.round(f2));
//得到一个0-1之间的随机浮点数(取不到1)
System.out.println(Math.random());
//得到一个0-10之间的随机整数 (取不到10)
System.out.println((int)( Math.random()*10));
//开方
System.out.println(Math.sqrt(9));
//次方(2的4次方)
System.out.println(Math.pow(2,4));
//π
System.out.println(Math.PI);
//自然常数
System.out.println(Math.E);
}
}
%s 表示字符串
%d 表示数字
%n 表示换行
printf和format能够达到一模一样的效果,如何通过eclipse查看java源代码 可以看到,在printf中直接调用了format
String sentenceFormat ="%s 在进行了连续 %d 次击杀后,获得了 %s 的称号%n";
System.out.printf(sentenceFormat,name,kill,title);
Java是跨平台的编程语言,同样的代码,可以在不同的平台使用,
然而在不同的操作系统,换行符是不一样的
为了使得同一个java程序的换行符在所有的操作系统中都有一样的表现,使用%n,就可以做到平台无关的换行
char用来保存一个字符
char对应的封装类是Character
package character;
public class TestChar {
public static void main(String[] args) {
System.out.println(Character.isLetter('a'));//判断是否为字母
System.out.println(Character.isDigit('a')); //判断是否为数字
System.out.println(Character.isWhitespace(' ')); //是否是空白
System.out.println(Character.isUpperCase('a')); //是否是大写
System.out.println(Character.isLowerCase('a')); //是否是小写
System.out.println(Character.toUpperCase('a')); //转换为大写
System.out.println(Character.toLowerCase('A')); //转换为小写
String a = 'a'; //不能够直接把一个字符转换成字符串
String a2 = Character.toString('a'); //转换为字符串
}
}
charAt | 获取字符 |
---|---|
toCharArray | 获取对应的字符数组 |
subString | 截取子字符串 |
split | 分隔 |
trim | 去掉首尾空格 |
toLowerCase toUpperCase | 大小写 |
indexOf lastIndexOf contains | 定位 |
replaceAll replaceFirst | 替换 |
startsWith | 以…开始 |
endsWith | 以…结束 |
equals | 判断是否相等 |
equalsIgnoreCase | 忽略大小写判断是否相等 |
append追加
delete 删除
insert 插入
reverse 反转
package character;
public class TestString {
public static void main(String[] args) {
String str1 = "let there ";
StringBuffer sb = new StringBuffer(str1); //根据str1创建一个StringBuffer对象
sb.append("be light"); //在最后追加
System.out.println(sb);
sb.delete(4, 10);//删除4-10之间的字符,都是闭区间
System.out.println(sb);
sb.insert(4, "there ");//在4这个位置插入 there
System.out.println(sb);
sb.reverse(); //反转
System.out.println(sb);
}
}
注意:是java.util.Date;
而非 java.sql.Date,此类是给数据库访问的时候使用的
零这个数字,就代表Java中的时间原点,其对应的日期是1970年1月1日 8点0分0秒 ,
为什么对应1970年呢? 因为1969年发布了第一个 UNIX 版本:AT&T,综合考虑,当时就把1970年当做了时间原点。
所有的日期,都是以为这个0点为基准,每过一毫秒,就+1。
// 当前时间
Date d1 = new Date();
System.out.println(d1);
// 从1970年1月1日 早上8点0分0秒 开始经历的毫秒数
Date d2 = new Date(5000);
System.out.println(d2);
返回long型的时间戳
直接打印对象,会看到 “Tue Jan 05 09:51:48 CST 2016” 这样的格式,可读性比较差,
为了获得“2016/1/5 09:51:48”这样的格式 请参考日期格式化
注:System.currentTimeMillis()也可以达到gettime()的功能
package date;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestDate {
public static void main(String[] args) {
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS" );
Date d= new Date();
String str = sdf.format(d);
System.out.println("当前时间通过 yyyy-MM-dd HH:mm:ss SSS 格式化后的输出: "+str);
}
}
转为日期类
package date;
import java.util.Calendar;
import java.util.Date;
public class TestDate {
public static void main(String[] args) {
//采用单例模式获取日历对象Calendar.getInstance();
Calendar c = Calendar.getInstance();
//通过日历对象得到日期对象
Date d = c.getTime();
Date d2 = new Date(0);
c.setTime(d2); //把这个日历,调成日期 : 1970.1.1 08:00:00
}
}
还能翻日历,别鸡巴学了,感觉没啥用啊
预祝大家学习进步✔