java学习小计(基础篇)


八大数据类型

整数类型

  • int
  • long //声明变量后加L 例如 long num=8545L
  • byte
  • short

浮点类型

  • float //声明变量后需要加F 例如:float 3.1F;
  • double

字符

  • char //char中只能有一个字符 例如 char name =’中’ ; √ char name= ‘中国’; ×

布尔类型

  • boolean /只有 Ture和False两种结果

整数扩展

进制 : 二进制 八进制0 十进制 十六进制 0x

int i=10;//输出10
int i2=010//输出8  八进制 满八进一
int i3=0x10 //输出 16  十六进制   0~9  A~F  满十六进一 

浮点扩展

最好避免使用浮点数进行比较!!

字符扩展

所有字符本质是数字!

转义字符 ==/t==也就是空格

==/n== 换行

包通俗来说就是一个文件夹,为了防止文件名重复冲突而提出的一个概念

为了更好的组织类,java提供了包机制,用于区分类名的命名空间。

包语句的语法格式为:

package pkg1[.pkg2[.pkg3…]];

为了能够使用某一包的成员,我们需要在java程序中明确导入该包。使用“import”语句可完成此功能

import package1[.package2…].(classname|*);

Java流程控制

Scanner对象

实现程序和人的交互

Scanner s = new Scanner(System.in);

通过Scanner类的next和nextLine方法获取输入的字符串,读取时使用hasNext和haxNextLine判断时候还有输入的数据

next()

一定要读取到有效字符后才可以结束输入

对输入有效字符之前遇到空白,next()方法会自动去除掉

只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符

next()不能得到带有空格的字符串

nextLine()

以Enter为结束符,也就是说nextLine()方法返回的是输入空格之前的所有字符

可以获得空白

顺序结构

java的基本结构,程序一条一条执行

选择结构

if语句
单选择结构语句
if(布尔表达式){
    //如果布尔表达式为true将执行语句
}
2.双选择结构
if(布尔表达式){
    //如果布尔表达式为true将执行语句
}else{
    //如果布尔表达式为false将执行语句
}
3.多选择结构
if(布尔表达式1){
    //如果布尔表达式1为true将执行语句    
}else if(布尔表达式2){
    //如果布尔表达式2为true将执行语句
}else if(布尔表达式3){
    //如果布尔表达式3为true将执行语句
}else if(布尔表达式4){
    //如果布尔表达式4为true将执行语句
}else{
    //如果以上布尔表达式都不为true将执行语句
}
switch语句
switch(expression){
    case value :
        //语句
        break;//可选
    case value :
        //语句
        break;//可选
    case value :
        //语句
        break;//可选
        //可以有任意数量的case语句
    default ://可选
        //语句
        }

循环结构

while循环
public static void main(String[] args) {
    // 输出1~100
    int i = 0;
    while (i <= 99) {
        i++;
        System.out.println(i);
    }
}

只要布尔表达式为true,循环体会一直执行下去。

do…while循环

对于while语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。 Do…while循环和while循环相似,不同的是,do…while循环至少会执行一次。

public static void main(String[] args) {
    int i = 0;
    int sum = 0;
    do {
        i++;
        sum+=i;
    }while (i<100);
    System.out.println(sum);
}

注意:布尔表达式在循环体的后面,所以语句块在检测布尔表达式之前已经执行了。如果布尔表达式的值为true,则语句块一直执行,直到布尔表达式的值为false。

For循环

虽然所有循环结构都可以用while或者do…while表示,但Java提供了另一种语言——for循环,使一些循环结构变得更加简单。 For循环执行的次数是在执行前就确定的。

public static void main(String[] args) {
    for (int a = 1; a <= 100; a++) {
        System.out.println(a);
    }
}

关于for循环有以下几点说明:

  • 最先执行初始化步骤。可以声明并初始化一个或多个循环控制变量,也可以是空语句。
  • 然后检查布尔表达式的值。如果为true,循环体被执行。如果为false,循环终止,开始执行循环体 后面的语句。
  • 执行一次循环后,更新循环控制变量。
  • 再次检测布尔表达式。循环执行上面的过程。

Java方法

概述

  • Java方法是语句的集合,他们在一起执行一个功能
    • 方法是解决一类问题的步骤的有序集合
    • 方法包含于类和对象中
    • 方法在程序中被创建,在其他地方被引用
  • 设计方法的原则:功能块,实现某个功能的语句块的集合,保持方法的原子性:一个方法只完成一个功能。

方法定义

方法必须先创建才可以使用,该过程称为方法定义

格式:public static void 方法名(){

方法体

}

public static void main(String[] args) {
    System.out.println(max(10, 50));
}

// 比大小
public static int max(int a, int b) {
    return a > b ? a : b;

}

方法的重载

重载就是在一个类中,有相同的函数名称,但形参不同的函数

  • 规则
    • 方法名称必须相同
    • 参数列表必须不同
    • 返回类型可以相同也可以不相同
    • 仅仅返回类型不同不足以成为方法的重载
  • 理论:
    • 方法名称相同时,编译器会根据调用方法的参数个数、类型等逐个匹配,已选择对应的方法,如果匹配失败,编译器会报错
// 方法的重载
public static void main(String[] args) {
    System.out.println(max(10, 50));
    System.out.println(max(10.1,23.11));
}

// 比大小
public static int max(int a, int b) {
    return a > b ? a : b;
}

// 名称必须相同,参数必须不同,返回类型随意
public static double max(double a, double b) {
    return a > b ? a : b;
}

可变参数(不定项参数)

  • 在方法的声明中,在指定参数类型后加一个省略号(…)
  • 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在他之前声明。
public static void main(String[] args) {
    Demo05 demo05 = new Demo05();
    demo05.test(1, 2, 3, 4, 5, 6);
}

public void test(int x, int... i) {
    System.out.println(i[0]);  // 本质是数组
    System.out.println(i[4]);
    System.out.println(i[5]);
}

递归

// 阶乘
public class Demo03 {
    public static void main(String[] args) {
        System.out.println(f(5)); //5! = 120
    }
    public static int f(int num){
        if (num==1){
            return 1;
        }else {
            return num*f(num-1);
        }
    }
}

数组

数组基础

public class Demo01 {
    public static void main(String[] args) {
        // 1. 声明一个数组
        int[] num1;
        int num2[];
        // 2. 创建一个数组
        num1 = new int[10];
        // 3. 赋值
        for (int i = 0; i < num1.length; i++) {
            num1[i] = i;
            System.out.println(num1[i]);
        }

        // 三种初始化方式
        // 静态初始化: 创建+赋值
        int[] a = {1,2,3};

        // 动态初始化:创建不赋值,默认值
        int[] b = new int[10];

    }
}

冒泡排序

当数据较大时,时间复杂度高,耗时

public class ArrayDemo01 {
    public static void main(String[] args) {
        int [] a ={1,20,30,5566,88745,12,3,65,95,4445};
        for (int i = 0; i < a.length-1; i++) {

            for (int j = 0; j < a.length-i-1 ; j++) {

                if (a[j+1] < a[j]) {
                    int tmp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = tmp;

                 }
                }

              }
        System.out.println(Arrays.toString(a));
            }

        }

稀疏数组

放一个稀疏数组的图片

image-20231017194033096

右侧即为稀疏数组

示例代码

package Practice.Practice.src.Array;

public class ArrayDemo02 {
    public static void main(String[] args) {
        //创建数组
        int[][] array1 = new int[11][11];
        array1[1][2] = 1;
        array1[2][3] = 2;
        System.out.println("原始棋盘");
        //遍历输出array1数组 \t是每个数字之间的空格
        for (int[] ints : array1) {
            for (int anInt : ints) {
                System.out.print(anInt + "\t");
            }
            //输出玩一行之后换行输出
            System.out.print("\n");

        }
        System.out.println("===========================================================");
        //21-25是为了先定义sum 来确定稀疏数组的行数
        int sum = 0;
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (array1[i][j] != 0) {
                     sum++;
                }
            }
        }
        System.out.println("有效值个数是" + sum);
        //定义稀疏数组首行
        int[][] array2 = new int[sum + 1][3];
        array2[0][0]=11;
        array2[0][1]=11;
        array2[0][2]=sum;


        //给稀疏数组进行赋值
        int count = 0;
        for (int i = 0; i < array1.length; i++) {
            for (int j = 0; j < array1[i].length; j++) {
                if (array1[i][j] != 0) {
                    count++;
                    array2[count][0]= i;
                    array2[count][1]= j;
                    array2[count][2]=array1[i][j];
                }
                }
            }
        //输出稀疏数组
        for (int i = 0; i < array2.length; i++) {
            System.out.println(array2[i][0]+"\t"
                +array2[i][1]+"\t"
                +array2[i][2]+"\t");
        }
        System.out.println("===========================================");
        System.out.println("还原的数组是:");
        //把稀疏数组的还原到普通数组
        int [][] array3 =new int[array2[0][0]][array2[0][1]];//定义普通数组的行列
        for (int i =1; i < array2.length; i++) {//i从1开始,因为稀疏数字第一行是定义,无实际数据储存
            array3[array2[i][0]][array2[i][1]]=array2[i][2];//赋值稀疏数组的内容
        }
        //遍历输出原始数组
        for (int[] ints : array3) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();

        }
        }
        }

面向对象(OOP)

终于到面向对象了

类、对象、方法的阐明

一开始学php反序列化的时候听课就把这三个整的云里雾里,十分混乱。

现在对这三个有了初步的自己的理解。

类中有对象,对象中有方法,对象中还有属性。

这样说可能也不太清楚,举个例子来说哈。

一个类就像是一个人(这里的人并不是指的是特定的某个人,而是泛指),而对象呢,就具体到个人了。比如说一个学生就是一个类,学生有自己的名字,学号,专业,宿舍号,所上的课程 …… 以上都是你的属性,也就是类的属性。而你的技能,比如你会说话,你会学习,你会敲代码,这些都是你的方法,也就是类的方法。这样说应该能 清楚点了吧

面向对象编程的本质:以类的方式组织代码,以对象的方式封装数据!

构造器

构造器也称构造方法,是在创建对象的时候必须要调用的,也就是new一个对象的时候一定会调用构造方法,有两个特点:

1.构造方法的名字必须和类名相同

2.必须没有返回类型,也不能写void

Alt + Insert快捷键生成构造器

public class Person {
    String name;
    int age;
    String gender;

    public Person() {
    }
}

6-7行即为构造器

构造器的作用:

1 .new的本质在于调用构造方法

  1. 初始化对象的值(就比如代码中,如果new了一个 Person类,则 name和gender的值就会被初始化为null,age被初始化为0)

注意:

​ 构造方法有无参构造和有参构造,默认不写是无参构造。

​ 但是,当你定义了有参构造之后,如果想要再使用无参构造,就必须要单独定义一个无参构造方法,如果没有单独定义无参构造,则无法使用无参构造。

没听懂没关系,来个例子就懂了。

Person.java


package Practice.Practice.src.OOP;

public class Person {
    String name;
    int age;
    String gender;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }
}

Application.java

public class Application {
    public static void main(String[] args) {
        Person person =new Person("aa");
        System.out.println(person.name);

    }
}

在person.java中的

12-13行即为一个有参构造

new的时候在()输入东西即调用有参构造(12-13),()内为空则调用无参构造(9-10),如果删掉(9-10),那么在new的时候,如果语句这样的话

  Person person =new Person();

则会报错。

特性

封装:

简单解释:(把数据封装起来,留一个接口调用)(比如:有一万块钱不想被被人看到,就放在箱子里边,为了方便我自己拿取,开了一个小口方便拿取)

我们程序设计的要求就是**”高内聚,低耦合”**。

高内聚:就是类的内部数据的操作细节自己完成,不允许外部干涉(就比如一个人的年龄,如果不让属性私有,让用户随意输入自己的年龄,那么用户可能会恶意输入年龄,比如-1岁,而我们设计程序的时候可以设置:当用户输入的年龄<0时,则提示用户:禁止恶搞!限制用户输入的年龄以及提示什么就是我们内部数据的操作细节,外人不能随意干涉。)

低耦合:仅暴露少量的方法给外部使用。

信息隐藏:我们封装的是我们类中的数据,通常,应禁止直接访问一个对象中数据的实际表示,而是通过操作接口来访问。这称为信息隐藏。

所以,我们会把属性私有化,用get和set来对数据进行操作和读取。

属性私有,get/set

快捷键 alt + insert 生成 get set

继承

(子类继承父类的属性)(儿子继承爸爸的遗产)

不理解?没关系,继续看!

还是一样,举个例子就明白:世界上有很多人,学生,老师,领导,CEO,帅哥,美女。他们都是人,都有姓名,性别,年龄…….这些属性是各种人都有的。所有我们可以定义一个”人”类(其中有姓名,性别,年龄…….各种属性),而“学生”,”老师“,”领导“,”CEO“,”帅哥“,”美女“类都可以继承”人”类的属性。(为什么要继承?因为懒,都是同样的东西为什么要写第二遍,一个extends继承就搞定了 )

Person类(Person.java)

public class Person {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

Student类(Student.java)

public class Student extends Person  {
}

Application(main方法)

public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        System.out.println();
        student.setName("小明");
        System.out.println("我是"+student.getName());
    }
}
/*输出结果:
我是小明。
*/

代码中就可以看到,我的student类中什么属性和方法都没有,但是我的main方法中却调用了setName和getName方法,这就是继承了Person父类中的方法和属性。

Surper与this

​ Super注意点:

  1. super调用父类的构造方法,必须在构造方法的第一行(默认是隐藏的无参构造)

  2. super必须只能出现在子类的方法或者构造方法中

  3. super和this不能同时调用构造方法(也就是你想调用父类或子类的有参构造的话,只能调用一个)

    代表的对象不同:

    ​ this:本身调用这个对象

    ​ super:代表父类对象的应用

    前提:

    ​ this:没有继承也可以使用

             super:只有在继承条件才可以使用
    

    构造方法:

             this();本类的构造
    

    ​ super(); 父类的构造

    重写

    重写都是方法的重写,和属性无关

    重写需要有继承关系,子类重写父类的方法!

    ​ 1.方法名必须相同

            2.参数列表必须相同
    

    ​ 3.修饰符:范围可以扩大但不可以缩小

    ​ 4.抛出的异常: 范围可以缩小,但是不能扩大 : ClassNotFoundException —> Exception(大)

    为什么需要重写?

    父类的功能,子类不一定需要或者不一定满足子类的需求!

    **Alt + Insert 重写的快捷键 ** 选择override

Java中只有单继承,没有多继承。(一个儿子只有一个爸爸,一个爸爸可以有多个儿子!)

多态

(有各种人,每个人的职业不同)

父类转向子类 向下转型 强制转换 部分方法丢失。

子类转向父类 向上转型

多态注意事项:

​ 1.多态是方法的多态,属性没有多态。

​ 2.父类和子类要有联系,否则会报异常(ClassCastException)

​ 3.存在条件:继承关系方法需要重写(子类继承父类的方法时候要重写方法)。父类引用指向子类对象! Father f1 = new son();

注意 :以下方法不可重写!

1. static静态方法

2.final常量修饰的方法

3.private 方法


下面看一个面经题目,关于多态的

public class Main {

    static class Animal{
        int weight = 10;

        public void print() {
            System.out.println("this Animal Print:" + weight);
        }

        public Animal() {
            print();
        }
    }

    static class Dog extends Animal {
        int weight = 20;

        @Override
        public void print() {
            System.out.println("this Dog Print:" + weight);
        }

        public Dog() {
            print();
        }
    }

    public static void main(String[] args) {
        Dog dog = new Dog();

        System.out.println

                ("a---------------");
        Animal dog222 = new Dog();
        Dog dog333 =  (Dog)dog222;

        System.out.println("a---------------");
        Dog dog444 = (Dog)new Animal();

    }
}


/*
输出结果:
this Dog Print:0
this Dog Print:20
a---------------
this Dog Print:0
this Dog Print:20
a---------------
this Animal Print:10
Exception in thread "main" java.lang.ClassCastException: Practice.Practice.src.OOP.Demo01.Main$Animal cannot be cast to Practice.Practice.src.OOP.Demo01.Main$Dog
    at Practice.Practice.src.OOP.Demo01.Main.main(Main.java:42)
*/

下面解释一下为什么。

首先来看第一部分

Dog dog = new Dog();

1.实例化子类dog的时候会先调用Dog子类的构造器,Dog子类继承Animal父类,接着会实例化父类,调用父类Animal的 构造器,执行print方法,实际上调用的是子类的Dog的方法print()打印 this Dog Print:0

接着又会调用Dog的构造方法,执行print() 输出 this Dog Print:20

​ a—————

  1. Animal dog222 = new Dog();` `Dog dog333 = (Dog)dog222;这两句话 第一句话是多态的引用,也就是向上转型。调用构造器,和1处一样的流程,而 第二句话是向下转型,不调用构造器。
  2. Dog dog444 = (Dog)new Animal();这一句话,会实例化Animal类,他没有父类,就会直接实例化当前的类,打印 this Animal Print:10 (Dog)表示向下转型,所以会报异常。那为什么2处的向下转型没有 报错呢?因为2处先实现了向上转型。

static关键字


public class A {
    {
        System.out.println("匿名代码");
    }
    static {
        System.out.println("静态代码");
    }

    public A() {
        System.out.println("构造方法");
    }
}

当new一个A类的时候,静态代码块最先执行,接着是匿名代码块,最后是构造方法。

并且: 静态代码块只执行一次!

abstract抽象类(了解)

缺点:单继承!(所以他是仅了解!)

1.抽象类不可以new,只能靠子类去实现它

2.抽象类中可以写普通的方法

3.抽象方法必须在抽象类中


文章作者: Rmy4x
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Rmy4x !
  目录