【Java】基础语法 | OOP用法 | 集合框架

因为后面可能要接触flink的东西,先快速入门java,像语法和oop特性 很多语言都是相通的~

零、IDEA环境配置

注意下面第3点,JavaVirtualMachines/jdk1.8.0_131.jdk文件中可能看不到这个.jdk的东西,可以通过/usr/libexec/java_home -V查看java的所有版本jdk对应的位置,会有这个.jdk的路径。

# mac中查看Java的JDK安装路径
/usr/libexec/java_home -V

# mac安装多个版本的jdk后环境变量的设置和切换
# 1. jenv来管理java的JDK
brew install jenv

# 2. 设置环境
echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(jenv init -)"' >> ~/.bash_profile
echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(jenv init -)"' >> ~/.zshrc

# 3. 添加jdk到jenv
jenv add /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home
jenv add /Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home
jenv add /Library/Java/JavaVirtualMachines/jdk-13.0.1.jdk/Contents/Home

# 4. 选择使用相应版本的jdk
jenv shell 1.8 // 这里如果不行就重启一下命令行工具,新打开一个terminal也可以

# 5. 切换成功,查看java版本
java -version

0.1 java项目跑起来

首先新建项目,不用创建模板,然后打开项目中的src文件夹:
在这里插入图片描述
右击src选择new->Package:
在这里插入图片描述
得到如图:
在这里插入图片描述
在刚才新建的com.java.demo中右键new,java class,名字随便写个hello_andy
在这里插入图片描述
在新建好的类中写一个main方法,和其他语言类似,java项目从这里开始执行:
在这里插入图片描述
最终的结果:
在这里插入图片描述

一、基础内容

1.1 java基本功

(1)Java 入门(基础概念与常识)

一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作。认识几个概念:

  • 对象:对象是类的一个实例,有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。
  • 类:类是一个模板,它描述一类对象的行为和状态。
  • 方法:方法就是行为,一个类可以有很多方法。逻辑运算、数据修改以及所有动作都是在方法中完成的。
  • 实例变量:每个对象都有独特的实例变量,对象的状态由这些实例变量的值决定。

在这里插入图片描述
注意:

  • 一个.java文件内不是只能写一个class,是可以有多个类的,但是只能有一个public的类,并且该类名要和文件名相同。
  • 一个文件中可以不含public类。

简单案例,循环,其中的打印System.out.print()print()是一个方法,System是系统类,out是标准输出对象:

package com.java.demo;

public class loop_test {
    
    
    public static void main(String[] args){
    
    
        int x = 10;
        while (x < 15){
    
    
            System.out.print("value of x: " + x);
            x++;
            System.out.print("\n");
        }
    }
}
//value of x: 10
//value of x: 11
//value of x: 12
//value of x: 13
//value of x: 14

(2)Java 语法

java基本语法:

  • 大小写敏感:Java 是大小写敏感的,这就意味着标识符 Hello 与 hello 是不同的。
  • 类名:对于所有的类来说,类名的首字母应该大写。如果类名由若干单词组成,那么每个单词的首字母应该大写,例如 MyFirstJavaClass
  • 方法名:所有的方法名都应该以小写字母开头。如果方法名含有若干单词,则后面的每个单词首字母大写。
  • 源文件名:源文件名必须和类名相同。当保存文件的时候,你应该使用类名作为文件名保存(切记 Java 是大小写敏感的),文件名的后缀为 .java。(如果文件名和类名不相同则会导致编译错误)。
  • 主方法入口:所有的 Java 程序由 public static void main(String[] args) 方法开始执行。

Java修饰符:像其他语言一样,Java可以使用修饰符来修饰类中方法和属性。主要有两类修饰符:

  • 访问控制修饰符 : default, public , protected, private
  • 非访问控制修饰符 : final, abstract, static, synchronized

Java 中主要有如下几种类型的变量

  • 局部变量
  • 类变量(静态变量)
  • 成员变量(非静态变量)
//java 的注释
public class HelloWorld {
    
    
   /* 这是第一个Java程序
    * 它将输出 Hello World
    * 这是一个多行注释的示例
    */
    public static void main(String[] args){
    
    
       // 这是单行注释的示例
       /* 这个也是单行注释的示例 */
       System.out.println("Hello World"); 
    }
}

(3)基本数据类型

六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型:byteshortintlongdoublebooleanchar。其中注意byte类型是8位,有符号的,以二进制补码表示的整数,即最小值是-128,最大值是127。

(4)方法(函数)

一个方法的定义:

修饰符 返回值类型 方法名(参数类型 参数名){
    
    
    ...
    方法体
    ...
    return 返回值;
}

在这里插入图片描述
和C++语言不同的是,java可以定义finalize()方法来清除回收对象,关键字 protected 是一个限定符,它确保 finalize() 方法不会被该类以外的代码调用。Java 的内存回收可以由 JVM 来自动完成。如果你手动使用,则可以使用finalize方法:

package com.java.demo;

public class FinalizationDemo {
    
    
    public static void main(String[] args){
    
    
        Cake c1 = new Cake(1);
        Cake c2 = new Cake(2);
        Cake c3 = new Cake(3);

        c2 = c3 = null;
        // 调用java垃圾收集器
        System.gc();
    }
}

class Cake extends Object{
    
    
    private int id;
    public Cake(int id){
    
    
        this.id = id;
        System.out.println("Cake Object " + id + "is created");
    }

    protected void finalize() throws java.lang.Throwable{
    
    
        super.finalize();
        System.out.println("Cake Object " + id + "is disposed");
    }
}

(5)java源程序与编译型运行的区别

在这里插入图片描述

1.2 Java 面向对象

(1)类和对象

java Object是所有类的父类,如果没有明确继承一个父类,java会自动继承Object,即显示继承和隐式继承:

public class Test1 extends Object{
    
     ...}
public class Test2{
    
     ...}

一个类可以包含以下类型变量:

  • 局部变量:在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。
  • 成员变量:成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。
  • 类变量:类变量也声明在类中,方法体之外,但必须声明为 static 类型。

java中是通过new实例化对象,和其他oop一样,同时会调用构造方法初始化对象。

(1)栗子1:访问实例变量和调用成员方法:

package com.java.demo;

public class Puppy{
    
    
    int puppyAge;
    public Puppy(String name){
    
    
        // 这个构造器仅有一个参数:name
        System.out.println("小狗的名字是 : " + name );
    }

    public void setAge( int age ){
    
    
        puppyAge = age;
    }

    public int getAge( ){
    
    
        System.out.println("小狗的年龄为 : " + puppyAge );
        return puppyAge;
    }

    public static void main(String[] args){
    
    
        /* 创建对象 */
        Puppy myPuppy = new Puppy( "tommy" );
        /* 通过方法来设定age */
        myPuppy.setAge( 2 );
        /* 调用另一个方法获取age */
        myPuppy.getAge( );
        /*你也可以像下面这样访问成员变量 */
        System.out.println("变量值 : " + myPuppy.puppyAge );
    }
}
//小狗的名字是 : tommy
//小狗的年龄为 : 2
//变量值 : 2

(2)import外部文件的类:import java.io.*;将会命令编译器载入 java_installation/java/io 路径下的所有类:
首先是员工类:

package com.java.demo;

import java.io.*;

public class Employee {
    
    
    // public: name实例变量对子类可见
    public String name;
    int age;
    String designation;
    // private: 私有变量,仅在该类可见
    private double salary;

    // Employee 类的构造器
    public Employee(String name) {
    
    
        this.name = name;
    }

    // 设置age的值
    public void empAge(int empAge) {
    
    
        age = empAge;
    }

    /* 设置designation的值*/
    public void empDesignation(String empDesig) {
    
    
        designation = empDesig;
    }

    /* 设置salary的值*/
    public void empSalary(double empSalary) {
    
    
        salary = empSalary;
    }

    /* 打印信息 */
    public void printEmployee() {
    
    
        System.out.println("名字:" + name);
        System.out.println("年龄:" + age);
        System.out.println("职位:" + designation);
        System.out.println("薪水:" + salary);
    }
}

接着是main函数,同样是开头有句import java.io.*;找到我们上面的员工类:

package com.java.demo;

import java.io.*;
public class EmployeeTest{
    
    

    public static void main(String[] args){
    
    
        /* 使用构造器创建两个对象 */
        Employee empOne = new Employee("RUNOOB1");
        Employee empTwo = new Employee("RUNOOB2");

        // 调用这两个对象的成员方法
        empOne.empAge(26);
        empOne.empDesignation("高级程序员");
        empOne.empSalary(1000);
        empOne.printEmployee();

        empTwo.empAge(21);
        empTwo.empDesignation("菜鸟程序员");
        empTwo.empSalary(500);
        empTwo.printEmployee();
    }
}

(2)面向对象三大特征

1)继承

  • Java通过extends申明继承。和其他oop语言类似,子类拥有父类非private的属性和方法,也可以用自己的方式实现父类的方法。
  • Java是单一继承,即不支持多继承(子类继承多个父类),但是支持多重继承(如下图)。

在这里插入图片描述

  • C++和Java中调用自身类是用this,如果调用自身类的方法则用this.xxx_function,而python中调用自身类的方法是用self.xxx_function
  • Java和python调用父类的方法可以直接用super,但是C++没有super
  • 在C++中,子类和父类函数名一样的函数fun,如果参数不一样,不管加不加virtual,当子类调用fun()时,会先在子类中找,找不到会报错。

Java的抽象类和C++那边是差不多的:

  • 当涉及父类时,父类的具体的方法无法确定,可以设置为抽象类,如public abstract class Employee,注意抽象类不能被实例化对象,需要被继承,子类重写方法。
  • 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
  • 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
  • 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
  • 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

2)多态

多态存在的三个必要条件:

  • 继承
  • 重写
  • 父类引用指向子类对象:Parent p = new Child();

java中的多态:当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。

java多态

package com.java.demo;

public class DuotaiTest {
    
    
    public static void main(String[] args) {
    
    
        show(new Cat());  // 以 Cat 对象调用 show 方法
        show(new Dog());  // 以 Dog 对象调用 show 方法
        //父类引用指向子类对象
        A a = new Cat();  // 向上转型
        a.eat();               // 调用的是 Cat 的 eat
        Cat c = (Cat)a;        // 向下转型
        c.work();        // 调用的是 Cat 的 work
    }

    public static void show(A a)  {
    
    
        a.eat();
        // 类型判断
        if (a instanceof Cat)  {
    
      // 猫做的事情
            Cat c = (Cat)a;
            c.work();
        } else if (a instanceof Dog) {
    
     // 狗做的事情
            Dog c = (Dog)a;
            c.work();
        }
    }
}
//父类animal
abstract class A {
    
    
    abstract void eat();
}

class Cat extends A {
    
    
    public void eat() {
    
    
        System.out.println("吃鱼");
    }
    public void work() {
    
    
        System.out.println("抓老鼠");
    }
}

class Dog extends A {
    
    
    public void eat() {
    
    
        System.out.println("吃骨头");
    }
    public void work() {
    
    
        System.out.println("看家");
    }
}

结果为:

吃鱼
抓老鼠
吃骨头
看家
吃鱼
抓老鼠

注意:@override表示子类的对父类方法的重写,是一种典型的标记式注解(只有编译器知道);如果子类重写的方法在父类中不存在,则编译代码时编译器会报错。

【虚函数】
java中其实没有虚函数概念,其普通函数相当于C++的虚函数,默认行为动态绑定(加上final关键字可以让某个函数变成非虚函数)。

3)封装

略。

(3)修饰符

(1)访问控制修饰符:java有四种不同的访问权限:

  • default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符,默认访问权限其实是public。使用对象:类、接口、变量、方法。
  • private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
  • public : 对所有类可见。使用对象:类、接口、变量、方法
  • protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。

(2)非访问控制修饰符

  • static 修饰符,用来修饰类方法和类变量:
    • 静态变量(类变量):用来声明独立于对象的静态变量,即无论一个类实例化多少个对象,其静态变量都只有一份拷贝;局部变量不能被声明为static变量。
    • 静态方法:静态方法不能使用类的非静态变量,需要从参数列表得到数据,然后计算该数据
  • final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。
  • abstract 修饰符,用来创建抽象类和抽象方法。
  • synchronizedvolatile 修饰符,主要用于线程的编程。

这里举个static的栗子,可以看到实例化对象500个后,静态变量是独立于不同的对象的,最终静态变量numInstances累加到500的数值:

//静态变量和方法的小栗子
package com.java.demo;

public class StaticTest {
    
    
    //静态变量
    private static int numInstances = 0;
    protected static int getCount(){
    
    
        return numInstances;
    }
    private static void addInstance(){
    
    
        numInstances++;
    }
    //main函数
    public static void main(String[] args) {
    
    
        System.out.println("Starting with" +  StaticTest.getCount() + " instances");
        for(int i = 0; i < 500; i++) {
    
    
            //new StaticTest();
            StaticTest temp = new StaticTest();
            temp.addInstance();
        }
        System.out.println("Created " + StaticTest.getCount() + " instances");
    }
}
// Starting with 0 instances
// Created 500 instances

(4)接口和抽象类

(5)Java包

  • java使用package包防止命名冲突。可以将功能相似或者相关的类or接口组织在同一个包中,方便类的查找和使用;不同包中的类的名字可以相同。在java源文件中,import语句应该在package语句之后。
  • java中的包有:java.lang打包基础的类,java.io包含输入输出功能的函数。
  • 如果一个源文件没有使用包声明,那么其中的类、函数、枚举、注释等将被放在一个无名的包中。

参考:https://www.runoob.com/java/java-package.html

(6)Java泛型

假定我们有这样一个需求:写一个排序方法,能够对整型数组、字符串数组甚至其他任何类型的数组进行排序,该如何实现?

答案是可以使用 Java 泛型。

使用 Java 泛型的概念,我们可以写一个泛型方法来对一个对象数组排序。然后,调用该泛型方法来对整型数组、浮点数数组、字符串数组等进行排序。

1.3 Java 核心技术

(0)java数据结构

(1)集合

先浏览下图的Java集合框架图,Java 集合框架主要包括两种类型的容器:

  • 一种是集合(Collection),存储一个元素集合。Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。
  • 另一种是图(Map),存储键/值对映射。

在这里插入图片描述
所有的集合框架都包括(参照下图,java集合框架位于java.util包中, 所以当使用集合框架的时候需要进行导包):

  • 接口:是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象
  • 实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayListLinkedListHashSetHashMap
  • 算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。

在这里插入图片描述

1)ArrayList集合

ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。ArrayList 继承了 AbstractList ,并实现了 List 接口。

package com.java.demo;
import java.util.ArrayList;
import java.util.Collections;

public class ArrayListTest {
    
    
    public static void main(String[] args) {
    
    
        ArrayList<String> sites = new ArrayList<String>();
        //如果是存储数字
        ArrayList<Integer> myNumbers = new ArrayList<Integer>();
        sites.add("Google");
        sites.add("Weibo");
        sites.add("AndyGuo");
        sites.add("AAAA");
        System.out.println(sites);
        //访问第二个元素
        System.out.println(sites.get(1));
        //将下标为2的元素改为Wiki
        sites.set(2, "Wiki");
        System.out.println(sites);
        //删除下标为1的元素
        sites.remove(1);
        System.out.println(sites);
        //迭代数组列表
        //for(int i = 0; i < sites.size(); i++){
    
    
        //    System.out.println(sites.get(i));
        //}
        //也可以用for-each来迭代元素
        for (String i: sites){
    
    
            System.out.println(i);
        }
        System.out.println("==========排序后:=========");
        Collections.sort(sites);
        for (String i: sites){
    
    
            System.out.println(i);
        }
    }
}

2)LinkedList集合

链表,一种线性表,不按线性的顺序存储数据,如果经常增加or删除元素可以用该数据结构。
在这里插入图片描述

3)HashSet集合

HashSet基于HashMap实现,允许有null值;
HashSet不是线程安全的:如果有多个线程尝试同事修改它,则最终结果是不去定的,即必须在多线程访问时显式同步对 HashSet 的并发访问。
在这里插入图片描述

package com.java.demo;
import java.util.HashMap;

public class HashMapTest {
    
    
    public static void main(String[] args) {
    
    
        //创建hashmap对象
        HashMap<Integer, String> Sites = new HashMap<Integer, String>();
        Sites.put(1, "AAAA");
        Sites.put(2, "BBBB");
        Sites.put(3, "CCCC");
        Sites.put(4, "DDDD");
        System.out.println(Sites);
        //通过get(key)获得对应的value
        System.out.println(Sites.get(3));
        //如果只想获取key 可以使用keySet方法
        //输出key 和 value
        for(Integer i: Sites.keySet()) {
    
    
            System.out.println("key:" + i + "; value:" + Sites.get(i));
        }
        //返回所有value值
        for(String value: Sites.values()){
    
    
            //输出每一个value
            System.out.println(value + ", ");
        }
        //直接得到所有的value
        System.out.println(Sites.values());
    }
}
/*
{1=AAAA, 2=BBBB, 3=CCCC, 4=DDDD}
CCCC
key:1; value:AAAA
key:2; value:BBBB
key:3; value:CCCC
key:4; value:DDDD
AAAA, 
BBBB, 
CCCC, 
DDDD, 
[AAAA, BBBB, CCCC, DDDD]
*/

4)HashMap

HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。

package com.java.demo;
import java.util.*;

public class MapTestt {
    
    
    public static void main(String[] args) {
    
    
        //也可以用第一种方法
        //HashMap m1 = new HashMap();
        HashMap<String, Integer> m1 = new HashMap<String, Integer>();
        m1.put("andy", 1);
        m1.put("bob", 2);
        m1.put("ccc", 3);
        System.out.print(m1);
    }
}

5)Iterator迭代器

package com.java.demo;

import java.util.ArrayList;
import java.util.Iterator;

public class IteratorTest {
    
    
    public static void main(String[] args) {
    
    
        ArrayList<String> sites = new ArrayList<String>();
        sites.add("AAAA");
        sites.add("BBBB");
        sites.add("CCCC");
        sites.add("DDDD");
        //获取迭代器
        Iterator<String> it = sites.iterator();
        System.out.println(it.next());
        //逐个遍历集合的所有元素
        while (it.hasNext()){
    
    
            System.out.println(it.next());
        }
    }
}

(2)异常

略。

(3)多线程

进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。

一个线程的生命周期:
在这里插入图片描述

(4)文件与 I\O 流

一个流被定义为一个数据序列。输入流用于从源读取数据,输出流用于向目标写数据。下图是一个描述输入流和输出流的类层次图。
在这里插入图片描述

二、并发

2.1 并发容器

JDK 提供的并发容器总结
ConcurrentHashMap
CopyOnWriteArrayList
ConcurrentLinkedQueue
BlockingQueue
ConcurrentSkipListMap

2.2 线程池

使用线程池的好处
Executor 框架
(重要)ThreadPoolExecutor 类简单介绍
(重要)ThreadPoolExecutor 使用示例
几种常见的线程池详解
ScheduledThreadPoolExecutor 详解
线程池大小确定

2.3 乐观锁与悲观锁

何谓悲观锁与乐观锁
乐观锁常见的两种实现方式
乐观锁的缺点
CAS与synchronized的使用情景

三、JVM

(1)Java内存区域
概述
运行时数据区域
HotSpot 虚拟机对象探秘
重点补充内容

(2)JVM垃圾回收
揭开 JVM 内存分配与回收的神秘面纱
对象已经死亡?
垃圾收集算法
垃圾收集器

(3)JDK 监控和故障处理工具
JDK 命令行工具
JDK 可视化分析工具

四、网络、linux、数据结构、数据库、系统设计

略,参考408系列。

Reference

[1] https://edu.csdn.net/job/javabe_01/java-4744df73a92b434593040c21501362c3
[2] runoob教程:https://www.runoob.com/java/java-character.html
[3] Spark之IDEA创建基于Scala语言的Spark Maven项目

猜你喜欢

转载自blog.csdn.net/qq_35812205/article/details/126199628