有术无道止于术,有道无术术尚可求
- 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中有三种
forwhiledo 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点该睡觉
方法
- 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马士兵 面向对象
面向对象极为重要,呵呵,就是很重要