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虚拟机的内存可以分为三个区域:栈,堆,方法区(在堆中)。
栈的特点如下:
- 栈描述的是方法执行的内存模型,每个方法都被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)
- JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)
- 栈属于线程私有,不能实现栈线程间的共享
- 栈的存储特性是"先进后出,后进先出"
- 栈是有系统自动分配,速度块。栈是一个连续的内存空间
堆的特点如下:
- 堆用于存储创建好的对象和数组(数组也是对象)
- JVM只有一个堆,被所有线程共享
- 对是一个不连续的内存空间,分配灵活,速度慢
方法区(又叫静态区):
- JVM只有一个方法区,被所有线程所共享
- 方法区实际也是堆,只是用于存放存储类、常量的相关信息
- 用来存放程序中永远是不变或唯一的内容(类信息【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 编程中封装的具体优点:
- 提高代码的安全性;
- 提高diamante的复用性
- “高内聚”:
2.6.2 封装的实现——使用访问控制符:
修饰符 | 同一个类 | 同一个包 | 子类 | 所有类 |
private | * | |||
default | * | * | ||
protected | * | * | * | |
public | * | * | * | * |
2.6.3 封装的使用细节
类的属性的处理:
- 一般使用private访问权限。
- 提供响应的get/set犯法来访问相关属性,这些方法通常是public修饰的,以提供对属性的赋值与读取操作(注意:boolean变量的get方法是is开头的)。
- 一些只用于本类的辅助性方法可以用protected修饰,希望其他类调用的方法用public修饰。
2.7 多态(polymorphism)
多态指的是同一个方法调用,由于对象不同可能会有不同的行为。显示生活中,同一个方法,具体实现会完全不同。
2.7.1 多态的要点:
- 多态是方法的多态,不是属性的多态(多态与属性无关)
- 多态的存在有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关键字的作用:
- 修饰变量:被他修饰过的变量不可以改变。一旦赋了初值,就不能被重新复赋值。
final int MAX_SPEED = 120;
- 修饰方法:该方法不可被子类重写。但是可以被重载!
final void study() {}
- 修饰类:修饰的类不能被继承。比如: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数组的定义:
数组是相同类型数据的有序集合。数组描述的是相同类型的若干个数据,按照一定先后次序排列组合而成。起哄,每一个数据称作一个元素,每一个元素可以通过一个索引(下标)来访问他们。数组的是哪个基本特点:
- 长度是确定的。数据一旦被创建,它的长度就不可以被改变。
- 其元素必须是相同类型,不允许出现混合类型。
- 数组类型可以是任何数据类型,包括基本类型和引用类型。
数组本身就是对象,因此无论存放的是基本数据类型还是其他数据类型,数组对象本身是在堆中存储的。
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 递归算法详解
递归是一种常见的解决问题的方法,即把问题逐渐简单化。递归的基本思想就是"自己调用自己",一个使用递归技术的方法将会直接或者间接地调用自己。
利用递归可以使用简单的程序解决一些复杂的问题。如:斐波那契数列的计算、汉诺塔、快排等问题。
递归结果包括两个部分:
- 定义递归头。解答:什么时候普不调用自身方法。如果没有头,将陷入死循环,也就是递归的结束条件。
- 递归体。解答:什么时候需要调用自身方法。
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
/*