大数据开发成长之路——Java基础(一)

Java基础

这里主要介绍学习大数据过程中的Java基础知识,欢迎大家共同交流。

环境

  • Java的运行环境和机制如图所示
    在这里插入图片描述
  • JRE(Java Runtime Environment) Java运行时环境
  • JDK(Java Development Kit) Java开发工具包
    需要在电脑上安装Java SE,下载地址,我的电脑是Windows系统,安装后将bin目录放入系统环境变量,使用cmd工具输入javajava -version命令查看是否输出相关信息
  • JDK版本
  1. Java SE:Standard Edition,标准版
  2. Java EE:Enterprise Edition,企业版
  3. Java ME:Micro Edition,移动版
  • 编译器使用IntelliJ IDEA,就不要再使用eclipse了。下载安装破解可以在网上查找资源
    在这里插入图片描述

java程序

基础部分

  • java程序的基本结构如上图所示,一个基本的java程序由类、方法、成员变量组成
  • 和所有语言类似,java中的变量、数据类型、整数浮点数运算、布尔运算就不再赘述
    如有疑问可以查看教程
包装类型
  • 我们常见的int float 变量不能视作对象(类),但是可以通过封装成对应的类并实例化实现,也叫作包装类型,JDK为每种基本类型都创建了对应的包装类型:
    在这里插入图片描述
  • 相互转化
	int a = 10;
	Integer n = Integer.valueOf(a);
	Integer n1 = Integer.valueOf("100");
	
	int b = n.intValue();
	int c = Integer.parseInt("100");
	
	String str = n.toString();
	
	Integer n = 99;		// 自动装箱
	int i = n;			// 自动拆箱	(这些都会影响效率,java是强类型语言)

Integer prop = Integer.getInteger(“cpus”); // 从系统环境中读取环境变量

String
  • 在java中,字符串属于引用类型,Java 提供了 String 类来创建和操作字符串
	public class StringDemo {
	    public static void main(String[] args) {// 字符串要使用双引号
	        String s = "Hello";     // 字符串属于引用类型,将引用类型赋给变量时:
	        String t = s;           // 变量t和s同时指向字符串Hello,而不是t重新开辟内存
	        s = "World";            // 变量s指向 World,t仍指向 Hello
	        System.out.println(s);  // World
	        System.out.println(t);  // Hello    引用类型类似指针,不产生任何副本
	    }
	}	// 可以理解为:普通变量是持有某个值(可以重写),字符串变量是指向某个值(可以重定向)

字符串的相关方法和原理可以查看:引文
常见的有substring() replace()

  • StringBuilder类
package Hello;

public class hello {
    public static void main(String[] args) {
        String name = "Roy";
        StringBuilder str = new StringBuilder();// 可变对象,可以高效拼接字符串(少占内存)
        str.append("Hello!").append(name).append("你最帅");// 支持链式操作(返回this)
        System.out.println(str);
    }
}
Array
  • 数组变量使用“类型[ ]”标识
	int[] arr = new int[5]; // 数组初始化
        arr[0] = 1;     	// 数组是统一类型的数据集合
        arr[1] = 2;     	// 可以通过索引访问
        arr[2] = 3;     	// 一旦创建大小不可改变
        arr[3] = 4;
        arr[4] = 5;
    int[] arr1 = {1,2,3,4,5};   // 也可以使用这种方式创建并赋值
    arr1 = new int[]{1,2,3};    // 数组也是引用类型,arr1重新指向了新的对象
    System.out.println(arr1.length);    // 打印数组长度
    System.out.println(arr1);   // 直接打印数组变量在JVM中的地址[I@6acbcfc0
    System.out.println(Arrays.toString(arr1));  // 快速输出数组内容

	int[][] arr2 = {	// 二维数组
                {1,2,3,4,5},
                {3,4,5,6,7},
                {5,6,7,8,9}
    };
    System.out.println(Arrays.deepToString(arr2));  // 打印多维数组
注:java是强类型语言,每个变量前面必须限定类型
  • 输入输出
    import java.util.Scanner;
    
    Scanner scanner = new Scanner(System.in);
    System.out.println("Input your name:");
    String name = scanner.nextLine();	// 输入字符类型
    System.out.println("Input your age: ");
    int age = scanner.nextInt();		// 输入int型
    System.out.println(name+", you already "+age+"years old");
	double d = 3.14159;
    System.out.print(d);    // 输出不换行
    System.out.printf("d: %.2f\n", d);  // d: 3.14 格式化输出
    System.out.printf("d: %5.2f\n", d); // d:  3.14
  • 条件判断
	public class conditionDemo {
	    public static void main(String[] args) {
	        String s1 = "Hello";
	        String s2 = "World";
	        if (s1 == s2) {
	            System.out.println("引用类型使用‘==’表示指向同一个对象");
	        }else if (s1.equals(s2)) {
	            System.out.println("判断内容相等需要使用equals()方法");
	        }
	        else if (s1 != null && s1.equals(s2)) {
	            System.out.println("当变量为null时equals()方法会报错,所以使用短路运算符");
	        }else {
	            System.out.println("也可以将字符串对象放在前面");
	        }

			double d = 1 - 9.0/10;
	        System.out.println(d);  // 浮点运算存在误差
	        if (Math.abs(d - 0.1) < 0.0001) {   // 需要使用绝对值函数判断
	            System.out.println("d is 0.1");
	        }else {
	            System.out.println("d is not 0.1");
	        }
	    }
	}
  • 循环
	public class foreachDemo {
	    public static void main(String[] args) {
	        int[] num = {1,2,3,4,5};
	        for (int n : num){        // 也叫作增强型for循环,可以循环List/Map,因此循环是无序的
	            System.out.println(n);
	        }
	    }
	} // continue 可以结束本次循环,进行下一次循环
  • 命令行参数
	public class ArgsDemo { // 命令行参数是 String[]
	    public static void main(String[] args) {	// 类似于python中的*args和**kwargs
	        System.out.println("Number of args: "+ args.length);
	        for (String arg : args) {
	            if (arg.equals("-version")) {
	                System.out.println(arg);
	            }
	        }
	    }
	}
	// 命令行参数由JVM传递给main方法
	// 使用快捷键[Alt+F12]即可在IDEA中调出命令行,输入:java ArgsDemo.java -version -s -t "Hello" 查看输出
	// javac 文件名.java 可以将java文件编译成.class文件

数据封装

  • 公有方法和私有方法,通过方法访问成员变量
  • 构造方法
  • 方法重载
package Hello;
// 一切皆对象Object
public class Person {   // 数据封装
    public String name;
    public int age;

    public Person(String name, int age) {   // 构造方法:可以在实例化时初始化成员变量的值
        this.name = name;
        this.age = age;
    }

    public Person() {  // 多个构造方法,实例化时可以根据参数的数量和位置自动选择合适的构造方法
        this("Roy",22); // 通过this进行实例化
    }

    public void setName(String name){   // 外部对象一般通过public修饰的方法访问成员变量
        this.name = name;
    }
    // 方法重载:功能相同的函数使用相同的名字
    public void setName() {     // 主要依靠参数类型和数量区分
        System.out.println("这是setName方法的重载");
    }

    public String getName() {
        return this.name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return this.age;
    }

    private int calcBirth(int age) {
        return 2020 - age;
    }

    public int getBirth(int age){ // 内部方法可以调用私有方法
        return calcBirth(age);
    }
}
package Hello;

public class Main {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person.name + person.age);// Roy22
        person.setAge(18);
        person.setName("Roy");
        System.out.println("Your name is " + person.getName());
        // 公有方法调用私有方法
        System.out.println("Your birthday is " + person.getBirth(23));
    }
}

继承

  • 继承是一种代码复用的方式
  • 一个类只能有一个父类,所有的类均继承自Object类,形成一个继承树:
  • Object——Person——Girl & Boy
package Hello;
// 一切皆对象Object
public class Person /* extends Object */{
    public String name;
    public int age;

    protected int speed;    // protected 把变量和方法都控制在继承树内部

    public Person(String name, int age) {   // 构造方法:可以在实例化时初始化成员变量的值
        this.name = name;
        this.age = age;
    }

    public Person() {   // 多个构造方法,实例化时可以根据参数的数量和位置自动选择合适的构造方法
        this("Roy",22); // 通过this进行实例化
        System.out.println("自动调用父类的无参数构造器");
    }

    public void run() {
        System.out.println("冲鸭!");
    }
}

package Hello;

public class Girl extends Person {
    String name;
    int age;

    public Girl(String name, int age) { // 构造方法
    	// 会自动调用父类的无参数构造方法,相当于super()
    	// 如果父类没有无参的构造方法,必须调用父类的有参构造方法!
        this.name = name;
        this.age = age;
    }

    public void run() {     // 继承并重写父类的方法
        super.run();		// 复用了父类的代码,提高效率
        System.out.println("女孩向前冲!");
    }
}

package Hello;

public class Boy extends Person {
    String name;
    int age;

    public Boy(String name,int age) {
        super("father",88); // 调用父类中有参数的构造方法
        this.name = name;
        this.age = age;
    }

    public void run() {     // 继承并重写父类的方法
        super.run();        // super关键字调用父类的成员
        System.out.println(super.speed);    // 子类不能调用父类的private变量,但可以使用protected变量
        System.out.println("男孩向前冲!");
    }
}
package Hello;

public class Main {
    public static void main(String[] args) {
        Person person = new Person("Roy",18);
        Boy boy = new Boy("John",16);
        Girl girl = new Girl("Diana",16);
        boy.run();
        girl.run();
    }
}
/* 输出:
父类的无参数构造器
冲鸭!
0
男孩向前冲!
冲鸭!
女孩向前冲! */
  • 注意区分继承和组合的关系,继承是is,拥有相同特性的类之间的从属关系;而组合是has,可以通过在类中实例化其对象实现
  • 继承往往和多态相联系,多态有三要素:1.要有继承关系 2.要有子类重写父类成员方法 3.要有父类数据类型引用至子类

转型

package Hello;

public class Main {
    public static void main(String[] args) {
        // 转型
        Person ps = boy;    // 向上转型(子类变成父类)
        ps.run();   // 冲鸭!
        Boy by = (Boy) person;    // 向下转型(父类变成子类),必须强制
        // 由于子类不一定实现了父类的所有方法,所以会抛出异常
        by.run();   // ClassCastException
    }
}

抽象类

  • 定义了抽象方法的类就是抽象类,必须使用abstract修饰
  • 抽象类是为了更加灵活地实现多态特性(子类可以控制父类的方法)
  • 抽象方法相当于定义了子类必须实现(重写)的接口规范
package Hello;

public abstract class CalcArea {	  // 抽象类
    public abstract double area();    // 抽象方法,没有任何实现的代码
    
    public double perimeter() {       // 可以定义非抽象方法
        return 0;
    }
}
package Hello;

public class RectArea extends CalcArea{
    private final double width;	// final修饰成员变量,必须要赋初始值,且只能初始化一次
    private final double height;// 所以必须使用有参构造方法赋值
    // final修饰类的时候,表示这个类不能被继承,类中的成员方法都会被隐式的指定为final方法
    // final修饰的方法不能被重写

    public RectArea(double width,double height) {
        this.width = width;
        this.height = height;
    }
    @Override
    public double area() {    // 实现父类的抽象方法
        return this.height * this.width;
    }
}
package Hello;

public class CircleArea extends CalcArea{
    public double redius;

    public CircleArea(double redius) {
        this.redius = redius;
    }
    @Override
    public double area() {
        return Math.PI * redius * redius;
    }
}
package Hello;

public class Main {
    public static void main(String[] args) {
        CalcArea Circle = new CircleArea(5);  // 调用的是子类的方法,但实例化为抽象类即可(因为实现了所有父类的方法,可以向上转型)
        CalcArea Rect = new RectArea(5,5);    // 我们只关心是否实现了抽象类的方法
        System.out.println(Circle.area());    // 具体的实现完全由不同子类承担,功能各异
        System.out.println(Rect.area());      // 更加灵活的实现了多态的特性
    }
}

接口

  • 接口定义了纯抽象的规范,使用interface关键字修饰
  • 一个类可以实现多个接口,使用implement
  • 接口也是数据类型,适用于向上向下转型
  • 接口不能定义实例字段(即只能定义方法)
  • 接口可以定义default方法,实现接口的类可以不用实现default方法
package Hello;

public interface InterfaceDemo {
    double area();    // 接口方法

    default double perimeter(){     // default方法,执行接口的类不用实现
        return 0;
    }
}
package Hello

public class CircleArea implements InterfaceDemo{  // 实现接口
    public double redius;

    public CircleArea(double redius) {
        this.redius = redius;
    }

    @Override
    public double area() {
        return Math.PI * redius * redius;
    }
}
  • 接口可以继承接口实现接口的扩展
package Hello;

public interface InterfaceDemo1 extends InterfaceDemo{
    int speed();
}
public class CircleArea implements InterfaceDemo1{  // 实现接口
    public double redius;

    public CircleArea(double redius) {
        this.redius = redius;
    }

    @Override
    public double area() {
        return Math.PI * redius * redius;
    }

    @Override
    public int speed() {
        return 0;
    }
}
  • 接口的层次代表了抽象的程度(可以先不理解)
  • 接口与抽象类的区别:
    在这里插入图片描述

静态字段和方法

  • 使用static修饰的字段和方法
  • 普通字段在每个实例中都有自己的一个“独立空间”
  • 静态字段只有一个“共享空间”,所有实例都共享该字段
    在这里插入图片描述
package Hello;

public class Person {
	static int number;
	// 静态方法
    public static int getNumber() {
        return ++number;
    }
}
package Hello;

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person();
        Person.number++;		// 类名访问静态变量
        System.out.println(Person.getNumber());
        Person p2 = new Person();
        Person.number++;
        System.out.println(Person.getNumber());
        Person p3 = new Person();
        Person.number++;
        System.out.println(Person.getNumber());
    }
}

  • 不推荐使用实例对象访问静态字段,因为实例本身并没有静态字段,也是由编译器转化为类名来访问。推荐直接使用类名访问!
  • 调用静态方法不需要实例对象
  • 静态方法通常用于工具类,例如:Arrays.sort() / Math.random()

  • 我们自定义的类名可能与java中或其他人的类名冲突,这是就需要定义包package,上面的每一个小例子都在包Hello
  • java加载class并执行代码时,总是使用类的完整类名,比如java.util.AraysHello.Person,这样就避免了重复命名引起冲突(类似于命名空间的概念),也因此,包没有继承关系!
  • 位于同一个包的类,可以访问包作用域的字段和方法
  • 前面使用了public/protected/private都代表了字段或方法不同的作用域,在一个包中不使用这些修饰的就默认在包的作用域

注:如果不能确定是否使用public方法,就不要使用,否则会暴露方法的

在这里插入图片描述

  • java的核心类放置在java.lang
    在这里插入图片描述
  • java文件的存放要按照包名的层次关系
    在这里插入图片描述

classpath

  • 是一个环境变量,指示如何搜索class
    在这里插入图片描述
    在这里插入图片描述
  • 我们通常引入jar包避免大量的目录和.class文件
    在这里插入图片描述
  • 创建jar包可以使用自带的jar命令,或者使用构建工具如Maven
  • jar中可以包含一个特殊的 MANIFEST.MF 文件,用于指定Main-class等
  • JDK自带的class被打包在rt.jar中

JavaBean

  • 在这里插入图片描述
  • 命名规范:成员变量私有化,使用类的getter/setter方法访问

enum常量

public enum Weekday {
    SUN("星期天"), MON("星期一"), TUE("星期二"), WED("星期三"), THU("星期四"), FRI("星期五"), SAT("星期六");

    private String chinese; // 定义私有变量

    private Weekday(String str){// 定义构造方法
        this.chinese = str;
    }
    
    public String toChinese(){
        return this.chinese;
    }
}
package Hello;

public class Main {
    public static void main(String[] args) {
        Weekday sun = Weekday.SUN;
        System.out.println(sun.toChinese());// 星期天
        System.out.println(sun.name());     // SUN (不推荐使用toString())
}
  • 在这里插入图片描述
  • 可以理解为以类形式封装的常量

常用工具类

  • Math
  • Random
  • 在使用过程中积累即可!

推荐廖雪峰老师的教程
下节继续
在这里插入图片描述

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瑞士_R

修行不易...

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值