JAVA学习-1

1 基础

1.1 进制转换

https://zhuanlan.zhihu.com/p/75291280

1.2 命令提示符

MS-DOS(Microsoft disk operating system)

cd.. 返回上一级
cd \ 返回根路径
dir 查看目录
cls 清屏
exit 退出
javac xxx.java 编译
java xx 解释
jshell 直接在cmd中运行

1.3 JAVA的跨平台特性

  • JVM (java virtual machine): JVM不具备跨平台特性,每个操作系统下都有不同的JVM
    在这里插入图片描述

  • JRE(java runtime environment): java程序运行的环境,包括JVM和运行时所需要的核心库

  • JDK (java development kit): java程序开发工具包,包括JRE和开发人员使用的工具

想运行,装JRE就可以;想开发,必须装JDK
在这里插入图片描述
集成开发环境IDE(integrated development environment): 专门用来提高java软件开发效率的软件,免费的有eclipse,收费的有intellij idea。

1.4 开发步骤

编写->编译->运行
java源程序->编译器->java字节码文件->jvm运行

  • 编译器:javac.exe
  • 解释器:java.exe

1.5 数据类型

  • 整数型:byte short int long (占用1 2 4 8 字节)
  • 浮点型:float double(占用4 8 字节)
  • 字符型:char(占用2字节)
  • 布尔型:boolean(占用1字节)

1.6 ASCII & unicode

ASCII 是美国标准的,unicode是万国码。unicode的0-127跟ASCII是一样的,但是从128开始包括更多字符,甚至包括emoji。

1.7 运行规则

  • 不同类型数据运算的时候,结果是数据范围大的。
  • 任何数据类型与字符串连接的时候,结果都会是字符串。
  • ++num是先加后用,num++是先用后加
  • && 是and, ||是or
  • int max = a>b? a:b
  • str1==str2其实是在比较地址

1.8 快捷键

alt+回车 修复错误
control+y 删除行
ctrl+alt+L 格式的代码

1.9 标准类

  • 所有成员变量都private修饰
  • 每个成员变量都有一对get set方法
  • 有一个无参/又参构造方法

1.10 api

application programming interface: 理解成一个大的字典,里面很多很多方法

2 内存

java的内存划分

  • 全部可以划分5个部分:
  • stack: 存放的是局部变量(方法的参数或方法内部的变量),特点是有作用域,一旦超出作用域,立刻从栈内存中消失。
  • heap:凡是new出来的东西都在堆中,堆内存中的东西都有一个地址(16进制),堆内存中的数据都有默认值。
  • method area:存class相关的信息(包括方法的信息)
  • native method stack:跟操作系统相关
  • pc register(寄存器):与cpu相关
    注意:方法运行在栈当中

2.1 一个对象

在这里插入图片描述

2.2 两个引用指向同一个对象在这里插入图片描述

2.3 静态static的内存图

内存中先有静态内容,然后才有非静态。静态中不能用this。

在这里插入图片描述

2.4 继承多态

在这里插入图片描述

3 类

3.1 Scanner类

java.util.Scanner

Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
String str = sc.next();

3.2 Random类

Random r = new Random();
int num = r.nextInt();
int num = r.nextInt(3);// 表示[0,3)

3.3 ArrayList

数组是不可以改变长度的,但是ArrayList可以。
表示范型,也就是说集合中所有的元素都是同一类型的。

ArrayList list = new ArrayList<>();
list.add();
list.get();
list.remove();
list.size();

关于中的E怎么写(把基本类型转化为包装类):

基本类型包装类
intInteger
charcharacter
byteByte
longLong

其他:将基本类型转化为包装类就是将首字母大写
从JDK1.5开始,支持自动装箱(基本类型->包装类)、自动拆箱(包装类->基本类型)

3.4 字符串

字符串的常量池
在这里插入图片描述
==其实是在比较地址
双引号写的直接在常量池中,而new出来的不再常量池中(因为是引用对象)
str3是把char[]转化为byte[](不在常量池中)

str1.equals(str2)
str1.equalsIgnoreCase(str2)

3.5 Objects

null是不能调用方法的,会抛出空指针异常。Objects类的equals方法对两个对象比较,但是是可以防止控制能异常

boolean equals = Objects.equals(s1, s2);

3.6 Date类

java.util.Date
表示特定的时刻,精确到毫秒。从1970.1.1 00:00:00(英国格林威治时间)开始算。中国是东八区,会把时间增加8个小时。

System.currentTimeMillis();
Date date = new Date(0L);
System.out.println(date.getTime());

3.7 DateFormat类

DateFormat是一个抽象类,不能直接使用,可以用子类

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Main {

    public void demo2() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        Date date = new Date();
        String d = sdf.format(date);
        System.out.println(date);
        System.out.println(d);
    }
    public static void demo3() throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");

        Date date = sdf.parse("2000年06月24日 12时38分55秒");
        System.out.println(date);
    }
}

3.8 Calendar类

clendar是一个抽象类,无法直接创建对象使用,里面有一个静态方法是getInstance(),该方法返回了calendar类的子类对象
static Calendar getInstance() 使用欧仁时区和语言环境获得一个日历。

    public static void demo4() {
        Calendar c = Calendar.getInstance();
        // set方法
        // Calendar.YEAR在Calendar中的静态块
        c.set(Calendar.YEAR, 8888);
        System.out.println(c.get(Calendar.YEAR));

        // get方法
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int date = c.get(Calendar.DATE);

        // add方法
        c.add(Calendar.MONTH, -3);
        System.out.println(c.get(Calendar.MONTH));

        // getTime方法把日历对象转化为日期对象
        Date d = c.getTime();
        System.out.println(d);

    }

3.9 System类

    public static void demo5() {
        // currentTimeMillis方法:返回毫秒为单位的时间,用来提高程序效率
        long s = System.currentTimeMillis();

        // arraycopy方法
        int[] src = {1,2,3,4,5};
        int[] dest = {6,7,8,9,10};
        System.arraycopy(src,0,dest,0,3);
        System.out.println(Arrays.toString(src));
        System.out.println(Arrays.toString(dest));
    }

3.10 StringBuilder类

字符串的底层是一个被final修饰的数组,不能改变,字符串是常量,值在创建之后不能更改。
若进行字符串的相加,内存中就存在多个字符串,占用空间多,效率低下。例如下图,存在5个字符串。
在这里插入图片描述
而StringBuilder类(字符串缓冲区)支持可变的字符串。可以提高字符串的操作效率(看成一个长度可以变化的字符串)。它的底层也是一个数组,但是没有final修饰,可以改变长度。
在这里插入图片描述

    public static void demo6() {
        StringBuilder bu1 = new StringBuilder();
        System.out.println("bu1: " + bu1);

        StringBuilder bu2 = new StringBuilder("abc");
        System.out.println("bu2: " + bu2);

        // append方法
        bu1.append("abc");
        System.out.println(bu1);
        System.out.println(bu1.append("abc") == bu1); // true 说明调用本身
        System.out.println(bu1 == bu2); // false


        // 用StringBuilder的构造方法可以把String转化为StringBuilder
        String s = "hello";
        StringBuilder bu = new StringBuilder(s);
        bu.append("world");
        System.out.println(bu);

        // toString方法:把StringBuilder转化为String
        String str = bu.toString();
        System.out.println(str);
    }

3.11 集合

集合框架
在这里插入图片描述

3.11.1 Collection类

java.util.collection接口,是所有单列集合的最顶层的接口,里面定义了所有单列集合共性的方法。任意的单列接都可以使用collectio接口中的方法。

    public static void demo1(){
        // 创建集合对象,可以使用多态
        Collection<String> coll = new ArrayList<>();
        System.out.println(coll); // 重写了tostring方法

        // add方法
        boolean b1 = coll.add("张三");
        System.out.println(b1);
        System.out.println(coll);
        coll.add("李四");

        // remove
        boolean b2 = coll.remove("赵六");
        System.out.println(b1);
        System.out.println(coll);
        coll.remove("张三");
        System.out.println(coll);

        // contains 判断是否包含元素
        boolean b3 = coll.contains("赵六");

        // isEmpty 判断当前集合是否为空
        boolean b4 = coll.isEmpty();

        // size 判断集合中元素的个数
        int size = coll.size();

        // toArray 把集合中的元素存储到数据中
        Object[] arr = coll.toArray();
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

        // clear
        coll.clear();
    }
3.11.2 Iteration
    public static void demo2(){
        // 迭代器是一个接口,我们无法直接使用,需要使用Iterator接口实现类对象,获取实现类的方式比较特殊
        // iterator接口中有一个方法叫做iterator(), 这个就是返回迭代器的实现类对象
        // 但会元素上进行迭代的迭代器

        /* 迭代器的使用步骤:
            1 使用itrator()获取迭代器的实现类对象,使用iterator接口接收(多态)
            2 使用iterator中的方法hasNext判断有没有下一个元素
            3 使用iteratir中的hasNext取出集合下一个元素
        */
        Collection<String> collection = new ArrayList<>();
        collection.add("a");
        collection.add("b");
        collection.add("c");
        collection.add("d");

        // 多态接口  实现类对象
        Iterator<String> it = collection.iterator();
        while (it.hasNext()) {
            String e = it.next();
            System.out.println(e);
        }
        System.out.println("-----------------------");

        for (Iterator<String> it2 = collection.iterator(); it2.hasNext();) {
            String e = it2.next();
            System.out.println(e);
        }
    }
3.11.3 增强for循环
    public static void demo3(){
        // 增强for循环:底层使用的也是迭代器,使用for循环的格式,简化了迭代器的书写
        // Collection<E> extends Iterable <E>: 所有的单列集合都可以使用增强for
        // public interface Iterable<T> 实现这个接口允许对象成为foreach语句的目标

        // 增强for循环,用来遍历集合和数组
        int[] arr = {1,2,3,4,5};
        for (int i:arr) {
            System.out.println(i);
        }

4 继承、多态

4.1 父类和子类

  • 继承是多态的前提,如果没有继承就没有多态。
  • 区分方法重写(覆盖)跟方法重载:覆盖是方法名称一样,但是参数不一样。
  • 子类方法的返回值一定要小于等于父类方法的返回值范围。
  • 子类方法的权限要大于等于父类方法的权限修饰符。(public>protected>default>protected)
  • java是单继承的,但是可以多级继承
  • 不能new一个抽象类,子类必须重写父类中的抽象方法(除非子类也是抽象类)

4.2 接口

接口是多个类的公共规范
接口是一种引用数据类型,最重要的内容是:抽象方法

如何定义接口
public interface 接口名称 {
    // 接口内容
}
备注:换成了关键字interface之后,编译生成的字节码文件还是: .java --> .class

如果是java 7,那么接口中可以包含的内容有:
    1 常量 [public] [static] [final] 数据类型 常量名称 = 数值;
    2 抽象方法 [public] [abstract] 返回值类型 方法名称(参数列表);
        要实现类必须覆盖重写接口所有的抽象方法,除非实现类是抽象类
如果是java 8,那么可以额外包含:
    3 默认方法 [public] default 返回值类型 方法名称(参数列表){方法体};
        默认方法也可以被覆盖重写
    4 静态方法 [public] static 返回值类型 方法名称(参数列表){方法体};
        只能通过接口名称被调用,不能通过实现类对象调用接口静态方法
如果是java9,那么可以额外包含:
    5 私有方法:
        普通私有方法:解决多个默认方法之间的重复代码问题 private
        静态私有方法:解决多个静态方法之间的重复代码问题 private static

接口使用步骤:
    1 接口不能直接使用,必须有一个“实现类”来实现该接口
    public class 实现类名称 implements 接口名称 { //方法体 }
    2 接口的实现类必须覆盖重写(实现)接口中所有的抽象方法:去掉abstract关键字,加上方法体大括号
    3 创建实现类的对象,然后使用。

注意事项:
    1 接口没有静态代码块或者构造方法
    2 一个类的直接父类是唯一的,但是可以有同时实现多个接口 public class xxx implements xx, xx
    3 如果实现类所实现的多个接口中有重名的方法,这时候不用覆盖重写多次,一次就可以
    4 如果没有覆盖重写接口中的所有方法,那么这个类必须是一个抽象类
    5 如果实现类的多个接口中,存在重名的默认方法,那么一定要覆盖重写
    6 一个类中如果直接父类的方法跟接口方法重名冲突,那么父类的优先级更高 继承优先于接口


接口跟类之间的差异
    1 类跟类之间是单继承的,直接父类只有一个
    2 类跟接口之间是多实现的,一个类可以实现许多接口
    3 接口跟接口之间是多继承的:public interface xx extends xx, xx
        如果多个父接口的抽象方法重复,没关系
        如果多个父接口的默认方法重复,需要重写

4.3 权限修饰符

java中有四种权限修饰符
        public > protected > default > private
同一个类    yes       yes         yes         yes
同一个包    yes       yes          yes        no
不同包子类  yes      yes           no         no
不同包非子类 yes      no          no           no4


内部类:如果一个事物内部包含另一个事物。比如:身体和心脏,汽车和发动机
分类:
    成员内部类、局部内部类(包含匿名内部类)

注意:
    内部类用外部类,随意访问,外部类用内部类,需要内部类对象
    如果接口的实现类或者父类的子类只需要使用唯一的一次,那么可以省略掉定义,而改为使用匿名内部类。
        如果希望多次创建对象,并且类的内容一样的话,那么必须使用单独定义的实现类
        recap:匿名对象是在调用方法的时候使用,只能调用唯一的一次。如果希望多次调用,必须给对象起个名字

如何使用内部类:
    1 间接方式:在外部类的方法中,使用内部类,然后main只是调用外部类的方法
    2 直接方式:外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
4.4 静态代码块

静态代码块:第一次运行本类时,静态代码块运行唯一的一次,用来一次性对静态成员变量赋值。

public class Person {
	static {
		int i = 0;
	}
}

5 包装类

基本数据类型使用起来十分方便,但是没有对应的方法操作这些基本类型数据。
可以使用一个类,把基本类型的数据装起来,在类中定义一些方法,这个类叫做包装类。
我们可以使用类中的方法来操作这些基本类型的数据。

基本类型对应的包装类(位于java.lang包中)
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

基本类型与对应的包装类对象之间,来回转换的过程称为”装箱“与”拆箱“:

  • 装箱:从基本类型转换为对应的包装类对象。

  • 拆箱:从包装类对象转换为对应的基本类型。

    public static void demo7() {
        // 装箱
        Integer int1 = new Integer(1);// 方法上有横线说明方法过时了

        Integer in2 = Integer.valueOf(1);

        // 拆箱
        int i = int1.intValue();

        // 自动拆箱
        Integer in = 1;
        in += 2;
        // 自动装箱
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1); // 其实是list.add(new Integer(1));
        // 自动拆箱
        list.get(0);// 其实是list.get(0).intValue();

        // 基本类型->字符串
        String combine = in + "";

        // 字符串 -> 基本类型
        int i_parse = Integer.parseInt("20");
    }

6 泛型

6.1 泛型概述

泛型是一种未知的数据类型,当我们不知道存什么数据类型的时候可以使用泛型。
也可以看成一个变量,用来接收数据类型。
ArrayList集合在定义的时候,不知道集合中都有存储什么类型的数据,所以使用泛型。
E e: Element 元素
T t: Type类型

在前面学习集合时,我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对象,并且进行相应的操作,这时必须采用类型转换。

public static void demo4() {
        // 当我们创建集合对象,不使用泛型
        // 好处是可以存储任意类型的数据
        // 坏处是不安全可能引发异常
        ArrayList list = new ArrayList<>();
        list.add(1);
        list.add("aa");

        // 使用迭代器遍历
        Iterator it = list.iterator();
        while (it.hasNext()) {
            // 取出的元素也是object类型
            Object obj = it.next();
            System.out.println(obj);
            // 想要使用string特有的方法length但是不能使用
            // 多态
            // 需要向下转型
            // 会报错,说不能把int类型转化为string类型
            String s = (String) obj;
            System.out.println(s.length());
        }


        // 创建集合对象使用泛型
        // 好处是避免了类型转换的麻烦,存储的是什么类型,去除的就是什么类型;
        // 好处还有把运行期异常提升到了编译期
        // 坏处是泛型是什么类型,就只能存储什么类型的数据
        ArrayList<String> ls = new ArrayList<>();
        // 报错 list.add(1);
        ls.add("bbbb");
        // 直接报错 ls.add(1);
        // 使用迭代器遍历
        Iterator it2 = ls.iterator();
        while (it.hasNext()) {
            Object obj = it2.next();
            System.out.println(obj);
            // 想要使用string特有的方法length但是不能使用
            // 多态
            // 需要向下转型
            String s = (String) obj;
            System.out.println(s.length());
        }

6.2 含有泛型的类

public class RandomClass <E> {
    private E name;

    public E getName() {
        return name;
    }

    public void setName(E name) {
        this.name = name;
    }
}
    public static void demo1() {
        // 如果不写类型的话默认为object类型
        RandomClass ls = new RandomClass();
        ls.setName("只能是字符串");

        // 创建泛型对象
        RandomClass<Integer> gc = new RandomClass<>();
        gc.setName(1);
    }

6.3 含有泛型的方法

public class JustClass {
    public <M> void print1(M m) {
        System.out.println(m);
    }

    public static <S> void print2 (S s){
        System.out.println(s);
    }
}
    public  static  void demo2() {
        // 测试含有泛型的方法
        JustClass j = new JustClass();
        // 调用含有泛型的方法,传递什么类型就是什么类型
        j.print1(1);
        j.print1("aa");

        // 静态方法,不建议创建对象使用
        // 静态方法可以通过类名.方法名(参数)使用
        j.print2(1);
        JustClass.print2("ss");
    }

6.4 含有泛型的接口

public interface GeneticInterface <S> {
    public abstract void method(S s);
}
public class GenericInterfaceImpl implements GeneticInterface<String> {
    /*
    含有泛型的接口,使用方式
        1 定义接口的实现类,实现接口,指定接口的泛型.
        public interface Iterator<E> {
            E next();
        }
        Scanner类实现了Iterator接口,并指定了接口的泛型为String,所以重写的next方法泛型默认就是String
        public final class Scanner implements Iterator <String> }
            public String next() {}
        }
     */
    @Override
    public void method(String s) {
        System.out.println(s);
    }
}
public class GenericInterfaceImpl2<I> implements GeneticInterface <I> {
    @Override
    public void method(I o) {
        System.out.println(o);
    }
}
    public static void demo3() {
        GenericInterfaceImpl gi1 = new GenericInterfaceImpl();
        gi1.method("字符串");

        GenericInterfaceImpl2<String> gi2 = new GenericInterfaceImpl2();
        gi1.method("字符串");
    }

6.5 泛型通配符

    public static void demo4() {
        ArrayList<Integer> ls1 = new ArrayList<>();
        ls1.add(1);
        ls1.add(2);

        ArrayList<String> ls2 = new ArrayList<>();
        ls2.add("aa");
        ls2.add("bb");

        printArray(ls1);
        printArray(ls2);

        // 泛型通配符
        ArrayList<?> ls3 = new ArrayList<?>();
    }

    public static void printArray(ArrayList<?> list) {
        // 定义一个方法,可以遍历所有类型的ArrayList集合

        // 如果输入参数是ArrayList<Integer> 或者ArrayList<String> list
        // 那么不能适用于其他的类型

        //如果输入参数是ArrayList<Object> list
        // 那么两个都会报错,因为泛型没有继承概念的
        Iterator<?> it = list.iterator();
        while (it.hasNext()) {
            // it.next()取出的元素是Object
            Object obj = it.next();
        }
    }

泛型的上限和下限
之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限下限

泛型的上限

  • 格式类型名称 <? extends 类 > 对象名称
  • 意义只能接收该类型及其子类

泛型的下限

  • 格式类型名称 <? super 类 > 对象名称
  • 意义只能接收该类型及其父类型
    public static void getElement1(Collection<? extends Number> coll) {
        // 必须是Number类或者子类
    }
    public static void getElement2(Collection<? super Number> coll) {
        // 必须是Number类或者父类
    }
    public static void demo5() {
        Collection<Integer> int_coll = new ArrayList<Integer>();
        Collection<String> str_col = new ArrayList<String>();
        Collection<Number> num_coll = new ArrayList<Number>();
        Collection<Object> obj_coll = new ArrayList<Object>();

        getElement1(int_coll);
        getElement1(str_col);//报错
        getElement1(num_coll);
        getElement1(obj_coll);//报错

        getElement2(int_coll);//报错
        getElement2(str_col);//报错
        getElement2(num_coll);
        getElement2(obj_coll);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值