how2j学习笔记(JAVA基础)

针对how2j的JAVA基础做的个人笔记,若有帮助不胜荣幸

学习网址请点击:https://how2j.cn?p=162023

学习的十点建议

  • 慢慢来,理解的越多,就越不需要死记硬背

    别只是看过去,要停下来思考,就当做真的有人来问你问题。

    你越强迫大脑思考,你就越有机会学习与记忆。

  • 做习题,写笔记

    许多证据都能证明练习活动能够提高学习效率

  • 认真阅读,书上没有蠢问题

  • 不要只是一种姿势

    站起来,伸展一下,到处走走。这样会让你的大脑有不同的感觉,

    并能防止学习过程与特定地点产生过多联系。

  • 把本书当作睡前读物,不然至少当做每天的最后一项挑战

    放下书本后的时间也是学习的一部分,大脑需要自己的时间来处理,

    如果在处理过程中还有其他输入,多少会丢失点东西

  • 多喝水

    大脑在水分充足的情况下运作最好,失水会降低人的认知能力

  • 大声说出来

    说话活动会用到大脑的其他部分,如果你要了解某些东西,或者增加记忆度,

    你需要大声说出来

  • 倾听大脑的声音

    注意是否负载过重,如果你感觉昏昏沉沉的,过目即忘,那就休息一下

  • 感受内容

    必须要让大脑知道,进入故事的情境中。

  • 自己编写程序并执行

    输入范例程序并跑跑看,Head First Java范例程序可以从https://github.com/bethrobson/Head-First-Java下载

常见的问题及解答

main()有什么作用?

  • 测试真正的类
  • 启动你的java程序

类与对象有什么联系?

类是对象的抽象,对象是类的实现或实例化。

我可不可以忽略返回值?

java要求一定要处理返回值,如果没有返回值就要标明void,否则就必须要有对应类型的返回值!

next和nextline有啥区别?

next在输入有效字符之前输入的空格,换行,tab都是无效的,在输入有效字符之后输入的空格,换行,tab都是它的结束符

nextline的开始结束都只有换行,中间输入的空格,tab都会照常输出

编译器和虚拟机有啥关系?

别问,问了就是不知道,先学完基础和中级再搞JVM

==与equals()区别在哪?

  • 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快,但是ArrayList用起来舒服,而且性能差异不大。

接口有啥意义?啥时候需要接口?

有的时候发现写不写接口都是可以的,要真正理解接口在面向对象的价值,需要学习多态之后才能深入理解。

函数与类前面的修饰符示例

how2j学习笔记(JAVA基础)_第1张图片

控制结构示例

包含的内容有: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主数据类型+引用=变量

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

如果一个变量是类类型,而非基本类型,那么该变量又叫引用。

可以把实例化的对象的reference当做一个遥控器,远程遥控其他的行为。

当实例化一个对象的时候,会创建一个遥控器,遥控器在栈区,对象在堆区。

Book b=new Book();//new Book();只是创建一个对象,前面的b表示引用指向他,等号表示指向
Book c=new Book();
Book d=c;//这时候c和d两个遥控器遥控一个对象
c=b;//这时候c和b遥控同一个对象,但是d仍然遥控自己的那个对象

作用域

  • 声明在类的外面,变量就叫做字段 或者属性成员变量Field ,其作用域就是从其声明的位置开始的整个类
  • 变量是参数:作用域在方法中
  • 方法的局部变量:在方法中创建的变量作用域在方法内部

final 修饰一个变量

当一个变量被final修饰的时候,该变量只有一次赋值的机会

  • 声明的是否赋值,后面可以赋值一次
  • 声明的时候不赋值,后面再赋值一次
  • 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)

  • 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循环

格式:

for (int each : values) {
    System.out.println(each);//do something
}

Arrays类的常用方法

包: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

动态的,长度不限。

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();
    }
}

this关键字

指向当前类本身的元素,类似c++,即使是同名的,this.name=name;也可以赋值,隐式调用。

但是只要和属性不同名,直接赋值也OK的

this还能调用现成的构造方法

一个包(package)内的class可以互相访问

要访问别的class用import导入哦,import package.class

成员变量四种修饰符

标黄了就表示不能

自身 同包子类 不同包子类 同包类 其他类
private 访问 继承 继承 访问 访问
protected 访问 继承 继承 访问 访问
public 访问 继承 继承 访问 访问
package 访问 继承 继承 访问 访问

static静态属性(类属性)与静态方法(类方法)

所有的饮用都能访问,用static修饰,到时候直接用 类+原点操作符 就能直接调用

例如Math库的Pi,math.pi

属性初始化

对象属性初始化有3种

  • 声明该属性的时候初始化 publicString 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,例如

super(name);//在ADHero带参构造下写,这个相当于调用参数为name的父类构造方法
  • 调用父类属性
super.speed;//父类的属性
  • 调用父类的方法
super.useItem();//父类的方法

Object类

Object类是所有类的父类

toString()方法

得不到有效信息就要重写这个方法

finalize()方法

垃圾回收时调用

垃圾回收的条件:垃圾很多的时候再回收

equals()方法

判断是否相等,可以考虑重写

hashCode()方法

返回一个对象的哈希值

线程同步相关方法

wait()
notify()
notifyAll()

getClass()

涉及反射机制

final

  • 修饰类。表示Hero不能够被继承

  • 修饰方法。方法不能够被重写

  • 修饰基本类型变量。该变量只有一次赋值机会

  • 修饰引用。表示该引用只有1次指向对象的机会

  • 修饰常量。表示可以直接访问当不能修改的常量

    public static final int itemTotalNumber = 6;
    

abstract抽象类

  • 在类中声明一个方法,这个方法没有实现体,是一个“空”方法 ,即抽象方法。

  • 一个类有抽象方法,就必须声明为抽象类。一个抽象类可以没有抽象方法。

  • 抽象类不能直接实例化,只能通过子类来实例化

  • 一个子类继承了抽象类就必须重写抽象方法,重写的时候就不用写abstract了

抽象类与接口的区别

区别1:

  • 子类只能继承一个抽象类,不能继承多个
  • 子类可以实现多个 接口

区别2:

  • 抽象类可以定义

    ​ public,protected,package,private

    ​ 静态和非静态属性

    ​ final和非final属性

  • 但是接口中声明的属性,只能是
    public

    ​ 静态

    ​ final的
    即使你没有特意声明

Java的内部类

内部类: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("新的进攻手段");
            }
        };

本地类

本地类可以理解为有名字的匿名类

可以直接在方法里创建一个类

default默认方法

jdk1.8之后的新特性

接口中的实现方法,可以在实现的类中直接调用

封装类

所有基本类型都有对应的类类型,例如int=>integer

Number类

数字封装类有

Byte,Short,Integer,Long,Float,Double

这些类都是抽象类Number的子类

how2j学习笔记(JAVA基础)_第2张图片

基本类型转封装类

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的最大值最小值

//int的最大值
System.out.println(Integer.MAX_VALUE);
//int的最小值      
System.out.println(Integer.MIN_VALUE);

数字与字符串

相互转换

  • 字符串=>数字(第二种方式不介绍了)

    String str = String.valueOf(5);
    
  • 字符串转数字

    int i= Integer.parseInt("15");
    

Math类

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

printf和format能够达到一模一样的效果,如何通过eclipse查看java源代码 可以看到,在printf中直接调用了format

String sentenceFormat ="%s 在进行了连续 %d 次击杀后,获得了 %s 的称号%n";
System.out.printf(sentenceFormat,name,kill,title);

换行符

Java是跨平台的编程语言,同样的代码,可以在不同的平台使用,

然而在不同的操作系统,换行符是不一样的

  • 在DOS和Windows中,每行结尾是 “\r\n”;
  • Linux系统里,每行结尾只有 “\n”;
  • Mac系统里,每行结尾是只有 “\r”。

为了使得同一个java程序的换行符在所有的操作系统中都有一样的表现,使用%n,就可以做到平台无关的换行

字符

char用来保存一个字符

char对应的封装类是Character

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 忽略大小写判断是否相等

StringBuffer

常用操作

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);

gettime()

返回long型的时间戳

直接打印对象,会看到 “Tue Jan 05 09:51:48 CST 2016” 这样的格式,可读性比较差,

为了获得“2016/1/5 09:51:48”这样的格式 请参考日期格式化

注:System.currentTimeMillis()也可以达到gettime()的功能

格式化

  • y 代表年
  • M 代表月
  • d 代表日
  • H 代表24进制的小时
  • h 代表12进制的小时
  • m 代表分钟
  • s 代表秒
  • S 代表毫秒
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
    }
}

还能翻日历,别鸡巴学了,感觉没啥用啊

结语


预祝大家学习进步✔


我爱你 帅帅龙


你可能感兴趣的:(JAVA学习笔记,how2j学习笔记,java)