java简易笔记一篇入门

🍭 不要焦虑也不要放弃,每天进步一点点 🍭

学前必看

本文面向的是对 java 只想做一个基本了解的同学,比如暂时不搞开发的脚本小子,如果需要深入学习,不建议观看,看完本文可以掌握 java hello world 编写和各语言通用的流程控制函数和忽略不计的面向对象知识

java是一种面向对象的编程语言,有很多特定的工具类/函数,方便不同情景的快速编程,使用的开发工具是 IntelliJ IDEA
参考视频教程:狂神的java基础

java 基础

java helloworld

新建 HelloWorld.java 文件(环境安装略) 本文使用 SDK 版本为1.8

public class HelloWorld {
    public static void main(String[] args){
        System.out.print("hello world!");
    }
}

① java 是严格大小写的语言,Test 和 test 是两个东西

② 类名要与文件名一致

java 是编译型语言,首先需将 HelloWorld.java 文件编译成 HelloWorld.class 文件再执行

PS C:\java_lession> javac .\HelloWorld.java
PS C:\java_lession> java HelloWorld
hello world!

在这里插入图片描述

class 文件是字节码文件,介于 java 类文件和机器码之间的一种文件,然后由 JVM 来解释执行

定义变量

java 是强类型语言,需要先定义数据类型,然后定义名称,再赋值,像php、python等不用预先定义,即可使用

//定义变量为String字符串类型,变量名为test,值为 this is a test
String test = "this is a test";

变量命名时只能以字母、$ 美元符、或 _ 下划线开头

数据类型

整数

byte:占 1个字节  范围:-128-127
short:占 2个字节  范围:-32768-32767
int:占 4个字节  范围:-2147483648-2147483647
long:占 8个字节  范围:-9223372036854775808-9223372036854775807
//long num = 10L; long类型要在数字后面加个"L"来标识

浮点类型(小数)

float:占 4个字节  //float num = 1.1F; 需加"F"来标识
double:占 8个字节
//double精度高,有效数字16位,float精度7位

最好避免使用浮点数进行比较,如果超出范围,在定义时没有报错,但是存储时数据已经有损失

在这里插入图片描述

字符类型

char:占 2个字节  //只能定义一个字符,且必须用单引号包裹
char a = '网';
char a = 'A';

char 类型能表示的数据十分有限,而字符串我们是通过String类来定义,是类而不是数据类型

在定义时,一旦类型确定,会在内存开辟相应大小的空间来存放数据,尽量选择合适的类型来节省空间

boolean:true or false 只占一位

除了以上8种基本数据类型,其它的叫做引用数据类型

关于字节的科普

位(bit):存储数据的最小单位,0 或 1 占一位,简写为 b

字节(Byte):8 位为一个字节,可以表示0-255,在少数系统中不是 8 位

因为我们交流不能使用 01010 字符串,所以要使用编码,来使 01 字符串和字母或汉字对应,而能表示人类语言的一个最小单位,也就是数据处理的基本单位,或许可以称为字节

比如 ascii 编码,收录了 128 个字符,常见字母和常见符号,用一个字节即可表示所有

进制

java 中不同进制数据表示方法

int i1 = 10;      // 10进制
int i2 = 0b10;    // 2进制
int i3 = 010;     // 8进制
int i4 = 0x10;    // 16进制

快速打印

// sout 回车 输出语句
System.out.println();  
// psvm 主函数
public static void main(String[] args) {}

强制类型转换

和之前学习的写法有所不同

char a = '中';
System.out.println((int)a);
>>>> 20013
System.out.println((int)'s');
>>>> 115

unicode 编码,又称万国码,将世界上所有的文字用 2 个字节统一进行编码,而常用的 utf8 编码是 unicode 的一种实现方式(unicode在扩充表意文字时发现不够用了),可根据不同编码通过变长(1~4字节)来表示,所以可以理解为什么汉字可以转换成数字

可以尝试打印一下看看汉字的编码范围,在 java 中是使用 UTF-16 的编码方式

System.out.println((char)13312);
ascii:65--a
unicode:61--a
utf-16:97--a

而普通类型转换可以不写,就是类似小范围转大范围,整数转小数这类的,略

内存溢出

顾名思义,就是数据与内存大小不匹配,装不下了

// 定义两个变量
int money = 10_0000_0000;
int years = 20;
// 变量相乘 一个乘之前做了类型转换 一个没有
long total = money*years;
long total2 = money*(long)years;
// 打印变量
System.out.println(total);
System.out.println(total2);

money*years 的值已经超过了 int 所能表示的最大值,就会溢出,结果如下

>>>> -1474836480
>>>> 20000000000

类与对象

类是变量(属性)和函数(方法)的集合,用 class 关键字标识

类有什么用? 为什么要把一堆数据函数绑定到一起? 这是为了实现封装,类是对现实生活中一类具有共同特征的事物的抽象,比如我要实现一个生成订单的功能,要扣减库存、扣减促销资源,更新用户账户等操作,我把这一系列操作抽象成一个订单类,需要的变量函数我都放到里面,这样就比较方便使用与理解

我们需要知道,类是一种数据类型,不是数据,不在内存中存储,所以我们需要实例化一个类,叫做对象,才能对它进行操作

public class a{}

变量作用域

包括类变量、实例变量、局部变量

public class Variable {
    static int allClicks = 0;   // 类变量 static关键字
    String str = "hello world!";    // 实例变量 不需要初始化即可使用 有默认值
  
    public void method(){
        int i = 0;  // 局部变量 必须声明和初始化
    }
}

局部变量就是只在最近的一个花括号内才能使用的变量

常量

使用 final 关键字,常量的名称一般用全大写的,比较容易区分

final double PI = 3.14;

修饰符

类似 final、static…等非数据类型的叫修饰符,不区分先后顺序,随意

static final double PI = 3.14;
final static double PI = 3.14;
public static final double PI = 3.14;

命名规范

推荐养成的习惯,便于阅读交流

所有变量名、方法名、类名:见名知意
类成员变量:首字母小写,后面单词首字母大写
局部变量:首字母小写,后面单词首字母大写
常量:全部字母大写,可加下划线 
类名:首字母大写,后面单词首字母大写 Man GoodMan
方法名:首字母小写,后面单词首字母大写 run() runRun()

运算符

java 支持如下运算符

算数运算符: + - * / %(取模) ++ --
赋值运算符: =
关系运算符: > < >= <= == != instanceof
位运算符: & | ^ ~ >> << >>>
条件运算符: ?:
扩展赋值运算符: += -= *= /=

位运算

因为任何计算都要转换为 01 序列进行运算,位运算在某些情况下可以提高计算机的运算效率

如计算 2 的 n 次幂

2^3 = 2<<3;

它的意思是将二进制数向左移 3 位,如何理解,拿十进制数看一下,0013,左移一位(空位补0),0130,就是扩大了十倍,左移两位,1300,就是扩大了一百倍,同理,二进制数左移一位,就是扩大两倍,左移两位,就是四倍,10 位就是 2^10,1024 倍…类似的,可以增加幂运算的计算效率

关于a++和++a

int a = 3;
int b = a++;
System.out.println(a);
System.out.println(b);
>>> 4
>>> 3

要给程序一个入口 main 函数,一个项目一个 main 函数就可以

int a = 3;
int b = ++a;
System.out.println(a);
System.out.println(b);
>>> 4
>>> 4

区别就是如果自增运算符在后,是先赋值,a才会加一,在前面则是先加一再赋值

短路运算

在进行与(&&)运算的时候,必须两个都为真结果才为真,那么只要第一个条件为假,就不必判断后面的条件了,这就是所谓的短路运算

int c = 4;
boolean d = (c<4)&&(c++)<5;
System.out.println(c);
System.out.println(d);
>>> 4
>>> false

在判断完 c<4 为假,就进行一些操作将其简化为假,并不会判断后面的语句然后执行 c++,所以 c 的值仍然为 4

在这里插入图片描述

int c = 4;
if ((c < 4)) {
    c++;
}
boolean d = false;

可以看到只单独判断了 c 是否小于4

三元运算符

x ? y:z

如果 x 语句结果为真,则结果为 y,为假则结果为 z

int c = 4;
int result = c>5 ? c++ : c-- ;
System.out.println(c);
>>> 3

语句有一个返回结果,需要用变量接收

包机制

为了更好的组织类,java 提供了包机制,用于区别类名的命名空间,类似于文件夹的功能

package pkg1[.pkg2[.pkg3]...];

一般利用公司域名倒过来作为包名

导入包使用 import 语句

import package1[.package2...].(classname|*)

流程控制

接收用户输入 scanner

// 创建一个扫描器对象,用于接收键盘数据
Scanner scanner = new Scanner(System.in);
System.out.println("使用next方式接收:");

// 判断用户有没有输入字符串
if(scanner.hasNext()){
    String str = scanner.next();
    System.out.println("输出的内容为:"+ str);
}
// IO流的类用完要随手关 养成节约资源的好习惯
scanner.close();
使用next方式接收:
hello world
输出的内容为:hello

使用 nextline 方法

String str = scanner.nextLine();
使用next方式接收:
hello world
输出的内容为:hello world

next 方法以空格作为结束符,nextline 以回车作为结束符

还可以简单判断数据的类型,例如

Scanner scanner = new Scanner(System.in);
System.out.println("请输入整数:");
if(scanner.hasNextInt()){
    int i = scanner.nextInt();
    System.out.println("整数数据:"+i);
}else {
    System.out.println("输入的不是整数数据!");
}
scanner.close();

if 结构

if(布尔表达式/默认为true){
    // 如果布尔表达式为 true 将执行的语句 
}
if(布尔表达式/默认为true){
    // 如果布尔表达式为 true 将执行的语句 
}else{
    // 如果表达式为false
}
if(条件1){
    ...
}else if(条件2){
    ...
}else{
    // 都不满足时执行
}

switch 结构

switch(expression){
    case value1:
    // 语句
    break;//可选
    case value2:
    // 语句
    break;
    case value3:
    // 语句
    break;//可选  
    default: //可选
    // 语句
}

break 语句是跳出当前语句,即{},结束 switch 语句,如果没有的话,在满足value2时,执行完对应的语句还会继续向下执行,不进行值的判断,直到遇到 break 语句或全部执行完才结束

while 循环

当满足条件时,执行语句

int i = 0;
while(i<100){
    i++;
}

do while 循环

一定会执行一次,然后判断是否满足条件,满足则继续执行

int i = 0;
do {
    i++;
}while (i<100);

for 循环

9.for 快速打印 i=0;i<9,i++ 的 for 循环

for (int i = 1; i <= 9; i++) {
    for (int j = 1; j <= i; j++) {
        int s = i*j;
        System.out.print(i+"*"+j+"="+s+"\t");
    }
    System.out.print("\n");
}

增强 for 循环,可以作为遍历数组集合的快捷方式

int[] numbers = {10,20,30,40,50};
for(int x:numbers){
    System.out.println(x);
}

跳出循环

break 中止循环,不执行剩余语句

continue 中止本次循环,直接进行下一次循环

小练习 打印三角形

// 打印三角形 一共打印 I 行
final int I = 25;
// 打印第 k 行 
for (int k=0;k<I;k++){
    // 打印第 j 列
    for (int j = 1; j <=(2*I-1); j++) {
        // 当满足条件时 打印 *  否则打印空格
        if((I-k)<=j&&j<=(I+k)){
            System.out.print("*");
        }else {
            System.out.print(" ");
        }
    }
    System.out.println("");
}

因为所有输出结果都是一行一行打印的,所以我们只需要思考每一行中什么时候应该打印星号,什么时候打印空格

方法

定义

方法就是类函数,最常见的就是程序入口的 main 方法,下面是一个计算两数之和的简单方法

// public、static是修饰符 int是返回值类型,没有则是void addNum是函数名
public static int addNum(int a,int b){
    return a+b;
}
// 调用
int c = addNum(3,4);

某方法在读取到 return 语句时,该方法就会结束然后返回值

方法调用就是通过对象名.方法名

方法重载

在某个类中定义了多个方法名相同的方法,但是他们的参数数量不同或类型不同或顺序不同,就认定为不同方法,这就叫方法重载

参数顺序不同

public static int add(int a,float b){}
public static int add(float a,int b){}

形参类型不同

public static int add(int a,int b){}
public static int add(float a,int b){}

参数个数不同

public static int add(int a,int b){}
public static int add(int a,int b,int c){}

可变参数

因为 java 函数要求形参和实参的数量和类型都要匹配,但是有些时候需要传入的参数不确定,比如使用一些命令行工具可传入多个参数,对于这种不完全匹配的情况可以使用可变参数

 public static void test(double... numbers){}

递归

重复调用自身知道达到某一条件退出

public static long f(long n){
    if(n==1){
        return 1;
    }else {
        return n*f(n-1);
    }
System.out.println(f(25));

求阶乘的函数,返回f(n)=n*f(n-1),直到n=1停止,不推荐使用递归调用,因为调用程序需要不断压栈,可能导致程序溢出

数组

定义:相同类型数据的有序集合,类型必须相同,每个数据称作数组元素,可以通过下标访问

dataType[] a1;    // dataType[] 代表数组数据的类型 int、String...
dataType a2[];    // 在变量名后加中括号 非常不推荐
int[] nums = new int[10];   //初始化数组大小 动态初始化&默认初始化
int[] a = {1,2,3,4,5};      //静态初始化

需要定义数组的初始大小

nums[0] = 1;     // 赋值 有默认值
nums[5] = 100;
System.out.println(nums[5]);  //通过下标取值 大于范围会越界

多维数组

简单来说就是数组的元素还是数组

int[][] array = {{1,2,7},{2,3,5},{3,4,6},{4,5,9}}
array[0]-->{1,2}
array[0][1]-->2
array[2][2]-->6
int[][][] array= {{{1,2}, {1,2}, {5,6}},{{1,2},{5,6},{5,6}},{{1,2},{5,6},{5,6}}};

数组有个常用的 Arrays 类,ctrl+左键即可点击看源码,左侧结构/structure可看到相关方法,方便看源码,很多常用的工具类都是某些开发者写的一些函数,自己也可以开发

在这里插入图片描述

稀疏数组

这是用来压缩数据的一种方法,无论是传输还是存储,数据的压缩都是非常重要的

在这里插入图片描述

主要适用于有用数据比较少,大部分是一些无意义数据的情况,举例就是棋盘对局

然后第一行记录矩阵共有几行几列,几个数据,接下来就记录哪一行哪一列,数据的具体值是多少

面向对象OOP

这里只是初步了解,不做过多讲解

所谓面向对象,就是一种功能分类,首先考虑是宏观层面的,再考虑具体代码实现

本质是:以类的方式组织代码,以对象的形式封装数据

test 软件包下新建一个 Demo05 的 java 类

package test;

public class Demo05 {
    public static String test(){
        return "测试";
    }
}

test 软件包下新建一个 Demo01 的 java 类,调用 Demo05 的 test 方法

package test;

public class Demo01 {
    public static void main(String[] args) {
        System.out.println(Demo05.test());
    }
}

因为是静态函数,在 static main 方法中可以直接以类名.方法名调用,如果是非静态的,需要实例化,而类型就是类名

Demo05 a = new Demo05();
System.out.println(a.test());

静态方法在类存在的时候就存在了,而非静态的方法在实例化之后才存在

构造函数

在使用 new 实例化对象时会调用的方法

public Test(){}

函数名和类名一样,没有返回值,作用就是用来初始化定义一些值

还可以多个构造方法,比如一个有参数,一个没有参数,类似之前说的方法重载,一旦定义有参数的构造方法,就必须定义没有参数的构造方法

public Test(){}
public Test(String name){}

堆栈初步了解

java 中对象时保存在堆中的,数组对象也是在堆中,堆栈是两个比较常用的概念,我们目前只需要知道是辅助程序运行的,用于存放数据,标识运行状态的东西

举个例子,一个 main 函数,实例化一个 pet 类并调用赋值

在这里插入图片描述

堆栈中大致过程示意图(不完全)

在这里插入图片描述

程序无非就是操作一些数据,进行逻辑运算的,在堆中有专门的方法区,用来存放类相关数据,堆中还会存放实例化的对象什么的,栈一般存放方法(执行到哪个方法)和变量引用,然后到堆中去寻找具体的数据和方法,入栈出栈在之前都有接触过

封装

减少暴露在外的数据,我们在之前的一篇 php 反序列化习题的文章接触过就是私有属性

private name = "xiaoming";

无法通过类名.属性名进行赋值调用,但是可以通过类内的 get/set 方法来操作,保证操作在可控范围内,通过 get/set 加属性名进行定义

在这里插入图片描述

继承

继承是指类之间的一种关系,父类子类,子类继承父类,相当于对父类进行扩展

比如有学生类/老师类两个子类,他们都继承自父类-人类,学生类老师类相对于人类变得更具体了,扩展了一些属性和方法,一般使用 extends 关键字

public class Student extends Person{}

java 只有单继承没有多继承,也就是只能有一个父类,子类会拥有父类除了私有的(private)其它全部的属性和方法

在子类构造方法调用父类的构造方法使用 super 关键字,当然,还是不能调用私有属性的

super.test();
super.name;

方法重写和多态

子类如果要重写继承父类的方法,不要加 static 关键字,静态方法在最开始加载,子类的非静态方法重写会覆盖父类的方法,很容易理解,不贴代码了

A extends B
A a = new A();
B b = new A();

A 继承 B 类,两种写法都是可以实例化 A 的,区别在于,父类引用指向子类对象(B b=new A)只能调用子类中重写的父类方法(没有属性的事),不能直接调用子类独有的方法,而子类引用指向子类对象,可以调用自己的所有方法,如果子类重写了某方法,则都会调用子类的方法

当然,也不是不可能,只要将对象进行类型转换就可以调用子类方法了,还是上面的例子,子类 A 中有一个 test 方法

A{
    test(){}
}

调用,引用子类 A 的对象 a 可以直接调用子类方法,而引用父类 B 的对象 b 需要进行类型转换才能调用(之前讲过的强制类型转换,和它很像)

a.test();
((A)b).test();

多态的一个比较大的作用就是解耦,什么意思呢?比如我设计了一个父类 List,还有一些子类,某一天我的一个子类 ArrayList 用不到了,需要修改为 LinkedList,只要修改实例化的子类名称就可以了,比较容易维护

List list = new ArrayList();
List list = new LinkedList();

抽象类

说抽象类呢,它只有方法的名字,没有方法的实现,使用 abstract 关键字定义

public abstract class Action{
    public abstract void dosomething();
}

由继承它的子类进行方法的实现,除非子类还是一个抽象类

接口

Java里面由于不允许多重继承,所以如果要实现多个类的功能,则可以通过实现多个接口来实现

接口由 interface 关键字定义,里面没有方法的实现,只需定义方法的名字,默认都是 public 的抽象类,需要在实现类里面写具体的代码

public interface UserService {
    void add(String name);
    void delete(String name);
}

实现类需要用 implements 关键字定义,Alt+Insert 快捷键插入实现方法

public class UserServiceImpl implements UserService{
    @Override
    public void add(String name) {
  
    }
    @Override
    public void delete(String name) {

    }
}

网上一堆眼花缭乱的什么接口和多继承有什么关系,没怎么看懂,倒是如果有十个接口的方法要实现,可以用所谓的继承在一个类里实现,既然最终都要在类里重写,不知道这一步有什么用,不过这种东西应该都是便于开发维护的东西,以后有了经验自然就知道了,没必要在这里硬抠

内部类

在类内定义类,如何调用?

package test;

public class Outer {
    private int id = 100;
    public void out(){
        System.out.println("外");
    }
    public class Inner{
        public void in(){
            System.out.println("内");
        }
    }
}

实例化外部类,然后再实例化内部类(java中可以直接在类内实例化自己)

package test;
import test.Outer;

public class test {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();
    }
}

还可以调用外部类的私有属性,和私有方法

private int id = 100;
private void test(){
    system.out.println("私有方法");
}
// 内部类调用
public class Inner{
    public void in(){
        System.out.println(id);
        test();
    }
}
//实例化调用
inner.in();

我觉得这个做题可能会用到

异常

程序经常会遇到各种各样的bug导致不能正常运行,这时就需要引入异常捕获机制,让程序更稳定的运行,即使有一些错误,也能照跑不误

举例:try 尝试执行代码块内的语句,如果catch语句捕捉到错误则执行catch代码块的语句,报错类型是根据语句决定的

int a = 2;
int b = 0;
try{
    System.out.println(a/b);
}catch(Exception e){
    System.out.println("xx");
}finally {
    System.out.println("fin");
}

finally 是不管是否报错,最终都会执行的语句

throw、throws一般是在方法里使用的,这里就不说了

自定义异常

自带的异常类不能满足我们的需求的时候可以自己写,java的很多东西都是可以自定义的,实现自定义异常类需要继承 Exception 类或其子类,如果自定义运行时异常类需继承 RuntimeException 类或其子类,这里不做讲解

练习

运行项目

将源码拖到编译器中,Maven 会自动加载需要的依赖包,然后一般是修改数据库配置等,再一键编译运行,这和 php 区别是比较大的

在这里插入图片描述

反编译 class 文件

直接将class文件拖到编译器,会直接显示反编译的文件

在这里插入图片描述

注意编码,可以看到 case 的值并不是明文,这是hashcode,通过它来指代

看完本套课程,印象最深的就是那句:程序,是对世界的建模!瞬间高大上起来了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值