静下心来撸一遍Java知识点

476 阅读12分钟

有术无道止于术,有道无术术尚可求

  • Shutout to 马士兵、李卫民
  • 向所有开发者致敬

第一章 Hello World

  • 第一代编程语言:打孔机,老师都没有见过
  • 第二代编程语言:汇编,比较难
  • 第三代编程语言:面向过程语言
  • 三代半:面向对象
  • 第四代语言:SQL
  • 第五代:自然语言(退休)
  • Think in Java 总和C++进行比较
  • Java没有指针但是全是指针
  • JVM和GC
  • Java是先编译.class->解释
  • 垃圾收集,只用申请内存就行,有人给回收
  • eclipse是java写的
  • 面向JVM编程
  • 开发用JDK(包含JRE) 生产用JRE?
  • 读书不要抠字眼尤其是计算机书
  • 输一个命令会去path环境变量中的目录里去找,path是从前往后找。配置了环境变量需要重启一下命令行 java -version 看当前用的那个jdk
  • classpath java在编译和运行的时候找的class文件(我没有配过classpath)
public class HelloWorld{
    public static void main(String[] args){
        System.out.println("hello world");
    }
}

Java类名和文件名应该一样,类体和方法体,一个源文件只能有一个public class 一个.java文件中有两个类的话 会编译出来两个.class文件 Java 严格区分大小写

Java注释

注释对于编译器视而不见 //TODO

总结第一个程序

  • path & classpath
  • 熟悉常见的错误
  • 熟悉Java程序简单的规则
  • 熟悉Java程序的编译和运行

编辑器和IDE

  • 编辑器:Nodepad++,视频中那个年代用ultra edit
  • IDE:集成开发程序,编写,编译,调试,运行。
  • 开始学的使用用编辑器
  • 10天之后用IDE

第二章 基础语法

标识符

  • 标识符就是能自己起名的 字母数字下划线
  • 不能用数字开头
  • 大小写敏感 不能与关键字重名
  • 用正常人的思维起名就行了——见名知意

关键字

有特殊颜色的就是关键字 都是小写 goto constjava没有用但是也是关键字

java 常量

  • 字符串常量
  • 整数常量
  • 字符常量(在计算机里是数字)'A'
  • 不可变的变量
  • final

变量

  • 先声明再赋值,使用变量名来用它
  • 本质上变量是内存中的一小块区域
  • 变量的名字 String name = "你的名字"(字符串这很多东西)
  • 变量有数据类型 根据数据类型在内存中占的大小 double d1,d2,d3 = 0.123声明了三个变量 思考这三个变量的值都是多少(不是都是0.123)
  • 全局变量会初始化一个值,局部变量必须给有初始值

内存分析(编译原理)

内存分析

  • 把代码全load到内存里去
  • 找到main方法进行执行 main(String[] args)
  • 开始内存的管理
  • code segment(load进来)
  • data segment 静态变量和字符串常量
  • heap(所有new出来的东西)
  • stack(局部变量)

变量的分类

按声明的位置分为局部变量和成员变量

  • 局部变量:方法或者语句块里定义的变量 方法的参数也是(形参)
  • 成员变量:方法外部类内部定义的变量

按所属的类型分为基本数据类型变量和引用数据类型变量

  • 类外面不能有变量的声明
  • Java里的全局?(有吗) Java是纯的面向对象的,上来就是一个class 所以没有全局变量的概念,全局参考下C++全局是什么

变量的作用域

在大括号里声明的变量,出了大括号就没有人认识了

public class TestVar{
    // 静态变量和静态方法等 知识点(static)
    static int j;
    public void m(){
        int i = 0;
        System.out.println(i);
    }
    public static void main(String[] args){
        int i = 0;
        System.out.println(i);
        System.out.println(j);
        boolean b = false;
        if(b){
            int c = 0;
            System.out.println("b is true");
        }
        // 这里报错找不到变量c
        System.out.println(c);
        long longNum1 = 8888888888888888;
    }
}

type writer && programmer 多写

数据类型

数据类型

  • 四类八种
  • 内存中的大小和小格的布局

Boolean

  • 这和C语言不一样 只有true或false,不能用0或非0代替
boolean b = true;
if(b){
    // TODO
}

字符型char

  • char表示通常意义上的字符 char eChar = '中'
  • Java采用 Unicode编码(全球语言统一编码) 每个字符占两个字节 因而可以用十六进制编码表示例如:
char c1 = '\u0061;
  • 所有的文字在计算机都是0101,每一个0或1 是一个bit 8bit是一个字节
  • 一个字节是8位 能表示2^8 也就是256种字
  • 涉及到编码的知识延伸,Unicode能表示全世界的语言
  • utf8 utf16java用的是utf16 都占用两个字节
  • 又扯到了进制相关的知识
  • 转义\n表示换行符

整数类型(在所有操作系统占用的大小一样)

C 有unsigned类型的整数 有一个字节用来表示正负号

类型 占用空间(字节) 表示数的范围
byte 1 -128~127
short 2 -2^15~2^15-1
int 4 -2^31~2^31-1
long 8 -2^63~2^63-1

16进制和10进制比较重要

  • 后面不写L 会当成int来处理 但是装不下long l1 = 888888888888L

浮点类型

  • 默认是double类型
  • float f = 12.3f 不写f会处理成double 装不进float
  • float 4个字节(7位) double 8个字节(15位) 有误差的 比较浮点数 知识点
  • 那个年代还有瑞星

基础数据类型转换

  • Boolean类型不能转换成其他数据类型
  • 字符型可以和数值型进行运算 因为他就是一个数字
  • byte short char 不会相互转换 他们做运算首先转成int类型
  • int->byte 4个字节变成1个字节 砍掉三个字节
  • long->int 也是砍
  • double->float infinity 不能砍 因为中间有小数点
  • 浮点数转换成整数会砍掉小数点后面的 不是四舍五入
float f1 = 0.123;// 报错 不兼容的类型
long l1 = 888888888888888888;// 过大的整数
float f2 = 123;//没毛病
float f3 = f1 + f2*0.3;//报错  0.3是double
byte b1 = 1;
byte b2 = 2;
byte b3 = b1 + b2;//错误: 不兼容的类型: 从int转换到byte可能会有损失
byte b1 = 68;
byte b2 = 86;
byte b3 = (byte)(b1 + b2);//-102
int i=1,j;
j = j + 10;// 声明了没有赋值
i = i / 10;// 两个都是int 操作完了还是int result=0
i = i * 0.1;// 报错 结果是double 需要强转

char c1='a',c2=125;
char c = c1 - c2;// 结果是int 还是报错

大数转换成小数写上强制转换,坑还是挺多的

float f = (float)0.123;// 0.123f  这两种写法本质上区别很大
byte b = 128;//报错

数据类型转换

格式——比算法还重要

  • 语句块之间加空行
  • 并排语句加空格 比如for
  • 运算符两侧加空格

运算符

  • 自增运算符
  • System.out.pirnt()不换行打印
  • 逻辑运算符 短路与 短路或 异或。。。
  • |||短路或
  • +字符串连接,把其他值转换成了字符串类型
  • 当打印时 都转换成字符串

三目运算符

int x = -100;
int flag = x > 0 ? 1 : (x == 0 ? 0 : -1)

语句

条件语句和循环语句

  • 循环语句java中有三种 for while do while 循环的执行某一段话

  • if语句 只有一行的时候可以省略大括号 小心

  • 设计一个算法很难,多学习别人的算法

  • 分析别人的算法时 分析内存 每一个值得变换 找找规律

    分析循环

  • 计算1!+2!+3!……+10!

  • 计算1+3+5+7+……+99

public class OddSum{
	public static void main(String[] args){
		// 计算100以内奇数的和
		int result = 0;
		for (int i = 1; i <= 100; i+=2){
			result += i % 2 != 0 ? i : 0;
		}
		
		System.out.println(result);// 2500
	}
}
  • for循环里第一个语句只执行一次
  • do while很少用
public class TestBreak{
	public static void main(String[] args){
		for(int i = 0; i < 10 ; i++){
			if(1 == 1);	
			break;
			System.out.println(i); // 报错 无法访问的语句
		}
	}
}
  • continue终止本次循环,进行下次
  • 输出1~100前五个可以被3整除的数
  • 输出101~200内的质数
public class TestLoop{
	public static void main(String[] args){
		TestLoop tl = new TestLoop();
		tl.foo();
		tl.bar();
	}
	
	// 计算被3整除的前五个数 在100以内
	public void foo(){
		// 计数器
		int num = 0;
		for(int i = 1; i <= 100; i++){
			if(i % 3 == 0){
				System.out.print(i + " ");
				num ++;
			}
			if(num == 5) break;
		}
	}
	
	// 输出101~200之间的质数
	public void bar(){
		System.out.println();
		for(int i = 2; i < 200; i++){
		    boolean isZS = true;
			for(int j = 2; j < i; j++){
				if(i % j == 0){
					isZS = false;
					break;
				}
			}
			if(isZS){
				System.out.println(i);
			}
		}
	}
}
  • switch case 小心case穿透问题
  • switch() 这里面只能是int 在java中 只要能转换成int的就能传进去
public class TestSwitch{
  public static void main(String[] args){
    long s = 2^10L;
    switch(s){
      case 100:
        System.out.println(s);
        break;
      default:
        System.out.println("bababalalalal");
        break;
    }
  }
}
  • 多个case可以合并 同时满足
case 3:
case 4:
case 5:
  System.out.println("等于3 4 5");
  break;
  • default可以不写 但是推荐写,印度人牛逼是因为母语 和 成语写的傻壮傻壮的
  • 程序鲁棒性 英雄无敌抡大棒子的兄弟 程序的健壮性很重要!
  • 12点该睡觉

方法

C/C++叫函数 Java叫方法 完成特定功能的代码片段 增强函数的复用性

  • void 调用 不返回任何值
  • 关键字 return
void echo(){
  // 二话不说就返回
  return;
  System.out.println("echo");
}

递归 在纸上画 著名的汉诺塔问题

在方法内部对自身进行调用

  • fibonacci
public class TestFibonacci{
  public static void main(String[] args){
    // 非递归的方式实现fibonacci
    fib(-1);
  }
  
  public static void fib(int index){
    // 健壮性 参数校验
    if(index < 1){
      System.out.println("非法的参数index");
      return;
    }
    
    long a = 1L;
    long b = 1L;
    long c = 0L;
    
    for(int i = 1; i <= index; i++){
      if (i == 1 || i == 2){
        System.out.println("第"+i+"个:"+1);
      }else{
        c = a + b;
        a = b;
        b = c;
        System.out.println("第"+i+"个:"+c);
      }
    }
  }
}

第三章面向对象编程

面向对象

  • 面向对象是重点,理解不好写的其实是面向过程
  • 面向对象和面向过程说白了就是代码复用的程度不同
  • 类是同一类对象的抽象 类中有属性和方法。
  • 所有的变量需要先声明,成员变量有初始化值,局部变量没有,必须手动初始化。这也就是成员变量和局部变量重要区别。

引用是什么,一小块内存指向一大块内存

除了基本数据类型(4类8种)都是引用类型

  • 基本类型就占一块内存
  • 引用类型占两块内存,对象在堆里面,引用在栈里。堆是动态分配内存的,运行期间分配,堆里空间比较大。著名的垃圾回收器回头给收拾了。
  • 类是静态的概念,在代码区里。
  • 方法是只有一份的,调用才占用内存。

对象的创建和使用

  • 必须用new关键字来创建
  • 使用对象的引用来使用成员变量和方法。
  • 每一个对象都有独立的空间,里面放的是成员变量。
  • 方法只有一份,所有对象共享,方法就是静态的代码,执行的时候才分配空间。

构造方法

构造方法没有返回值而且方法名和类名一样new就是调构造方法

  • 方法的参数也是局部变量分布在stack中,当方法调用完毕之后,这些变量就消失不再占用stack的空间
  • 默认的构造方法是一个孔方法,会初始成员变量的值。
  • 分析下列代码在内存中的过程
public class TestObject{
  public static void main(String[] args){
    TestObject to = new TestObject();
    BirthDay bd = new BirthDay(1);
    System.out.println(bd+"---"+bd.getId());
    
    to.change1(bd);
    System.out.println(bd+"---"+bd.getId());
  } 
  
  void change1(BirthDay bd){
    /*这里的bd是一个形参,也是在stack中,形参bd的内容就是一个地址*/
    System.out.println(bd+"---"+bd.getId());
    /*形参bd的内容变成了一个新的地址,但是和之前实参没有一毛钱关系*/
    bd = new BirthDay(10);
    System.out.println(bd+"---"+bd.getId());    
    // 方法执行完毕之后,这个形参bd在stack中会消失,引用的对象也就被回收了。
  }
}

class BirthDay{
  private int id;
  BirthDay(int id){
    this.id = id;
  }
  public int getId(){
    return id;
  }
}

方法的重载-OverLoad

名字相同,参数不一样

  • 参数不一样指参数个数不一样或者参数类型不一样
  • 只有返回值类型不一样不是重载 是重名,编译不通过!
// 是否构成重载?
void max(int a, int b){
    return a > b ? a : b;
}
void max(short a, short b){
    return a > b ? a : b;
}
  • 构造方法也是可以重载的,而且可以调用
  • 调用直接用this(),以下是错误的示范编译不通过。
public class TestPerson{
  private int age;
  private String name;
 
  TestPerson(){}
  
  TestPerson(int age, String name){
    this.age = age;
    this.name = name;
  }
  
  TestPerson(String name){
    this.TestPerson(name, 18);
  }
  
  public static void main(String[] args){
    new TestPerson("zhangsan");
  }
}
  • stack是从下面开始画
  • 方法的返回值会临时存在stack中

this关键字

this一般出现在方法中

  • this可以看成一个变量,值是对当前对象的引用

static关键字data seg

  • static成员变量是静态成员变量,为该类的公用变量,只有一份。任何对象都能访问,即使没有创建对象,用类名也能访问。
  • 用类名加.访问的一定是静态成员变量。System.out
  • 字符串常亮也在data seg

静态成员变量的作用

  • 计数用
public class Cat{
    public static int count;
    Cat(){
        //TODO
        count ++;
    }
}
  • 基本数据类型没有指针,Java也不要说指针,Java是引用
  • 分析内存,所有的语言都一样,局部变量在stack中,对象在heap中,静态的在data seg,代码在代码区。
  • main方法是静态的,编译器不用new对象就能调用。

作业

接口中的方法是public的,可以不写,但是实现类中重写方法时不能省略访问修饰符,省略了的话就成了default,编译报错

public class TestInterface{
  public static void main(String[] args){
    withPet(new Worker());
    System.out.println("=================");
    withPet(new Farmer());
    System.out.println("=================");
    withPet(new Gover());
  }
  
  public static void withPet(LookAfterPet lap){
    lap.eat();
    lap.play();
  }
}

interface LookAfterPet{
  void eat();
  void play();
}

class Worker implements LookAfterPet{
  public void eat(){
    System.out.println("工人喂宠物砖头");
  }
  
  public void play(){
    System.out.println("工人和宠物玩");
  }
}

class Farmer implements LookAfterPet{
  public void eat(){
    System.out.println("农民喂宠物粮食");
  }
  
  public void play(){
    System.out.println("农民和宠物玩");
  }
}

class Gover implements LookAfterPet{
  public void eat(){
    System.out.println("国家干部喂宠物money");
  }
  
  public void play(){
    System.out.println("国家干部和宠物玩");
  }
}

2019 v1马士兵 面向对象

面向对象极为重要,呵呵,就是很重要