Java基础知识 - 不全 只是我不太熟悉的地方的回顾

  • java面向对象基础和java基础
  • 1. java基础
  • 1.1 java应用程序的运行机制
  • 2.1 JVM,JDK和JRE的区别
  • 2.1.1 JVM:Java Virtual Machine
  • 2.1.2 JRE是什么:
  • 2.1.3 JDK:
  • 3. JDK目录介绍
  • 2. java面向对象基础
  • 2.1 Java面向对象的内存分析
  • 2.2 this指针的本质
  • 2.3 static关键字
  • 2.4 == 和 equals 方法
  • 2.5 super关键字
  • 2.6 封装的作用和含义
  • 2.6.1 编程中封装的具体优点:
  • 2.6.2 封装的实现——使用访问控制符:
  • 2.6.3 封装的使用细节
  • 2.7 多态(polymorphism)
  • 2.7.1 多态的要点:
  • 2.8 对象的转型(casting)
  • 2.9 final关键字
  • 2.10 数组概述和特点
  • 2.10.1数组的定义:
  • 2.10.2 数组的初始化方法总共有三种:静态初始化、动态初始化、默认初始化
  • 2.11 递归算法详解
  • 2.11.1 递归的缺陷
  • 2.11.2 注意事项


java面向对象基础和java基础

1. java基础

1.1 java应用程序的运行机制

java是编译型和解释型两种语言的结合。编译指在编译器中将源文件编译成字节码文件。然后在jvm(java虚拟机,解释器)中执行。Java和C与C++不同,java使用虚拟机来执行java程序,使用虚拟机来与操作系统打交道,而C和C++在编译完成后,直接与系统打交道。这也是java实现跨平台的核心机制。

2.1 JVM,JDK和JRE的区别

2.1.1 JVM:Java Virtual Machine

一个虚拟的计算机,用来执行bytecode字节码。

2.1.2 JRE是什么:

jre:java runtime environment,即java运行环境。运行java程序所必须的环境的集合,包含JVM标准和java核心类库。

jre包含Java虚拟机(jvm),java核心类库和支持文件。它不包含开发工具(JDK)–编译器、调试器和其他工具。

2.1.3 JDK:

Java Development Kit:java开发环境包。增加了编译器、库函数、运行java程序的所必须的文件。

3. JDK目录介绍

bin:存放二进制文件。

db:存放数据。

include:头文件。

lib:库,java的jar包。

2. java面向对象基础

2.1 Java面向对象的内存分析

java虚拟机的内存可以分为三个区域:栈,堆,方法区(在堆中)。

栈的特点如下:

  1. 栈描述的是方法执行的内存模型,每个方法都被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)
  2. JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)
  3. 栈属于线程私有,不能实现栈线程间的共享
  4. 栈的存储特性是"先进后出,后进先出"
  5. 栈是有系统自动分配,速度块。栈是一个连续的内存空间

堆的特点如下:

  1. 堆用于存储创建好的对象和数组(数组也是对象)
  2. JVM只有一个堆,被所有线程共享
  3. 对是一个不连续的内存空间,分配灵活,速度慢

方法区(又叫静态区):

  1. JVM只有一个方法区,被所有线程所共享
  2. 方法区实际也是堆,只是用于存放存储类、常量的相关信息
  3. 用来存放程序中永远是不变或唯一的内容(类信息【class对象】、静态变量、字符串常量等)

2.2 this指针的本质

this的本质就是"就是创建好的对象的地址"!由于在构造方法调用前,对象已经创建。因此在构造方法中也可以使用this代表"当前对象"。

2.3 static关键字

在类中,使用static声明的成员对象变量为静态成员变量,也成为类变量。类变量的声明周和类相同,在整个应用程序执行期间都有效。

static修饰的成员变量和方法,从属于类。普通变量和方法从属于对象的。

2.4 == 和 equals 方法

== 用来代表比较双方是否相同。如果是基本类型则表示值相等,如果是引用类型则表示地址相等即是同一个对象。

equals 方法:Object类中定义有:public boolean equals(Object obj)方法,提供定义”对象内容相等“的逻辑。

2.5 super关键字

super是直接父类对象的引用。可以通过super、来访问父类中被子类覆盖的方法或属性。

2.6 封装的作用和含义

封装就是把对象的属性和操作结合为一个独立的整体,并竟可能隐藏对象的内部实现细节。

我们程序设计要追求"高内聚,低耦合"。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合是仅暴露少量的方法给外部使用,尽量方便外部调用。

2.6.1 编程中封装的具体优点:
  1. 提高代码的安全性;
  2. 提高diamante的复用性
  3. “高内聚”:
2.6.2 封装的实现——使用访问控制符:

修饰符

同一个类

同一个包

子类

所有类

private

*

default

*

*

protected

*

*

*

public

*

*

*

*

2.6.3 封装的使用细节

类的属性的处理:

  1. 一般使用private访问权限。
  2. 提供响应的get/set犯法来访问相关属性,这些方法通常是public修饰的,以提供对属性的赋值与读取操作(注意:boolean变量的get方法是is开头的)。
  3. 一些只用于本类的辅助性方法可以用protected修饰,希望其他类调用的方法用public修饰。

2.7 多态(polymorphism)

多态指的是同一个方法调用,由于对象不同可能会有不同的行为。显示生活中,同一个方法,具体实现会完全不同。

2.7.1 多态的要点:
  1. 多态是方法的多态,不是属性的多态(多态与属性无关)
  2. 多态的存在有3个必要条件:继承,方法重写,父类引用指向子类对象。
  3. 父类引用指向子类对象后,用该父类调用子类重写的方法,此时,多态就出现了。
public class Test {
	

	public static void main(String[] args) {
		Cat c = new Cat();
		Dog d = new Dog();
		
		Animal a = new Dog(); // 自动向上转型
		Dog a2 = (Dog) a; // 自动向下转型
        
		animal(a);
		
	}
	
	static void animal(Animal a) {
		a.shout();
	}
	
}

class Animal {
    public void shout() {
        System.out.print汪汪汪
汪汪汪
喵喵喵ln("叫了一声");
    }
}

class Cat extends Animal{
    public void shout() {
        System.out.println("喵喵喵");
    }
}

class Dog extends Animal{
    public void shout() {
        System.out.println("汪汪汪");
    }
}
/**
汪汪汪
汪汪汪
喵喵喵
**/

2.8 对象的转型(casting)

父类引用指向子类对象,我们成这个过程为向上转型,属于自动类型转换。

向上转型后的父类引用变量只能调用它编译类型的方法,不能调用它运行时类型的方法。这时,我们就需要进行类型的强制转换,我们称之为向下转型。

2.9 final关键字

final关键字的作用:

  1. 修饰变量:被他修饰过的变量不可以改变。一旦赋了初值,就不能被重新复赋值。
final int MAX_SPEED = 120;
  1. 修饰方法:该方法不可被子类重写。但是可以被重载
final void study() {}
  1. 修饰类:修饰的类不能被继承。比如:Math、String等。
final class A {}

测试:

public class Test {
	

	public static void main(String[] args) {
		Cat c = new Cat();
		Dog d = new Dog();
		汪汪汪
汪汪汪
喵喵喵
		Animal a = new Dog(); // 自动向上转型
		Dog a2 = (Dog) a; // 自动向下转型
        
		animal(a);
		
	}
	
	static void animal(Animal a) {
		a.shout();
	}
	
}

class Animal {汪汪汪
汪汪汪
喵喵喵
    public void shout() {
        System.out.println("叫了一声");
    }
}

class Cat extends Animal{
    public void shout() {
        System.out.println("喵喵喵");
    }
}

class Dog extends Animal{
    public void shout() {
        System.out.println("汪汪汪");
    }
}

2.10 数组概述和特点

2.10.1数组的定义:

数组是相同类型数据的有序集合。数组描述的是相同类型的若干个数据,按照一定先后次序排列组合而成。起哄,每一个数据称作一个元素,每一个元素可以通过一个索引(下标)来访问他们。数组的是哪个基本特点:

  1. 长度是确定的。数据一旦被创建,它的长度就不可以被改变。
  2. 其元素必须是相同类型,不允许出现混合类型。
  3. 数组类型可以是任何数据类型,包括基本类型和引用类型。

数组本身就是对象,因此无论存放的是基本数据类型还是其他数据类型,数组对象本身是在堆中存储的。

2.10.2 数组的初始化方法总共有三种:静态初始化、动态初始化、默认初始化

静态初始化:

public class Test {
    
    public static void main(String[] args) {
        //静态初始化
        int[] a = {2,3,5};
        User b = {
            new User(1001, "zhangsan"), 
            new User(1002, "zhaoxin")
        };
        
        //默认初始化
        int[] c = new int[3]; //  数字默认为0, boolean默认为false, String默认为null
    }
}

2.11 递归算法详解

递归是一种常见的解决问题的方法,即把问题逐渐简单化。递归的基本思想就是"自己调用自己",一个使用递归技术的方法将会直接或者间接地调用自己。

利用递归可以使用简单的程序解决一些复杂的问题。如:斐波那契数列的计算、汉诺塔、快排等问题。

递归结果包括两个部分:

  1. 定义递归头。解答:什么时候普不调用自身方法。如果没有头,将陷入死循环,也就是递归的结束条件。
  2. 递归体。解答:什么时候需要调用自身方法。
2.11.1 递归的缺陷

简单的程序是递归的优点之一。但是递归调用会占用大量的系统堆栈,内存消耗多,在递归调用层次多时速度要比循环慢很多,所以在使用递归时要慎重。


2.11.2 注意事项

任何能用递归解决的问题也能使用迭代解决。当递归方法可以更加自然地反应问题,并且易于理解和调试,并且不强调效率问题时,可以采用递归;

在要求高性能的情况下尽量避免使用递归,递归调用既花时间又耗内存。

package BasicKnowledge;

public class TestRecursion {

    public static void main(String[] args) {

        long d1 = System.currentTimeMillis();
        long result =  factoria(35);
        System.out.println(result);
        long d2 = System.currentTimeMillis();
        System.out.printf("递归所耗费的时间: %s%n", d2-d1);
        long result2 = factoria2(35);
        System.out.println(result2);
    }

    public static int count = 0;

    public static void a() {
        System.out.println("a");
        count ++;
        if(count < 10) {
            a();
        }else{
            return;
        }


    }

    public static void b() {
        System.out.println("bs");
    }

    public static long factoria(int n) {
        if(n ==1) {
            return 1;
        }
        else {
            return n * factoria(n - 1);
        }
    }

    public static long factoria2(int n) {
        long temp = 1;
        if(n == 0){
            return 1;
        }

        else if(n == 1){
            return 1;
        }
        else{
            for (int i = 2; i <= n; i++) {
                temp = temp * i;
            }
            return temp;
        }
    }

}

/**
* 然而这段程序在i7-9750h看来执行时间都短的可怜。
* 递归所用时间是 1ms左右(有时也显示为0ms)
* 迭代循环也是0-1ms
/*