Java小白的基础总结(一)

用了java从入门到精通和Java核心技术的基础篇,准备第一本为主,第二本为辅,实践加上理论的去学习。

Java之输出字符串

Java的基本概念

java是用类组成的。每个类都要有一个主函数。含有main方法的类称为Java主类。

变量的声明

全局变量

这个是声明在主函数外面的

成员变量

这个是申明在主函数里面的。

里面的变量定义可以边定义边操作:long s1 = s2+s3+s4;

常量的声明

final <类型> <变量名>=<值>

在Java中,变量名和变量名所对应的数据是存放在不同的地方的。

一般申明在主函数外部,这个可以参考C语言。

输出值

System.out.println(s1);

这个就是输出的语法。这里有个问题,能不能一次性输出一大堆。

打印的时候可以类似于python里面,用+这个符号,这个跟C语言有点不大一样。

数据类型

  1. 整数类型:
    1. 整型
      1. byte
      2. short
      3. int
      4. long
    2. 浮点型
      1. float是能表示32位的数值,需要后面加上f
      2. double是能表示64位的数值,需要后面加上d

注意,整数类型不能以0开头,八进制以0开头,十六进制以0X开头。

整数类型的名称是和他们能表示的进制位有关系,byte是八位,依次成倍数增长。可以表示从负数到正数。

  1. 字符型
    1. 一个字符占两个字节的空间
    2. java里面和C以及C++是一样的,可以将字符串看作整型,而且还是无符号数。
    3. 具体申明方法char x='<字符>'这个就是单个字符的申明。多个字符用双引号。
    4. 转义字符,这个和python一样,知识继承就好了。
  2. 布尔型
    1. 小写

数据类型转换

package cd.idcast.num;

public class test {
    public static void main(String[] args) {
        int s1=15;
        System.out.println((char)s1)

    }
}

就是将目标类型用圆括号括起来,然后跟上变量。

  1. Java中是区分双引号和单引号的

问题

目前没搞懂,为什么main里面要有一个String[] args

以及stactic是什么意思?是全局变量的意思吗?

变量

变量的声明

常量

final <类型> <变量>

变量的有效范围

成员变量

在整个类中都适用的变量叫做成员变量。成员变量中包含两种变量:

  1. 静态变量
    1. static <数据类型> <变量>
    2. 静态变量可以在整个类中被访问,同时,还可以用<类名>.<静态变量>来访问。
    3. 由于静态全局变量的作用域限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其他源文件中引起错误。
      static全局变量与普通的全局变量的区别是static全局变量只初始化一次,防止在其他文件单元被引用。
  2. 实例变量

局部变量

只在当前的类里面有效,一旦跳出了这个类,就无效了。

运算符

这里面最重要的就是自增和自减,这个参考C语言。

逻辑运算符

这个和其他语言是一样的,参考python和c语言。

位运算

这个就是:

  1. << 左移
  2. >>右移,并且,最高位和之前的最高位有关系。在书pdf93,有需求了再看。

三元运算符

这个比较的关键,因为,这个可以减少空间复杂度。

boolean b = 20<45?true:false

上面这个例子只是一部分,当然我们可以定义其他类型来完成三元运算。

即满足条件就是true的部分,否则就是false的部分。

数据类型转换

隐式转换

从低级类型向高级类型的转换,这个是由系统自动执行的,不需要我们人为的来完成。

这里就有一个转换表:

显式类型转换

当我们把高精度的数据赋给低精度的数据的时候,我们就要用显示类型转换了。这个和C语言是不一样的。

这个和上面那个刚好是相反的。

(<类型>)<变量>

注释

这个和C语言一样

文档注释

这个就是/** */中间的被视为文档注释。

复合语句

这个就是在函数总又加了一对大括号,在大括号里面会新开辟一个命名空间,一旦这里面的变量到了外面使用,就会报错。

流程控制

这里面就是if语句了,这个是语言中非常重要的环节之一。这个和C语言很像。

switch也是一样的。

循环语句

for语句和循环语句,以及do while语句,这个和C语言是一样的,我们沿用就行了。

其中有一个foreach语句,这个是for语句的精髓。

int arr[]={1,8,9}
for(int x:arr){
    System.Out.printIn(x)
}

这个变量的定义要和数组中的保持一致。

标签语法

java中有标签语法,就是说内层循环可以直接结束外层循环,当指定标签的时候。

Loop:for(int i = 0;i<=10;i++){
    for(int j = 0;j<=5;j++){
        if(j==3){
            break Loop;
        }
    }
}

类似于这样,就可以结束外层的循环嵌套。

String类

这个我看上去和python有点像,又和C语言有点像。

这个是基于序列之上的。

char a[]={'g','o','o','d'};
String s = new String(a,<>,<>);//第一个参数是起始坐标,第二个参数是取的的个数。
    
//或者直接这么定义
String s = new String("student");

String是字符串的意思,然而,char是字符的意思。

或者直接定义String <变量>;

字符串的连接

直接用加号。

获取字符串信息

str.length();str指的就是字符串。

字符串查找

indexOf;查找字符串第一次出现的位置

lastIndexOf;查找字符串最后出现的位置

str.charAt(<坐标>);

字符串操作

substring 截取字符串

str.substring(int x);这个就是从指定的字符串索引开始往后截取。当然,也可以定义结束的位置。取头不取尾。

去除空格 trim

str.trim();这个因为是类写的,所以有多态。

字符串的替换

str.replace(,);

查找字符串最开始的位置和最后的位置

str.startsWith(<期望字符>);

str.endsWith(<期望字符>);

这两个方法返回的都是布尔值。

判断字符串是否相等

str.equals();

下面这个方法是忽略大小写。

str.equalsIngnoreCase();

判断两个字符的前后位置

str.CampareTo(<另一个字符>)

转换大小写

str.toLowerCase()

str.toUpperCase()

字符串分割

这个比较的管用,在处理字符串方面用的很多,至少爬虫这方面我是深有体会:

str.split(<要分割的字符串>)同时,加个逗号后面跟整型,可以标识分割几次。

字符格式化

这个等用到的时候再说,练起来没有多大的意义。

但是常规个字符格式化是要记住一些的。这个就跟C和python中的格式化输出一个道理。

字符串生成器

这个就跟内存有关系了,在python中我们避免一直用str += str的原因就是,这样会不停的创建出一个新的内存,时间复杂度很高。Java中有类似的机制避免这种情况。

Java中提供了一种字符串生成器来减少系统的开销。

这个我觉得它应该是使用了一种花销平坦的机制,和python的列表是很像的。

StringBuilder <变量> = new StringBuilder("");

不过,这里建议使用变量名是builder,这个可能是一个规定。

输出字符串

str.toString();

插入字符串

str.insert(int start,int end);

这样就可以在字符串中插入

删除字符串

str.delete(int start ,int end);

数组

数组有一维的和二维的等等。在Java中,我们每一个都是一个对象,所以我们在申明了数组的变量之后,还要new一个对象,这样的话,系统才会给它分配内存,不然这个变量名就是无效的,下面举一个例子,我们来创建一个一维的int类型的数组。

int x[];
x = new int[6];

现在才算真正的创建了一个一维的数据,长度是6。

当然,上面的语法是可以合起来的:int <变量名>[]=new int[6]

初始化方式

int <>[]={<元素>,...,<元素>};

int <>[]=new int[]{<元素>,...,<元素>};

这个也是可以的。

数组的访问

数组的访问跟python的一摸一样,就是用下标的方式进行访问,这里我觉得可以用none乘以任意值来初始化数据,当然,这个是我的猜想。

二维数组

这个初始化和一维是一样的,只不过,我们还要不停的为两个维度的数组分配内存

int a[][]=new int[2][4];
a[0]=new int[5];
a[1]=new int[2];

二维数组的初始化

int a[][]={{<元素>},...,{<元素>}}这个初始化和C语言是一样的。

二维数组的遍历时一样的

这个参考当时的C语言。

这里采用的是拆解遍历法

for(int xi[]:xx){
            int j=0;
            for(int e:xi){
                if (i==1&&j==2){
                    System.out.println(e);
                    break;
                }else {
                    System.out.println(e);
                    j++;
                }
            }
            i++;
        }

里面用的就是java中的foreach语句。

第一个循环是不停的把二维变成一维;第二个循环就是把一维变成一个个的元素。这个循环就是在不停的把数据降维度输出。每次都下一个维度。

我们可以用print这个函数来让它在同一行输出。

填充数组

我们可以使用fill方法来对数据进行填充。举个例子来讲:

<>.fill(<类型> <数组>[],<填充的东西>)这个只是一个例子,这个fill可以用一个值填充整个数据。

package cd.idcast;

import java.lang.reflect.Array;
import java.util.Arrays;

public class 数组的填充 {
    public static void main(String[] args) {
        int arry[]=new int[8];
        Arrays.fill(arry,5);
        for(int i=0;i<arry.length;i++){
            System.out.print(arry[i]+", ");
        }
    }
}

我们发现,填充这个方法,用的是Arrays对象。当然,填充也是可以指定范围的,这个可以类似于替换数组中的元素。

Arrays.fill(<数组变量>,<起始位置>,<结束位置>)这个就是指定位置的填充,也可以理解为替换。

数组排序

Arrays.sort(<对象>)

数组的复制

这个就要用到另一个对象了。

copyOf(<数组对象>,<复制的长度>)

copyOfRange()这个就是指定数组的指定复制范围。

binarySearch(Object[] a,int fromIndex,int toIndex,Object key);

/*其中,a 表示要进行查找的数组,fromIndex 指定范围的开始处索引(包含开始处),toIndex 指定范围的结束处索引(不包含结束处),key 表示要搜索的元素。

在使用 binarySearch() 方法的上述重载形式时,也需要对数组进行排序,以便获取准确的索引值。如果要查找的元素 key 在指定的范围内,则返回搜索键的索引;否则返回 -1 或 “-插入点”。插入点指要将键插入数组的位置,即范围内第一个大于此键的元素索引。*/

几大经典的排序方法

冒泡排序

思想就是,不停的从头开始对比,但是交换的次数是越来越少的。因为每次交换都能保证最大的一定在最下面。当然,这个是升序,我们当然可以降序排列

package cd.idcast.num;

public class 冒泡排序 {
    public static void main(String[] args) {
        int[] array = {63,5,24,1,100,3};

        //冒泡排序

    }
    public void sort(int[] array){
        for(int i = 1;i<array.length;i++){
            for(int j=0;j<array.length-i;j++){
                if(array[j]>array[j+1]){
                    int temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                }
            }
        showArray(array);
        }
    }
    public void showArray(int[] array){
        for(int i:array){
            System.out.print(">"+i);

        }
        System.out.println();
    }
}

选择排序

这个就是从最后一个位置开始,每次选出最大的一个,然后和位置交换,这个位置呢,就是array[array.length-i],这个位置每循环一次就会减一。为什么说最开头的这个不换了呢,因为当后面位置的数全是最大的时候,那么第一个数一定是最小的。

package cd.idcast.num;

public class Select_order {
    public static void main(String[] args) {
        int[] array = {96,52,18,2,1,0};
        Select_order sorter = new Select_order();
        sorter.sort(array);
    }
    public void sort(int[] array){
        int index;
        for(int i=1;i<array.length;i++){
            index = 0;
            for(int j=1;j<=array.length-i;j++){
                if(array[j]>array[index]){
                    index = j;
                }
                int temp;
                temp = array[array.length-i];
                array[array.length-i] = array[index];
                array[index] = temp;
            }
            pprint(array);
        }
    }
    public void pprint(int[] array){
        for(int x:array){
            System.out.print(x+" ");
        }
        System.out.println();
    }
}

类是封装对象的载体,我们不能把单一的事物称为类。

现在还没有办法理解这个public的具体含义,以及public和private是怎么协同工作的。

怎么实现一个类

我们先要从设计一个类开始,然后再着手的去实现类里面的方法。

初始化一个类

我们通常用类名来申明一个对象,同时,要配合上new来让该对象能够不停的被访问:Book one_editor = new Book()

我们引用的类实例都是外部的,是一个具体的,而且,每个不同的变量指向不同的类实例。

什么是UML

我们都会翻译,UML是统一建模语言,是一种可视化的面向对象建模语言,是一种用来对真实世界物理进行建模的标准标记,用图形方式表现典型的面向对象系统的整个结构。它的作用域不局限于支持面向对象的分析与设计,还支持从需求分析开始的软件开发的全过程。

https://blog.csdn.net/xdd19910505/article/details/18698825/

上面的网站中有详细的说明。

成员方法

不管前面的权限修饰符是public或者是private,这个都是成员方法。成员方法的声明格式是:权限修饰符 返回值类型 方法名(参数类型 参数名){//方法体}

权限修饰符

这个我觉得如果用python中的类来理解会好一点。

在Java中,权限修饰符有三个:

  1. public
  2. private
  3. protected
  4. default修饰的成员:该成员对同一个包中的类都可见。

如果是public,那么这个就属于公共的,也就是说任意地方都能访问到。

如果是private的话,这个就跟python中类里面,用下划线定义的变量或者是函数,是私有的,它存在在本类当中,但是不能够被外界访问。

如果是protected的话,那就是只有其他包不能访问,同包里面,或者同一个文件里面都是可以访问到的。

在类中,如果学过python,那么我们将this映射成python中的self,也就是实例对象本身。我们将private映射成用“_”开头的私有属性或者函数,也就是只有内部才能调用和访问,子类以及其它是访问不了的。

如果一个类前面没有任何的权限修饰符的话,那么我们将这个类默认成protected类型的类,也就是只有本包和子类可以访问该类。本包外的就不行。

在类中的方法如果不定义权限修饰符,那么会默认是public,因为类的权限设定会影响里面的权限设定。

局部变量的使用

这个就跟python中的命名空间是一个概念,在该命名空间中,变量的名称是不能够重复的,但是在不同的作用域里面,变量的名称确实是可以重复的。这个就跟在两个for循环里面用同样的变量i是一个道理。

局部变量在调用结束后就会被销毁。

this

这个就相当于python中的self,而且,这个可以直接作为对象返回。

类的构造方法

这个是在项目中创建public <类名称>(){//函数体}这个可以没有返回值,同时,如果没有参数的话,我们可以在函数体中的第一句加上this("<参数>"),但也只能是第一句。

静态变量,常量和方法

这个就是可以让别的类也访问的常量类型,用于节省内存。

调用方法

用类名加上点来调用方法。

初始化常量

static{
    
}

我觉得这个跟python中的init就很像。

对象

构造方法

这个就是前面的权限修饰符。

package cls_test;

public class lei_tes_2 {
    public lei_tes_2(){
        System.out.println("Hello");
    }

    public static void main(String[] args) {
        new lei_tes_2();
    }
}

在这里面,我们发现,在主类里面创建了一个lei_tes_2,它的构造方法和它是同名的。

构造方法就是相当于初始化方法,这个会在主函数中一旦遇到了new之后自动调用,构造函数的方法就是在主函数外面创建一个同名的类名,里面定义其它代码。

“==”和equals的区别

前面是比较地址是否相等,后者是字符串的方法,比较两个字符串是否相等。

对象的销毁

将对象赋值为null或者用finalize()方法都是可以的。同时我们可以用System.gc()来强制回收对象。

编写类的方法

每个类中,只有一个main方法,同时,有很多的不同类,这些类最终会在main方法中被调用。要想创建一个完整的程序,就要将他们结合到一块。

包装类

有些情况下,我们需要将数字作为对象进行处理,所以这个时候,我们就需要包装类了。

Integer

在这个类里面就有很多的方法:

其中有很多转换的方法在pdf189页,这里举一个例子:

package Pack_class_test;

public class Integ {
    public static String[] num = {"45","56","343"};

    public static void main(String[] args) {
        int sum = 0;
        for (String s : num) {
            int x = Integer.parseInt(s);
            sum += x;
        }
        System.out.println(sum);
    }
}

这个就是将数字当作对象来处理了。

Boolean

这个就是,如果我创建了一个Boolean的对象,那么如果对象不是true(忽略大小写),那么返回false。

其他方法和上面是类似的。

package Pack_class_test;

public class Integ {
    public static String[] num = {"45","56","343"};

    public static void main(String[] args) {
        int sum = 0;
        for (String s : num) {
            int x = Integer.parseInt(s);
            sum += x;
        }
        System.out.println(sum);
        Boolean bool = Boolean.valueOf("type");
        System.out.println(bool);

    }
}

其他的方法是类似的,我们只需要查书就行了。

数字处理中的格式化(DecimalFormat)

这个相当于python中的format,非常的有用,尤其是在处理一些别的方面的时候。

里面符号的具体意思和用法

package Pack_class_test;

import java.text.DecimalFormat;

public class NumFormat {
    static public void FormatNum(String pattern,double num){
        DecimalFormat myformat = new DecimalFormat(pattern);
        String nums = myformat.format(num);
        System.out.println(nums);

    }

    public static void main(String[] args) {
        FormatNum("000.00kg",185.6989);
        FormatNum("#####.##",15.3);
        FormatNum("#.###%",0.236);
    }
}

符号解释

  1. #就是有就填上,没有就空着
  2. 0就表示,有就填上,没有就用0来填充
  3. %就表示用百分位来表示数字

其他的书中也有介绍,用到的时候再具体的查书。在PDF199页这里。

给数字设置分组

<对象>.setGroupingSize(<整型>)

Sting <变量> = <对象>.format(<整型>)

Math这块

用到了查书。PDF203页。

random这块

这个根据以往用python的经验来讲,还是比较重要的。

这个模块呢,只能产生0-1之间的数,所以我们用这个的时候,需要乘上相应的值来达到任意区间随机数的目的。

package Pack_class_test;

import java.text.DecimalFormat;

public class NumFormat {
    static public void FormatNum(String pattern,double num){
        DecimalFormat myformat = new DecimalFormat(pattern);
        String nums = myformat.format(num);
        System.out.println(nums);

    }
    static public void RandomNum(double num1,double num2){
        int s = (int)(num1)+(int)(Math.random()*num2);
        System.out.println(s);

    }
    public static void main(String[] args) {
        FormatNum("000.00kg",185.6989);
        FormatNum("#####.##",15.3);
        FormatNum("#.###%",0.236);
        RandomNum(12.6,89.898989);
    }
}

我们也可以用它来生成随机的字符,这个和上面的方法是一致的,只不过,我们用的是char类型。

创建一个random实例

Random r = Random();

后面就可以调用里面的方法了,这个书中都有列出,这里略过,要用的时候查文档就行。书PDF208页。

大数字运算

BigInterger

BigInterger可以表示任意大小的整型。

里面的算术运算是以对象的形式进行的,我们来举几个例子:

package Pack_class_test;

import java.math.BigInteger;

public class bigNum {
    public static void main(String[] args) {
        BigInteger bigs = new BigInteger("45");
        System.out.println(bigs.add(new BigInteger("69")));
        
    }
}

其他的和这个类似。

BigDecimal(大型小数的数据)

在这个类中,不同的传参转换的结果是一样的,我们可以传double类型,也可以传string类型。

package Pack_class_test;

import java.math.BigDecimal;
import java.math.BigInteger;

public class bigNum {
    public BigDecimal add(double var1,double var2){
        BigDecimal d1 = new BigDecimal(Double.toString(var1));
        BigDecimal d2 = new BigDecimal(Double.toString(var2));
        return d1.add(d2);
    }

    public static void main(String[] args) {
//        System.out.println(bigs.add(new BigInteger("69")));
//        BigDecimal dd = new BigDecimal("15.26541");

//        System.out.println(dd.add(new BigDecimal("8861.165489461")));
//        System.out.println(BigCal);
        bigNum b = new bigNum();
        System.out.println(b.add(1254.156,896.3486416));

    }
}

核心技术

接口,继承,多态

子类中可以重构父类的方法和参数,但是除了权限修饰符为private的除外,同时,重写时不能降低权限的修饰范围,也就是提升是可以的。

Java中,用extends来表示继承类

class Text2 extends Text1

这里我们发现,是前面的继承了后面的

同时我们用super();来调用父类方法。

super();//这个是调用父类的构造方法。
super.<方法>();

使用父类方法的时候要注意,如果定义的是static类型的函数,那么不用加super,直接调用即可。

实例化的时候,父类先实例化,然后再是子类。

Object类

这个是一个基类,我们创建的Java类都默认继承了它。

toString()方法

这个方法是类自动继承的,我们通常重写他,它会在类被实例化之后自动调用。同时,它可以让类对象作为一个字符串输出。

equals()方法

在实例化的过程中,equals是默认"==",所以我们要重写它。

对象类型的转换

package Pack_class_test;

class Fulei{
    public static void draw(Fulei p) {
        System.out.println("劳资是你爸爸");
    }
}
public class S_B extends Fulei{
    public static void main(String[] args) {
        S_B p = new S_B();
        draw(p);
    }
}

也就是子集向全集转化的时候,就可以实现向上转型。

static类型的函数,只初始化一次,所以继承后可以直接调用。

向下转型

这个时候必须使用显示类型转换,不然就会报错。

<类名> <变量> = (类名)<变量>

判断对象的类型

这样配合上面的转型,可以让程序变得更加的健壮。

package Pack_class_test;
class QQQ{
    public static void draw(QQQ q) {
        System.out.println("来了老弟");
    }
}
class Square extends QQQ{
    public static void gg(){
        int i=0;
        System.out.println("我是方");
    }
}
class  Anything{

}
public class Judge_ex extends QQQ{
    public static void main(String[] args) {
        QQQ p = new QQQ();
        if(p instanceof Judge_ex){
            System.out.println("没错,现在我要开始转换了");
            Judge_ex q = (Judge_ex)p;
        }
        if(p instanceof Square){
            System.out.println("是方的");
            Square q = (Square)p;
            System.out.println("转型完成");
        }
    }
}

方法重载

一个类里面,Java允许有相同名字的不同函数,只要这些函数的类型,传参等等不一样,JAVA就能识别他们,这样方便我们管理代码。

同时,里面有一个任意传参的语法:

任意传参

<类型>...<变量>这个就相当于数组了。

package Pack_class_test;

public class ReloadFuc {
    public static double add(double...num){
        double sum=0;
        for(double x:num){
            sum +=x;
        }
        return sum;
    }
    public static int add(int...num){
        int sum = 0;
        for (int x:num){
            sum +=x;
        }
        return sum;
    }

    public static void main(String[] args) {
        System.out.println(add(1,5,6,8));
        System.out.println(add(1.2,5,8.6,45));
    }
}

多态问题

利用了向上转型的特性,比如说绘制四边形,我们定义一个大类,然后让里面的子类同变成参数传递进draw这个大类里面,然后通过不同的限制来处理不同的四边形绘制,这个大概就是多态的思想。

package Pack_class_test;

public class Duotai {
    //四边形类
    private final Duotai[] qtest = new Duotai[6];
    private int nextindex = 0;
    public void draw(Duotai q){
        if(nextindex<qtest.length){
            qtest[nextindex]=q;
            System.out.println(nextindex);
            nextindex++;
        }
    }

    public static void main(String[] args) {
        Duotai q = new Duotai();
        q.draw(new Sq());
        q.draw(new Parallelogramgle());
    }
}

class Sq extends Duotai{
    public Sq(){
        System.out.println("我是正方形");
    }
}

class Parallelogramgle extends Duotai{
    public Parallelogramgle() {
        System.out.println("我是长方形");
    }

}

这里我们就可以看到,我们在主类方法里面,就实现了多态的运行。

接口

多态和接口的技术相结合,就能让代码变得更加的健壮。

在Java中,是不允许多重继承的,但是呢,如果调用接口就是可以的:

class <类名> implements <接口>,<>...<>{
    
}

接口之间也是可以继承的。这个继承方法和类是一样的。

interface <> extends <>{}

你可能感兴趣的:(java)