一、垃圾回收机制
1、为什么要进行垃圾回收机制
如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收。除非内存无限大,我们可以任性的分配而不回收,但是事实并非如此。所以,垃圾回收是必须的。
2、哪些内存需要回收?
哪些内存需要回收是垃圾回收机制第一个要考虑的问题,所谓“要回收的垃圾”无非就是那些不可能再被任何途径使用的对象。那么如何找到这些对象?(如何判断一个对象是否可以被回收)
3、如何判断一个对象是否可以被回收
问:垃圾收集器有哪几种?
垃圾收集器底层原理剖析?
垃圾收集器的算法,优化?
(1)引用技术算法
这个算法的实现是,给对象中添加一个引用计数器,每当一个地方引用这个对象时,计数器值+1;当引用失效时,计数器值-1。任何时刻计数值为0的对象就是不可能再被使用的。引用计数为 0 的对象可被回收。正因为循环引用的存在,因此 Java 虚拟机不使用引用计数算法。
package com.baidu.GC;
public class ReferenceCountingGC {
private Object instance = null;
private static final int _1MB = 1024 * 1024;
/** 这个成员属性唯一的作用就是占用一点内存 */
private byte[] bigSize = new byte[2 * _1MB];
public static void main(String[] args) {
ReferenceCountingGC objectA = new ReferenceCountingGC();
ReferenceCountingGC objectB = new ReferenceCountingGC();
objectA.instance = objectB;
objectB.instance = objectA;
objectA = null;
objectB = null;
System.gc();
}
}
二 、JAVA跨平台原理
1、JAVA
Java是可以跨平台的编程语言,那我们首先得知道什么是平台,我们把CPU处理器与操作系统的整体叫平台。
C语言是编译执行的,编译器与平台相关,编译生成的可执行文件与平台相关;
Java是解释执行的,编译为中间码的编译器与平台无关,编译生成的中间码也与平台无关(一次编译,到处运行),中间码再由解释器解释执行,解释器是与平台相关的,也就是不同的平台需要不同的解释器。
在执行的时候,表面上我们调用的是Java.exe,实际上我们在调用java.exe的时候,会去动态调用JVM虚拟机,JVM将字节码文件一行一行的解释成为当前操作系统认识的可执行文件的格式,因此,java是一个“解释型”语言。
Java是编译型的语言,也是解释型的语言,现在明白了,编译型的语言是因为java的你可以说它是编译型的,因为所有的Java代码都是要编译的,.java不经过编译就什么用都没有
而解释型因为java代码编译后不能直接运行,它是解释运行在JVM上的,而JVM的执行方式是把字节码文件一行一行的解释成当前平台认识的可执行文件,所以它是解释运行的,那也就算是解释类型的了。
2、C语言的跨平台原理
那么c语言是不是跨平台的语言呢,实际上我们所说的跨平台,是指编译后的文件是否可以跨平台,从这个角度来讲,c语言不是跨平台的,但是网上有很多人讲c语言是跨平台的语言,这里指的是因为不同平台有对应的编辑器,是源文件跨平台.
3、效率问题
我们回到两个语言跨平台的原理,java把程序先编译成字节码,然后通过对应的JVM进行一句一句的解释执行,而c语言,则直接通过对应平台的解释器翻译成直接可以在对应平台是执行的文件,从这可以看出,c语言的执行效率是快于java的。
三、JAVA的常用DOS命令
(1)控制命令台:
win+R
(2)切换盘符
C: D: E: //大小写都可以
(3)显示详细信息 dir
dir
(4)改变当前目录
cd
(5 ) 当前目录和上一层目录
cd . //当前目录
cd .. //上层目录
(6)清屏
cls
(7)补全命令 TAB
cd s+TAB
(8)创建/删除一个目录
md a // make dir 创建目录
rd a // remove dir 删除目录
(9)复制文件夹
copy demo.txt a\test.txt
(10)删除文件
del 文件名
四、JDK和JRE
JRE(Java Runtime Enviroment) 是 Java 的运行环境。。面向 Java 程序的使用者,而不是开发者。如果你仅下载并安装了 JRE,那么你的系统只能运行 Java 程序。
JDK(Java Development Kit) 又称 J2SDK(Java2 Software Development Kit),是 Java 开发工具包,它提供了 Java 的开发环境(提供了编译器 javac 等工具,用于将 java 文件编译为 class 文件)和运行环境(提 供了 JVM 和 Runtime 辅助包,用于解析 class 文件使其得到运行)。如果你下载并安装了 JDK,那么你不仅可以开发 Java 程序,也同时拥有了运行 Java 程序的平台。JDK 是整个 Java 的核心,包括了 Java 运行环境(JRE),一堆 Java 工具 tools.jar 和 Java 标准类库 (rt.jar)。
五、JAVA基本语法
1、变量
(1)变量的概念
在内存中分配一块地址,用来存储各种不同类型的数据。
(2)变量的类型
int a, b, c; // 声明三个int型整数:a、 b、c
int d = 3, e = 4, f = 5; // 声明三个整数并赋予初值
byte z = 22; // 声明并初始化 z
String s = "runoob"; // 声明并初始化字符串 s
double pi = 3.14159; // 声明了双精度浮点型变量 pi
char x = 'x'; // 声明变量 x 的值是字符 'x'。
变量在声明时候可以没有初始值,但是在使用的时候必须赋予初始值。
JDK10之后,有一种变量声明方式,VAR,但需要赋值,会推断其属于什么类型。
var 变量 = 值
(3)变量的范围
①局部变量
局部变量是在方法、构造函数或块内部声明的变量,它们在声明的方法、构造函数或块执行结束后被销毁,局部变量在声明时需要初始化,否则会导致编译错误
public void exampleMethod() {
int localVar = 10; // 局部变量
// ...
}
②实例变量
实例变量是在类中声明,但在方法、构造函数或块之外,它们属于类的实例,每个类的实例都有自己的副本,如果不明确初始化,实例变量会被赋予默认值(数值类型为0,boolean类型为false,对象引用类型为null)。
public class ExampleClass {
int instanceVar; // 实例变量
}
③静态或类变量
类变量是在类中用 static 关键字声明的变量,它们属于类而不是实例,所有该类的实例共享同一个类变量的值,类变量在类加载时被初始化,而且只初始化一次。
public class ExampleClass {
static int classVar; // 类变量
}
④参数变量
参数是方法或构造函数声明中的变量,用于接收调用该方法或构造函数时传递的值,参数变量的作用域只限于方法内部。
public void exampleMethod(int parameterVar) {
// 参数变量
// ...
}
2、关键字
(1)48个关键字
(2)保留字
goto | const |
(3)特殊直接量
true | false | null |
3、八种基本数据类型
4、数据类型的转换
(1)自动转换
小的数据类型向大的数据类型转换,或者整数类型转换成浮点数类型,都是自动转换的。
byte->short->int->long
public class Main {
public static void main(String[] args) {
// 当文本光标位于高亮显示的文本处时按 Alt+Enter,
// 可查看 IntelliJ IDEA 对于如何修正该问题的建议。
System.out.println("Hello and welcome!");
byte egg = 10;
int x = egg;
System.out.println(x);
}
}
(2)强制转换
大的数据类型转换成小的数据类型则要强制转换。
long->int->short->byte
public class Main {
public static void main(String[] args) {
// 当文本光标位于高亮显示的文本处时按 Alt+Enter,
// 可查看 IntelliJ IDEA 对于如何修正该问题的建议。
System.out.println("Hello and welcome!");
int egg = 10;
byte x = (byte)egg;
System.out.println(x);
}
}
5、基本算数运算
加:+
减:-
乘:×
除法:/
求余(取模):%
注意:
JAVA默认的整数类型是INT
short a = 10;
short b = 20;
short c = (short)(a+b)
注意:
任何的数据类型和字符串使用+运算,+都表示连字符,最后得到的结果都是String类型。
自增自减
① i++ :
i=10;
int j=i++; //先把i的值赋给j,i再+1
// j=10
②i-- :
i=10;
int j=i--; //先把i的值赋给j,i再-1
// j=10
③++i :
i=10;
int j=i++; //i先+1再把值赋给j
// j=11
④--i :
i=10;
int j=i--; //i先-1再把值赋给j
// j=9
public class Ari {
public static void main(String[] args) {
int i=10;
int j=i++; //j=10 i=11
int m=i+++j; //m=21 i=12 j=10
int n=j--+m; //n=31,i=12,j=9,m=21
System.out.println(i);
System.out.println(j);
System.out.println(m);
System.out.println(n);
}
}
6、关系运算符
< > == <= >= !=
import java.util.Scanner;
public class rel {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入两个数字比较:");
int x=scanner.nextInt();
int y=scanner.nextInt();
boolean b=x>y;
System.out.println(x+"是否大于"+y+":"+b);
}
}
7、逻辑运算符
与运算 A&B :同时为真,则结果为真;
或运算 A|B :其中一个为真,则结果为真;
非运算 !A:A必须是boolean类型;
短路与运算 A&&B:和与运算的规则相同,但左侧表达式为False,则直接返回结果为False;如果左侧表达式为True,则右侧运算后返回结果;
短路或运算 a||B:和或运算的规则相同,但如果左侧表达式为True,则右侧不进行运算,直接返回True;如果左侧为False,则右侧计算后再返回结果;
异或运算 A^B:相同为False,不同为True。
注意:
如果要求右侧表达式,不管在什么情况下,都要计算到,则不能用短路。
8、按位运算符(效率高)
首先转换为二进制
按位与:
按位或 :
按位异或
按位取反:
9、移位运算符(效率高)
①有符号位
左移位运算 y<<2:整体将二进制位向左侧移动移位,右侧补0,左移动1位,相当于乘2;(符号不影响)
右移位运算:使用>>符号表示,整体将二进制向右移位,左侧补0,右移动1位,相当于除以2。(符号不影响)
如果移动的位数超过所能表述的长度,则采用求余的方式计算;
如:如果移动32位时候,32%32=0;
如果移动33位的时候,33%32=1.
②无符号位
- 无符号右移位运算:用>>>符号,不考虑正负数的问题;
- 正数移动和右移位相同。
- 负数移动不考虑最左侧负号的问题,意义不大。
10、赋值运算符
= :将右侧的值赋值给左侧变量。
+= :
-= :
……
<<= : 在变量自身上作左移运算 x<<=2
>>= : 在变量自身上作右移运算 x>>=2
>>>=: 在变量自身上做无符号右移运算 x>>>=2
……
11、条件运算符(三元运算符)
x?y:z
表达式1?表达式2:表达式3
x必须位boolean类型的值,如果x为True,则整个表达式取值为y,否则为z。
注意:
不允许 表达式1?表达式2:表达式3 单独存在。
int x=10;
int y=5;
int max=x>y?x:y;
12、优先级
13、从键盘接收数据
导入工具包
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入第一个数字");
double x=scanner.nextDouble();
System.out.println("请输入第二个数字");
double y=scanner.nextDouble();
System.out.println("输出结果");
double z=x+y;
System.out.println(z);
}
}
14、字符类型
①java虚拟机JVM,定义了boolean,但是没有专门的虚拟指令。
②在JAVA语言中,对boolean值操作时替换成int类型数据,占4字节(32位),且只有一位是有效的。
③布尔类型数组,转成byte数组,数据占1字节(8位)。
15、字符串和转义字符
- String不是基本数据类型,是一种引用类型;
- 使用String来声明;
- 特殊的转义字符。
public class String_test {
public static void main(String[] args){
String x = "你好!\nJava!"; //String是一个类
System.out.println(x);
}
}
16、字面量值和常量
字面量:表达的信息如字面所示,程序源码直接给出的一个值,如整数、浮点数和字符串。
常量:不可变的,字面值常量,定义的常量。
//使用final关键字来修饰,不可以重新被赋值
public class ConstTest {
public static void main(String[] args) {
final double pi=3.141526;
}
}
17、编码风格 (驼峰式编码风格)
类名:
- 1个单词组成,首字母大写,后面全小写,如Student Teacher
- 2个或2个以上单词组成,每个单词首字母大写,其他小写,如TeacherName
变量、包、方法名字:
- 1个单词组成,全小写 a b c name
- 2个或两个单词以上组成,第一个单词全部小写,后面每个单词首字母大写
- studentName studentFirstNanme
常量:
- 一个单词组成,全部大写,PI
- 2个或2个以上单词组成,全部大写,中间建议使用下划线分隔。USER_NAME
18、程序结构_分包概念
(1)包的概念
包相当于磁盘下面的一个文件夹。
命名:公司互联网地址的方向写法。如:www.itszb.com,则命名为
|--com.itszb.项目名.模块名
|----java类
在程序中,会出现打包语句:
//package必须在最上边的代码
package.com.coder.xxxx
(2)选择结构
注意:
if...if....
if...else...
这两个是不同的,要注意易错 。
① i f_else
package com.coder.if_test;
import java.util.Scanner;
public class if_Demo {
public static void main(String[] args) {
//从键盘输入一个整数,判断其是否是偶数
Scanner scanner=new Scanner(System.in);
System.out.println("请输入你想要判断的数字:");
int x=scanner.nextInt();
if (x%2==0) {
System.out.println(x+"是偶数!");
}else{
System.out.println(x+"不是偶数!");
}
}
}
猜硬币正反面游戏
package com.coder.if_test;
import java.util.Scanner;
public class if_Else {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
//猜硬币的正反面
double x=(int)(2*Math.random()); //random 0-1之间的小数
System.out.println("请猜正反面(0:反面 1:正面):");
int y=scanner.nextInt();
if (x==y){
System.out.println("恭喜你正确了");
}else{
System.out.println("很遗憾你错误了");
}
if (x==1) {
System.out.println("硬币是正面");
}else{
System.out.println("硬币是反面");
}
}
}
② i f_elseif_else
血型判断
package com.coder.if_test;
import java.util.Scanner;
public class if_Elseif_If {
public static void main(String[] args) {
Scanner scaner=new Scanner(System.in);
System.out.println("请输入你的血型(0:A型 1:B型 3:O型 4:AB型):");
int c=scaner.nextInt();
if (c==1) {
System.out.println("你是A型血");
}else if (c==2) {
System.out.println("你是B型血");
}else if (c==3) {
System.out.println("你是O型血");
}else if (c==4) {
System.out.println("你是ab型血");
} else {
System.out.println("输入错误!");
}
}
}
天气判断
package com.coder.if_test;
import java.util.Scanner;
public class if_Elseif_Demo {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("请你输入您的出生年份");
int month=scanner.nextInt();
if (month==12 || month==1 || month==2) {
System.out.println("冬天出生!");
}else if(month>=3 && month<=5){
System.out.println("春天出生!");
}else if(month>=6 && month<=8){
System.out.println("夏天出生!");
}else if(month>=9 && month<=11){
System.out.println("夏天出生!");
} else {
System.out.println("月份输入错误!");
}
}
}
条件分支嵌套
比较大小
package com.coder.nested;
import java.util.Scanner;
public class if_Nested {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入三个数字比较大小!");
int a = scanner.nextInt();
int b = scanner.nextInt();
int c = scanner.nextInt();
if (a > b) {
if (a > c) {
System.out.println(a + "最大");
} else {
System.out.println(c + "最大");
}
} else {
if (b > c) {
System.out.println(b + "最大");
} else {
System.out.println(c + "最大");
}
}
}
}
石头剪刀布游戏
package com.coder.nested;
import java.util.Scanner;
public class Game {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请出拳(0:石头 1:剪刀 2:布):");
int x = scanner.nextInt();
int y = (int)(3*Math.random());
if (y==0) {
System.out.println("系统出:石头");
if (x==0) {
System.out.println("平局!");
} else if (x==1) {
System.out.println("你输了");
} else if (x==2) {
System.out.println("你赢了");
} else {
System.out.println("你出的不对!");
}
} else if (y==1) {
System.out.println("系统出:剪刀");
if (x==0) {
System.out.println("你赢了");
} else if (x==1) {
System.out.println("平局");
} else if (x==2) {
System.out.println("你输了");
} else {
System.out.println("你出的不对!");
}
} else if (y==2) {
System.out.println("系统出:布");
if (x==0) {
System.out.println("你输了");
} else if (x==1) {
System.out.println("你赢了");
} else if (x==2) {
System.out.println("平局");
} else {
System.out.println("你出的不对!");
}
}
}
}
③switch分支
switch(变量X) X的数据类型支持:byte,short,int,char,String,enum枚举。
前面四个数据类型是老版本支持的。
package com.coder.Switch_Demo;
import java.util.Scanner;
public class Demo1 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int x= scanner.nextInt();
switch (x) {
case 1:
System.out.println("走1号路线");
break;
case 2:
System.out.println("走2号路线");
break;
case 3:
System.out.println("走3号路线");
break;
default:
System.out.println("另寻他路");
break;
}
System.out.println("可以走出来!");
}
}
也可以简洁写月份
package com.coder.Switch_Demo;
import java.util.Scanner;
public class Bithday {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("Please enter your month of birth");
int x=scanner.nextInt();
switch (x) {
case 12:
case 1:
case 2:
System.out.println("winter");
break;
case 3:
case 4:
case 5:
System.out.println("spring");
break;
case 6:
case 7:
case 8:
System.out.println("summer");
break;
case 9:
case 10:
case 11:
System.out.println("autumn");
break;
default:
System.out.println("Please enter the right month of birth!");
}
}
}
计算器
package com.coder.Switch_Demo;
/*
@author JingPeng
* @project Java Project
* @package_name PACKAGE_NAME
* @data 2024/6/4
*/
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("计算器!");
System.out.println("please enter the first number:");
int x=scanner.nextInt();
System.out.println("please enter the later number:");
int y=scanner.nextInt();
System.out.println("Please enter an operator:");
String op=scanner.next();
String results="";
switch (op){
case "+":
results=(x+"+"+y+"="+(x+y));
break;
case "-":
results=(x+"-"+y+"="+(x-y));
break;
case "*":
results=(x+"*"+y+"="+(x*y));
break;
case "/":
if (y!=0){
results=(x+"/"+y+"="+(x/y));
}else {
results="The divisor cannot be 0!";
}
break;
default:
System.out.println("Please enter the right operator!");
break;
}
System.out.println(results);
}
}
④while循环(打怪)
package com.coder.While_Test;
public class game1 {
public static void main(String[] args) {
// 打怪游戏 玩家300血量,怪物500血量
// 回合制游戏, 玩家攻击力为5-8之间,怪物的攻击力3-5之间
// 直到有一方血量小于等于0,游戏结束
int i=0;
int p=300;
int q=500;
while(true){
i++;
System.out.println("-------------------------------------------------");
System.out.println("第"+i+"回合!");
int x=(int)(Math.random()*(8-5)+5); //玩家攻击力
int y=(int)(Math.random()*(5-3)+3); //怪物攻击力
//萨满攻击
q=q-x;
System.out.println("萨满攻击暗黑魔王,暗黑魔玩血量-"+x+",攻击力为"+x+",血量变为:"+(q));
if (q<=0){
break;
}
//魔王攻击
p=p-y;
System.out.println("暗黑魔王萨满攻击,玩家血量-"+y+",攻击力为"+y+",血量变为:"+(p));
if (p<=0){
break;
}
}
System.out.println(q<=0?"萨满胜利!":"暗黑魔王胜利!");
}
}
⑤do...while
无论如何,都要先执行一次循环。
猜价格游戏
package com.coder.Do_While;
import java.util.Scanner;
public class game1 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
//猜数字的游戏
//有一件的商品就,价格是1-100之间的数字,系统会提示大或小
//直到用户猜中
int y=(int)(Math.random()*100+1);
int x;
int i=0; //计数器
do{
System.out.println("-------------------");
System.out.println("请输入价格:");
x=scanner.nextInt();
if (x<y){
System.out.println("猜小了!");
} else if (x>y) {
System.out.println("猜大了");
} else{
System.out.println("正确!商品的价格为"+y+"元!");
break;
}
i++;
} while (true);
if (i<=3) {
System.out.println("你是个天才!");
} else if (i<=7) {
System.out.println("不傻,但也不聪明");
} else {
System.out.println("大笨蛋!");
}
}
}
⑥for循环
逢7过
package com.coder.For_Test;
import java.util.Scanner;
public class test1 {
public static void main(String[] args) {
// 100内的数字逢7过
Scanner scanner=new Scanner(System.in);
// 第一个人键盘输出1-10之间的数,表明开始。
int x=scanner.nextInt();
//控制第一个数必须是1-10之间
while (x <= 0 || x > 10) {
System.out.println("请重新输入:");
x = scanner.nextInt();
}
if (x==7) {
System.out.println("过");
x++;
}
for (;x<=100;x++){
if (x%7==0 || x/10==7 || x%10==7){
System.out.println("过");
}else {
System.out.println(x);
}
}
}
}
快速生成for循环的方式
fori
for (int i = 0; i < ; i++) {
}
100.fori //正向循环
for (int i = 0; i < 100; i++) {
}
100.forr //反向循环
for (int i = 100; i > 0; i--) {
}
for循环变量的初始,最好在for循环内声明,遵循迪米特法则
// 迪米特法则:don‘t talk to stranger
// 最少知识原则:耦合度越低,程序越容易扩展,设计越合理
// 高内聚,低耦合
⑦循环嵌套解决搬砖问题
假设有36块砖,由36个人搬走,男人一次搬4块转,女人一次搬3块砖,2个小孩抬一块砖。
男:x人
女:y:人
小孩:z个
4x+3y+0.5z=36
x+y+z=36
package com.coder.For_Test;
public class Ban_Zhuan {
public static void main(String[] args) {
for (int x = 1; x <= 9; x++) {
for (int y = 1; y <=12; y++) {
for (int z = 2; z <= 36-x-y; z+=2) {
if((4*x+3*y+0.5*z)==36 && (x+y+z==36)){
System.out.println("男人:"+x);
System.out.println("女人:"+y);
System.out.println("小孩:"+z);
}
}
}
}
}
}
⑧带标号的break continue
public class Break_Continue {
public static void main(String[] args) {
out: //带标号的break,代表打破的是out这个循环!!
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 5; j++) {
if (j==4){
continue out; // 结束本次循环,从标号循环的位置执行下一次循环
// break out; // 退出标号的循环
}
System.out.println("j: "+j);
}
}
}
}
break out 代表打破out这个所有循环,如果用continue,则代表打破外层的一次循环,从外层的下一次循环开始。
19、引用类型内存模型
(1)数组
①是一种容器。是一组相同类型的数据的组合,将这一组数据做统一管理。
②数组是一种引用数据类型,在数组中,可以存储基本数据类型,也可以存储引用数据类型。
③引用数据类型:类、String、数组、接口、枚举、注释
在JVM中,把内存分为,堆内存、栈内存。
①方法中的变量,如果是基本数据类型,则存储在栈内存中。
②如果是引用类型,内容存储在堆内存中,在栈内存中,有一个变量指向内存地址(引用)
声明(数组刚刚声明,是不可以直接使用的):
ublic class test1 {
public static void main(String[] args) {
int[] x;
double[] y;
}
}
(2)数组的创建
①静态创建数组
数组的下标:每个数组中的元素,对外有一个同一的名字(数组的名字),为了区分每一个元素,使用下标(索引)的方式,下表碧血是整数,并且从0开始。
且必须要给定数组的长度,且不能再改变。
第一种写法:
//数组的创建 静态创建数组 动态创建数组
//数组的类型[] 数组名
int[] x;
x=new int[]{12,23,34}; //new关键字,在堆内存中申请开辟一块新的空间地址。
第二种写法:
double[] y={12.4,22.3,444.2}; //一次成形
②动态创建数组
语法:
//数组类型[] 数组名=new 数组类型[长度(数组中存储元素的个数)]
int[] x=new int[5];
数组中的元素会有默认值,基本数据类型中,氨基苯数据类型默认值(整0,浮点0.0,字符类型\u0000,布尔类型false,引用类型(string null)。
③数组的打印
数组的属性
double[] y={12.4,22.3,444.2};
for (int i = 0; i <= y.length-1; i++) {
System.out.println(y[i]);
}
增强循环(推荐)
//JDK5版本之后的一种增强循环(只针对于数组、集合)
//for(数据类型 每次从数组中取出元素存放到一个临时变量:数组名)
double[] x={11.1,2323.1,3332.1,4444.1,3232.5};
for (double a:x){
System.out.println(a);
}
快捷键
x.for
// 快捷键1
for (double a : x) {
}
x.fori
// 快捷键2 正向
for (int i = 0; i < x.length; i++) {
}
x.forr
//快捷键3 反向
for (int i = x.length - 1; i >= 0; i--) {
}
//前两中比较常见
④数组的合并
public class Array_Test3 {
public static void main(String[] args) {
int[] x={1,23,42,55};
int[] y={123,33,43,52};
int[] z=new int[x.length + y.length];
for (int i = 0; i < z.length; i++) {
if(i<x.length){
z[i] = x[i];
}else{
z[i] = y[i-x.length];
}
}
for (int i : z) {
System.out.println(i);
}
}
}
⑤数组求和_平均值_极值
public class ScoreArray {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int len;
System.out.println("请输入学生的人数:");
len=scanner.nextInt();
double[] y=new double[len];
for (int i = 0; i < len; i++) {
System.out.println("请输入学生的分数:");
y[i]=scanner.nextDouble();
}
// 统计总成绩和平均成绩
double sum=0,average;
for (double v : y) {
sum+=v;
}
average=sum/len;
System.out.println("sum:"+sum+"\taverage:"+average);
// 求出最高分和最低分
double max=y[0];
for (int i = 1; i < y.length; i++) {
if (y[i]>max) {
max=y[i];
}
}
System.out.println("max:"+max);
}
}
⑥选择排序
先思考内层循环怎么循环的,然后外循环嵌套,改变变量。
时间复杂度:
N+(N-1)+...+1
最终时间复杂度为:O(n^2),空间复杂度O(1)。
public class Array_select {
// 选择排序法
public static void main(String[] args) {
int[] a={15,7,12,2,8};
for (int i = 0; i < a.length-1; i++) {
// 每一轮只做一次交换,也有可能不交换
int minIndex=i; //认为第一个是最小的
for (int j = i+1; j < a.length; j++) { //从第i+1个开始
if (a[j] < a[minIndex]){
minIndex=j;
}
}
// 交换处理
if (minIndex!=i){
int temp=a[i];
a[i]=a[minIndex];
a[minIndex]=temp;
}
System.out.println("第"+(i+1)+"轮排序");
for (int i1 : a) {
System.out.print(i1+"\t");
}
System.out.println();
}
}
}
public class Bubble {
public static void main(String[] args) {
int[] x={15, 7, 12, 2, 8, 16};
for (int i = 0; i < x.length-1; i++) {
// 每一轮从头开始,与紧挨着的后一位比较大小
for (int j = 0; j < x.length-1-i; j++) { // x.length-1-i实际上是前一轮比较过的无需再比较
if (x[j] > x[j+1]){
int temp=x[j];
x[j]=x[j+1];
x[j+1]=temp;
}
}
}
for (int i : x) {
System.out.print("\t"+i);
}
}
}
最终时间复杂度为:O(n^2),空间复杂度O(1)。
⑦快速排序
public class quicksort {
public static void main(String[] args) {
int[] x=new int[10000];
for (int i = 0; i < x.length; i++) {
x[i]=(int)(Math.random()*100000);
}
long t1=System.currentTimeMillis();
Arrays.sort(x);
long t2=System.currentTimeMillis();
System.out.println(t2-t1);
}
}
(3)Arrays工具类(Arrays.toString)
public class tools {
public static void main(String[] args) {
int[] x={15, 7, 12, 2, 8, 16};
Arrays.sort(x);
String s = Arrays.toString(x);
System.out.println(s);
}
}
(4)Arrays工具类(Arrays.fill)
public class ArrayFill {
// 对数组元素进行填充
public static void main(String[] args) {
int[] x=new int[5];
System.out.println(Arrays.toString(x));
//用法1
Arrays.fill(x,200); //填充200 ,将数组中的所有的值,进行替换填充处理。
//无论原来的值如何
System.out.println(Arrays.toString(x));
//用法2
//在程序中出现前一个和后一个,规定起始位置包含,终止位置不包含。
x[2] = 500;
x[3] = 333;
x[4] = 111;
Arrays.fill(x, 0, 3,200);
System.out.println(Arrays.toString(x));
}
}
(5)Arrays工具类(二分查找)binarySearch
前提:数组必须进行排序。
①先找到中间位置(通过低值和高值,找到中间值)
②那要找的值进行比较,如果找到,直接返回下标,
如果当前值比目的值大,则把高值改为当前值。
如果当前值比目的值小,则把低值改为当前值。
public class binarySearch {
public static void main(String[] args) {
int[] x={15, 7, 12, 2, 8, 16};
Arrays.sort(x);
// 返回的是下标值
System.out.println(Arrays.toString(x));
int i=Arrays.binarySearch(x,2);
System.out.println(i);
}
}
要是返回负数,则表明没有,或者没有排序。
(6)Arrays工具类 copyOf_copyOfRange
public class CopyOF {
public static void main(String[] args) {
int[] x={12, 323, 21, 52, 12, 52};
// 从0开始,copy五个数
int[] y= Arrays.copyOf(x,5);
System.out.println(Arrays.toString(y));
//不包括5
int[] z=Arrays.copyOfRange(x,1,5);
System.out.println(Arrays.toString(z));
//参数1:原数组 参数2:从原数组到那个小标开始赋值, 参数3:复制到的目标数组
//参数4:从目标数组的那个小标位置开始放入 参数5:赋值原数组多长
}
}
(7)Arrays工具类 equals_copare方法
public class equal_compare {
public static void main(String[] args) {
int[] x={15, 7, 12, 2, 8, 16};
int[] y= Arrays.copyOf(x, x.length-1);
// 比较两个数组的值是否完全相同,
// 如果相同true,否则false
System.out.println(Arrays.equals(x,y));
}
}
(8)数组的数组(二维数组)
java是没有二维以上的数组的,数组的第一位元素指向的堆内存地址,又是一个数组,实现二维数组的效果。
public class Arrays_two {
public static void main(String[] args) {
//声明
//方法1
int[][] a = {{1, 2, 3},{4, 5, 6},{7, 8, 9}};
//方法2
int[][] b = new int[][]{{1, 2, 3},{4, 5, 6},{7, 8, 9}};
//方法3
int[][] c=new int[3][];
// System.out.println(c[0][1]); //此时二维数组的第二维并没有初始化,
// // 引用时会出现空指针问题
int[] array0 = {12,23};
int[] array1 = {34,45,67};
int[] array2 = {22,33,44};
c[0] = array0;
c[1] = array1;
c[2] = array2;
// 第一种打印
for (int i = 0; i < c.length; i++) {
for (int j = 0; j < c[i].length; j++) {
System.out.print(c[i][j]+"\t");
}
System.out.println();
}
//第二种打印
//每一个数组里边还存放了一个数组
for (int[] ints : c) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
}
}
20、方法
好处:
(1)方法的定义和调用
- 实现对相同代码的复用;
- 是程序逻辑清洗
- 实现细粒度设计
public class test1 {
public static void main(String[] args) {
attack("小兵"); //实参
}
//方法声明后不能够自己运行
//必须由主方法或其他方法进行调用
//调用方法 : 方法名([实参])
public static void attack(String type){ //形参
System.out.println(type+"攻击防御塔");
System.out.println("生产");
System.out.println("前进");
System.out.println("瞄准");
System.out.println("开炮"+5);
}
}
(2)方法返回值
- 方法传入的实参必须和形参相对应
- 方法返回的数据类型必须和方法声明的数据类型相同或兼容
public class test2 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int x = scanner.nextInt();
int y = scanner.nextInt();
int z = add(x, y);
System.out.println(z);
}
public static int add(int x, int y){
int z = x + y;
return z;
}
}
(3)方法调用和内存结构
- 方法可以由主方法调用,也可以有别的方法调用,但是方法之间不可以互相调用(a->b b->a 会产生StrackOverflowError)
- 方法编写完成,没有被掉用的时候,在方法区(JVM)中存放。
- 当调用方法时候,方法进入到栈内存中执行。
(4)方法参数传递
java 按值传递
基本数据类型按值传递!而不是参数;
引用数据库类型传递:传递的是存储的引用地址(可以修改对应地址的值),有一种特殊情况,字符串String,传递的是字面值。
(5)方法重载
定义:在一个类中, 使用相同的方法名字,定义多个不同的方法的机制
要求:
1.方法名必须相同
2.访问修饰符可以相同,也可以不相同
3.返回值类型可以相同,也可以不相同
4.参数列表必须不同(不区分形参名称)
1)参数的类型不同
2)参数的个数不同
3)参数的顺序不同(不推荐)
案例:计算圆形、长方形、正方形的面积
public class test3 {
// 计算圆形、长方形的面积
public static void main(String[] args) {
}
public static double cal_area(double r){
double s;
s = 3.14*r*r;
return s;
}
public static double cal_area(double l, double w){
double s;
s = l*w;
return s;
}
}