欢迎来到我的主页:【一只认真写代码的程序猿】
本篇文章收录于专栏【Java入门学习】
如果这篇文章对你有帮助,希望点赞收藏加关注啦~
目录
Java和C的区别
- C是面向过程,按行执行;Java是面向对象,按模块执行。
- 面向过程(Procedure Oriented):要实现一件事情,首先将事情拆分成多个步骤,然后按照一定的顺序执行。
面向对象(Object Oriented ):首先将事物抽象成对象的概念,然后给对象赋予属性和方法,接着让每个对象去执行他们自己的方法。 -
单文件的编译时间Java更快。
-
C语言可以直接操作内存,java不能。
-
C语言可以封装动态库,java不能
-
C语言不容易跨平台,java容易实现跨平台。
Java只需要编译一次,就可以在不同的平台上面运行,但是C如果在windows系统上编译生成的文件只能在windows上运行,如果在Linux需要重新编译。 -
举个栗子,买电脑
面向过程实现:我要买一台电脑-->我要了解我需要什么样的电脑-->了解电脑的各个参数-->去实体店里买电脑-->砍价-->买到电脑
面向对象实现:我要买电脑-->找个人帮我买-->他买好之后回来给我了 -
面向对象的优点:
易维护、质量高、效率高、思考方式接近于生活、易扩展。
-
三大特性
封装:将对象的属性和操作合并成一个独立的整体,同时会尽量隐藏对象的内部细节。继承:从a类中派生出b类,b类能吸收a类的数据属性和行为并扩展出新的能力。
多态:同一个行为,具有多个不同的表现形式。也就是同一个接口,可以用不同的实例进而执行不同操作。 -
C语言中变量未初始化会赋随机值,Java中未初始化则无法编译
Java中的运算
Java中的关系运算(6个): 相等== 不相等!= 大于> 小于< 大于等于>= 小于等于<=
关系运算符的优先级低于算术运算符,但是比赋值运算符要高关系运算符中的==和!=的优先级比其他关系运算符要低
C语言中一般用1或0表示真假,Java中一般用true or false
- true或false没有谁大谁小之分,二者不可以和数字进行比较
- 7>=3+4,先算3+4,再算7>=7
- 5>3==6>4 先算5>3得到true,6>4得到true,最后:true == true
- 6>5>4 先做6>5,得到true,再做true>4 无法比较
- a==b==true 先做a==b,得到true or false,再判断是否等于true
- a==b==6 先做a==b,得到true或false,再判断是否等于6,无法判断
- a==b>false 先做b>false,不管b是什么,都无法比较 (a==b)>false,但是前面得出true或false,也无法与false比较大小
- System.out.println(5==5.0);//输出true
- 两个浮点数比较
判断两个浮点数是否相等,求出差值的绝对值,该绝对值要小于一个很小的数字。
public class compare {
public static void main(String[] args) {
System.out.println(5==5.0);
//整数和浮点数比较得到true
//两个浮点数呢?
double a = 1.0;
double b = 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1;
System.out.println("a为" + a + " b为" + b);
System.out.println(a==b);//得到false
//判断两个浮点数是否相等:>先求差值绝对值,和一个比较小的数字比较
System.out.println(Math.abs(a-b) < 1e-6);//得到true
}
}
- 保留小数(使用printf)
System.out.printf("%.2f\n",3.356);//输出3.36
Math.random()函数
函数介绍
Math.random()可以随机生成大于等于0.0且小于1.0的伪随机值,类型是double
随机生成数字或字符
随机生成0到n的数
int num=(int)(Math.random()*n);
随机生成a到b的数
int number=m+(int)(Matn.randon()*b + a);
随机生成char1到char2的字符
char c = (char)(cha1+Math.random()*(cha2-cha1+1));
//猜数游戏
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
int x = (int)(Math.random()*100+1); //数字在[1 , 100]
System.out.println("请猜数:>");
int num;
int count=0;
do{
num=in.nextInt();
count++;
if(num>x) System.out.println("猜大了!");
else if(num<x) System.out.println("猜小了!");
}while(x!=num);
System.out.println("恭喜你,猜了"+count+"次就猜对了!!");
}
跳出多重循环的两种break方法
在想要跳出的循环前面加上标签,之后break跳出时直接跳过标签下的循环。
标签后要加冒号(以下代码中的标签是OUT)
ps:类似于C语言中的goto语句
实现跳出3-3-3层循环(后面的循环不再执行)
public static void main(String[] args) {
int i=0;
int j=0;
int n=0;
OUT:
for(i = 0; i < 5; i++) {
System.out.println("一层循环第" + i + "次");
for(j = 0; j < 5; j++) {
System.out.println("二层循环第 " + i + "-" + j + " 次");
for(n = 0;n < 5; n++)
{
System.out.println("三层循环第 " + i + "-" + j + "-" + n + "次");
if(i==3&&j==3&&n==3)
{
System.out.println("跳出3-3-3循环");
break OUT;
}
}
}
}
System.out.println("结束");
}
通过外层循环增加判断条件,内层循环修改判断条件的值来跳出循环
如下代码中的flag
由于flag只会使用到两个值,所以考虑用boolean类型,它只有true和false这两个值。
public static void main(String[] args) {
int i=0;
int j=0;
int n=0;
boolean flag =true;
//在最外层循环中增加一个flag是否为true的判断条件
for(i = 0; i < 5 && flag; i++) {
System.out.println("一层循环第" + i + "次");
for(j = 0; j < 5; j++) {
System.out.println("二层循环第 " + i + "-" + j + " 次");
for(n = 0;n < 5; n++)
{
System.out.println("三层循环第 " + i + "-" + j + "-" + n + "次");
if(i==3&&j==3&&n==3)
{
System.out.println("跳出3-3-3循环");
flag = false;
break;
}
}
}
}
System.out.println("结束");
}
的确跳出了3-3-3的循环,但是后面的循环依旧在执行。所以如果要跳出整个大循环,应该都加上一个flag的判断条件。
for( i=0 ; i<5 && flag; i++){
for( j=0 ; j<5 && flag; j++){
for(n=0 ; n<5 &&flag; n++){
if( i==3&&j==3&&n==3){
System.out.println("跳出3-3-3循环");
flag=false;
break;
}
}
}
}
数组中的使用以及Java中的可扩展性
数组成员length
在Java中,数组的元素个数是可以改变的;而在C语言中数组元素个数一般是固定的,要改变元素个数需要进行内存分配。
在Java中,每一个数组都有一个内部成员length,它可以告诉你数组元素个数。
格式:数组名.length
求数组中大于平均值的数:>
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("要输入多少数字:>");
int cnt=in.nextInt();
int [] numbers=new int[cnt];
double sum=0.0;
for(int i=0;i<cnt;i++)
{
numbers[i]=in.nextInt();
sum+=numbers[i];
}
double average = sum/cnt;
System.out.println("平均数为"+average);
System.out.println("比平均数大的数字有:");
//length在for循环的判读条件里
for(int i=0;i<numbers.length;i++)
{
if(numbers[i] > average)
{
System.out.println(numbers[i]);
}
}
}
可扩展性
这样的程序有可扩展性
也就是指:不需要修改这个for循环,与数组名、元素个数等无关,这个程序可以用于其他代码中。
如下代码中,数组的内容不影响for循环的进行。
由于length的存在,无论数组内容如何变化,都能将各个元素输出。
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
int []arr={1,2,3,4,5,6};
//从这里之后的代码都与arr元素内容无关了
System.out.println("数组元素有"+arr.length+"个");
for(int i=0;i<arr.length;i++)
{
System.out.println(arr[i]+" ");
}
}
可扩展性高就是指:
当你要添加新的内容时,不需要对程序中的其他内容进行修改。
也就是说新的功能可以很容易地加入到程序中去。比如说在过程中需要增加新的功能时,这个项目的主结构不变,这就是可扩展性高。
数组中的new int [n]
先看一段代码:>
在改变数组b的同时,数组a也发生了变化
原因:只有一个new int [5]的数组,而a和b都只是管理这块空间。
如下图:>
int i =5;是将5这个值赋给一个整型变量i,i拥有这个数值5
而 int []a=new int [5];
是指 创建出了一块数组,属于new int [5],而数组a可以管理这个new数组。
而int []b=a;
是指 让b也拥有这块空间的管理权,数组b也可以管理这个数组。
举个栗子:有一块公共的空地,叫做new int [],
有一天,地主a在这块地上的第一块空间内种了5棵树;
后来,邻居b想在第一块空间内种6棵树,于是把a的5棵树砍了,种好了自己的6棵树.
在数组内放的数据与数值大小无关,只和存放的先后有关。
(先有数组,占一块空间,后来的a和b都只是管理这个数组)
(谁最后在这里种树,这片区域的树就有几棵)
为了加深理解,看以下代码:>
请问a1的各个值为多少?
所以,在java中可以通过a2改变a1中数组各元素大小。
因为数组并不归谁所有,a1和a2都只是负责使用这一块区域;甚至可以有a3、a4....
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
int []a1= {1,1,1};
int[] a2=a1;
for(int i=0;i<a2.length;i++)
{
a2[i]++;
}
System.out.println("a1数组元素如下:>");
for(int i=0;i<a1.length;i++)
{
System.out.println(a1[i]);
}
}
数组变量间的比较
数组变量间进行比较,判断的是:是否管理同一个数组。(不仅仅是内容相同)
解释:
1、false 虽然a1和a2的内容相同,但是二者的数组所占的位置不同,不是同一块空间。
2、true 由于a3=a1,将管理权分给a3;a1和a3管理同一片区域。
3、false 由于a3管理的是a1管理的空间,这就相当于是比较a1和a2了,当然不相等。
小总结:
1、数组变量是数组的管理者,而不是数组本身。
2、我们先是创建出了一个数组,如何可以将这个数组交给多个人去管理。
3、数组变量之间的赋值只是共享管理权限。
比如说 int[]a2 = a1;就是让a2一起管理这个数组
4、数组变量之间的比较只是判断是否管理同一个数组。
数组的拷贝以及对应元素的比较
数组的拷贝必须遍历整个数组。
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
int[] arr={1,2,3,4,5};
int[] brr=new int[arr.length];
for(int i=0;i<brr.length;i++)
{
brr[i]=arr[i];
}
System.out.println("brr中各元素如下:>");
for(int i=0;i<brr.length;i++)
{
System.out.println(brr[i]);
}
}
数组各元素的比较同理,对应元素进行比较。
Scanner in =new Scanner(System.in);
int[] arr={1,2,3,4,5};
int[] brr=new int[arr.length];
for(int i=0;i<brr.length;i++)
{
brr[i]=arr[i];
}
boolean flag=true;//标记是否相等
for(int i=0;i<brr.length;i++)
{
if(arr[i]!=brr[i])
flag = false;
}
System.out.println("结果是:" + flag);
数组的一些计算以及for-each循环
题1:计算某个数字输入了多少次。
如下代码计算1、2、3出现了多少次
注意:Java中数组在创建时,会默认初始化为0。
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
int[] nums=new int[4];
System.out.println("请输入数字");
int x=in.nextInt();
while(x!=-1)//输入-1则结束计数
{
if(x>0&&x<4)
{
nums[x]++;
}
x=in.nextInt();
}
for(int i=1;i<nums.length;i++)
{
System.out.println(i+":"+nums[i]+"次");
}
}
题2:数组中的线性搜索(最笨的方法)
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
int[] arr={11,98,76,54,32};
boolean flag =false;
int i=0;
int x=in.nextInt();
for(i=0;i<arr.length;i++)
{
if(arr[i]==x)
{
flag=true;
break;
}
}
if(true==flag)
{
System.out.println("找到了,"+x+"在数组中的第"+(i+1)+"个位置");
}else System.out.println("找不到");
}
For-Each循环
for-each循环是Java中的一种新的遍历数组的方式。比如在数组内,你只想要找到是否有某个元素,而不用知道下标,那么for-each循环是一个不错的选择。
缺点:无法通过for-eacch循环给数组进行赋值;无法找到数组对应元素的的下标。
下图中的for(int k : arr)是指:
从arr[0]开始,遍历arr数组,每次都将arr中的一个元素赋给k。
for-each格式:
for( <变量类型><变量名> :<数组> ){
......
}
Scanner in =new Scanner(System.in);
int[] arr={11,98,76,54,32};
boolean flag =false;
int i=0;
int x=in.nextInt();
for(int k:arr)
{
if(x==k)
{
flag=true;
break;
}
}
题3:素数
方法1:遍历查找
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
int x=in.nextInt();
boolean isP=true;
int n=0;
do{
if( 1==x )
isP = false;
for(int i=2;i<x;i++)
{
if(0==x%i)
{
isP=false;
break;
}
}
if(isP)
{
System.out.println(x+"是素数");
}else
{
System.out.println(x + "不是素数");
}
System.out.println("请输入:>");
isP=true;
x=in.nextInt();
}while(x!=0);
}
方法2:抛开偶数,只查奇数
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
boolean isP=true;
System.out.println("请输入:>");
int x = in.nextInt();
while (x != 0)
{
if (x == 1 || x % 2 == 0 && x != 2)
isP = false;
else
{
for (int i = 3; i < x; i += 2)
{
if (0 == x % i)
{
isP = false;
break;
}
}
}
if (isP) System.out.println(x + "是素数");
else System.out.println(x + "不是素数");
System.out.println("请继续输入:>");
isP=true;
x=in.nextInt();
}
System.out.println("程序结束。。。");
}
方法3:开根查找
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
boolean flag=true;
System.out.println("请输入:>");
int x=in.nextInt();
while(x!=0) {
flag = true;
for (int j = 2; j <= Math.sqrt(x); j++) {
if (x % j == 0) {
flag = false;
break;
}
}
if (flag) {
System.out.println(x+"是素数");
} else {
System.out.println(x+"不是素数");
}
System.out.println("请继续输入:>");
flag=true;
x=in.nextInt();
}
}
方法4:素数表
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
int[]primes=new int[30];
primes[0]=2;
int cnt=1;
OUT:
for(int n=3;cnt<30;n++)
{
for(int i=0;i<cnt;i++)
{
if(n%primes[i]==0)
{
continue OUT;
}
}
primes[cnt]=n;
cnt++;
}
for(int k:primes)
{
System.out.print(k+" ");
}
}
字符类型
char表示单个字符,可以是字母'a',数字'1'、汉字'文' 。
Java使用Unicode表示字符,可以表示汉字在内的多种文字。
字母和数字在Unicode表中是按照顺序排列的,但是大小写是分开排列的,并不在一起。 48~57是0~9
65~90是A~Z
97~122是a~z
小写字母排在大写字母后面
//实现大小写转换
Scanner in =new Scanner(System.in);
char c1='A';
char ret=(char)(c1+'a'-'A');
System.out.println(ret);
- 逃逸字符
逃逸字符:无法打印出来的控制字符或特殊字符,由反斜杠\开头
- 包裹类型
包裹类型:
将一个基本数据类型的数据转换成对象的形式,使得它们可以像对象一样参与运算和传递。
既然有了基础类型,那么为什么要有包裹类型呢?
其实,包裹类型可以方便我们代码的书写,
如下图,在Character.中,有很多代码可以帮助我们简化程序的书写
包裹类型的一些使用:
public static void main(String[] args) {
System.out.println(Character.toLowerCase('A'));//转换为小写
System.out.println(Character.toUpperCase('b'));//转换为大写
System.out.println(Integer.max(4,8));//输出较大的那个数
System.out.println(Double.sum(1.2,3.8));//两个浮点数求和
}
Math类
Math类,用于提供一些数学操作。
注意:
三角函数中输入弧度制而不是角度制,例如:Math.sin(Math.PI/2)才是正确写法
方法 | 作用 |
Math.abs | 取绝对值,返回类型与原类型相同 |
Math.round | 四舍五入,返回整型 |
Math.rint | 四舍五入(比较特殊) |
Math.random | 随机数,范围是[0.0,1.0)返回类型double |
Math.pow | 次方,pow(2,3)计算2的立方,输出8.0类型double |
Math.ceil | 向上取整,double |
Math.floor | 向下取整,double |
Math.E | 自然对数e,e=2.718.... |
Math.PI | 圆周率π |
Math.exp() | exp(x)就是计算e的x次幂,指数函数 |
Math.sqrt | 开算术平方根,类型double |
Math.log(x) | 数学中的对数函数lnx,返回double |
Math.log10() | 数学中的lgx,返回double |
Math.min | 返回最小值 |
Math.max | 返回最大值 |
Math.toDegrees() | 弧度转角度,Math.toDegrees(Math.PI/6); 输出 30.0,返回double |
Math.toRadians() | 角度转弧度 |
Math.sin() | 计算正弦值,返回double |
Math.cos() | 计算余弦值,返回double |
Math.tan() | 计算正切值,返回double |
Math.asin() | 根据值计算角度,输出弧度,输入0.5,输出π/6 |
Math.acos() | 根据值计算角度,输出弧度 |
Math.atan() | 根据值计算角度,输出弧度 |
字符串
字符串的创建与连接
String str;
String(第一个字母S要大写)是一个类String的变量是对象的管理者而非所有者,和数组类似
String str = new String("hello");
String str ="hello";
创建了一个String的对象,用"hello"初始化这个对象
创建了管理这个对象的变量str,让str去管理这个对象
用+可以连接两个字符串,如果+的一边是字符串,另一边不是呢?
答:它会将另一边表达为字符串然后连接
为什么左边是6?
因为运算是从左往右,第一个数字是1,为int,第二个数字是2,也为int,所以二者进行整型的加法,接着和3进行整型加法。
当碰到str时,被转换为字符串类型与hello连接,得到"6hello"
接着这整个字符串与下一位1进行运算,由于1是整型,要被转换为字符串类型,于是我们得到了"6hello1",后续同理。
字符串的输入
字符串的输入:
in.next();读入的是一个单词,单词结束标志是空格;
包括(空格space、缩进tab、换行符)
in.nextLine();读入的是一整行
字符串的比较
和数组相似,String的变量是对象的管理者而非所有者
如果用==进行比较,这只能判断二者是不是同一个东西。
如下图中,str1和str2的内容都hello,但是str2与"hello"并不相等。
如果要比较内容该怎么办呢?像遍历数组一样去遍历整个字符串吗?
并不,有一种更简单的方法,字符串对象中的.equals操作,如下
小结:
==判断的是二者是不是同一个东西。
.equals判断的是二者的内容是否相同。
对字符串操作
介绍:
字符串是对象,对它的所有操作都是通过“.”操作符来进行
格式:字符串.操作
这里的字符串可以是变量也可以是常量
-
字符串比大小comparTo
//--------------字符串的比较compareTo---------------
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
String str1="abc";
String str2="abd";
System.out.println(str1.compareTo(str2));//输出-1
//这里是将str1与str2作比较,如果str1大,则返回1
//若相等则返回0,如果str2大就返回-1
}
-
获取字符串长度length()
//-------------获取字符串长度length()------------
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
String str1="abcdefg";
String str2=" ";//一个空格
String str3="";
String str4;
System.out.println(str1.length());//输出7
System.out.println(str2.length());//输出1
System.out.println(str3.length());//输出0
System.out.println(str4.length());//error
//因为str4没有管理任何String的对象
}
-
访问字符串里的单个字符
str.charAt(index);
返回在index位置上的单个字符
index的范围是0~length()-1
字符串中第一个字符的index是0,和数组类似
注意:不能用for-each遍历字符串
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
String str = "12ab啦啦";
for(int i=0;i<str.length();i++)
{
System.out.println(str.charAt(i));
}
}
-
得到字符串的子串
s.substring(n)
得到从n号位置到末尾的全部内容
s.substring(a,b)
得到从a号到b号位置之前(不包括b号位置)的内容
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
String str="012345哈哈哈";
System.out.println(str.substring(5));
System.out.println(str.substring(0,6));
}
-
寻找某个字符
str.indexOf('char') 找到char字符所在的位置,找不到就返回-1
str.indexOf('char' , n) 从第n号位置开始找char字符,返回首次找到的char字符的下标
str.indexOf('str1') 找到字符串str1所在的位置(该字符串首字符的位置)
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
String str ="hello world";
System.out.println(str.indexOf('w'));//6
System.out.println(str.indexOf('l'));//2
//如果我要找第二个l怎么办?
int loc = str.indexOf('l');
System.out.println(str.indexOf('l',loc));//依旧是2
System.out.println(str.indexOf('l',loc+1));//此时才是3
System.out.println(str.indexOf('l',loc+2));//此时是9
}
诸如str.lastIndexOf()的操作就是从后往前找。
-
其他String操作
str.startsWith() | 是否以某个字符串开头,返回true or false |
str.endsWith() | 是否以某个字符串结尾,返回tre or false |
str.trim() | 删掉字符串两端的空格 |
str.replace(s1,s2) | 将字符串中的s1全部替换成s2 |
str.toLowerCase() | 将所有字符变成小写 |
str.toUpperCase() | 将所有字符变成大写 |
代码演示:>
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
String str="Hello Nyx";
String str2=" Hello Nyx ";
System.out.println(str.startsWith("Hello"));//是否以某个字符串开头
System.out.println(str.startsWith("abc"));
System.out.println(str.endsWith("nyx"));//是否以某个字符串结尾
System.out.println(str2.trim());//删掉字符串两端的空格
System.out.println(str.replace('l','a'));
System.out.println(str.toLowerCase());//所有字符变成小写
System.out.println(str.toUpperCase());//所有字符变成大写
}
注意:
在Java中,所有的字符串都是不可变的
对字符串的操作结果都是制造出一个新的字符串再将该字符串返回
不会改变原字符串!!!!!
示例如下:>
一点小尾巴:
在C语言中,我们的switch-case中都是用整型表示
但是在Java中在switch-case中也可以使用字符串
Java中的"new"运算符为每个对象分配内存空间,而C语言中通过malloc()和free()分别实现对于的内存的分配和运用,这一点还是很方便的。
Over.