Java基础代码语法讲解下
2021/7/12 20:07:59
本文主要是介绍Java基础代码语法讲解下,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一:方法
方法是实现某个功能的语句块的集合,Java的方法包含于类与对象中。
1:方法的组成
修饰符:告诉编译器如何调用该方法,定义了该方法的访问类型(所以用访问修饰符),常见的修饰符有,public,protected、缺省默认(default、friendly),private。
返回值类型方法可能会有返回值。类似于:
public static int add(int a ,int b){ return a+b; }
返回值是int型,所以需要返回int类型。
psvm的返回值类型是void,所以不需要有返回值。
存在返回值时,一定要用return返回出去。
参数类型:参数类型像一个占位符,当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
形式参数:在方法被调用时用于接收外界输入的数据。
实际参数:调用方法时实际传给方法的数据。
public class Text10{ public static void main(String[] args) { int sum =add(1 ,2); } public static int add(int a ,int b){ return a+b; } }
其中1,2是实际参数,而a,b是形式参数。
可变参数
格式:在方法声明中,在制定的参数类型后加一个省略号(…)
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数,任何普通的参数必须在它之前声明.
public void massItem(int...i){//...意味着参数是可变的,i值可以不止一个 System.out.println(i[0]); }
打印输入的i的值,i的个数取决于输入的值的个数.
2:方法的调用
对象名.方法名(实参列表)
直接调用
上面的代码完整版如下:
public class Text10 { public static void main(String[] args) { int sum =add(1 ,2); System.out.println(sum); } public static int add(int a ,int b){ return a+b; } }
因为在同一个类Text10中,所以可以直接调用,即方法名(实参列表)。
注:Java支持两种调用方法的方式,根据方法是否有返回值来选择。
当方法返回一个值的时候,方法调用通常被当作一个值,所以用另一个值进行接收。比如:
int sum =add(1 ,2);
如果方法返回值是void,则方法调用的一定是一条语句:
同样的返回a+b在void中需要写成:
public class Text10{ public static void main(String[] args) { Cook(); } public static void Cook(){ int a=1,b=2; System.out.println(a+b); } }
如代码片,void被调用,调用的是语句sop,最后输出3。
不然没有语句也没有返回值,如何执行方法的功能。
实例化类
如果方法在不同的类中,则通过先实例化类再进行调用。
实例化类:对象类型 对象名 = 对象值
public class Test01 { public static void main(String[] args) { } }
public class Test02 { public void Sing(){ System.out.println("I want my money back."); } }
我们在Test01中调用Test02中的方法,先实例化Test02,然后再进行调用:
public class Test01 { public static void main(String[] args) { Test02 sing = new Test02(); sing.Sing(); } }
其中sing为对象名。
如果是静态方法的话,可以直接通过类名.方法名()进行调用
(如何判断是否为静态方法,看是否有static)
public class Test02 { public static void Sing(){ System.out.println("I want my money back."); } }
调用:
public class Test01 { public static void main(String[] args) { Test02.Sing(); } }
递归
递归就是A方法调用A方法,也就是自己调用自己.
递归的结构包括两个部分:
递归头:什么时候不调用自身方法.如果没有头,将陷入死循环.
递归体:什么时候需要调用自身方法.
public static int f(int n){ if(n==1){ return 1; }else { return n*f(n-1); } }
如图,求n的阶乘,就是用f方法调用f方法来进行相乘.
静态方法与非静态方法
如何区分是静态方法还是非静态方法,就是看它有没有static.
public class Text { public static void main(String[] args) { } //静态方法 public static int add(int a,int b){//创建一个方法,方法的类型是整型,static使方法被调用 return a+b; } //非静态方法 public void Input(){ System.out.println("哈哈"); } }
值传递和引用传递
Java是值传递.
3:方法的重载
简单来说就是方法的名字不变,改变方法的参数类型。比如将上文中的int类型改为浮点型:
public static double add(double a ,double b){ return a+b; }
方法重载的规则
~方法名称必须相同
~参数列表必须不同(个数不同,或类型不同,参数排列顺序不同等)
~方法的返回类型可以相同也可以不相同
~仅仅返回类型不同不足以成为方法的重载。
二:数组
1:什么是数组
数组是相同类型数据的有序集合,数组描述的是相同类型的若干数据,按照一定的先后次序排列组合而成.其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们.
数组的四个基本特点
1:其长度是确定的,数组一旦被创建,它的大小就是不可以改变的.
2:其元素必须是相同类型,不允许出现混合类型.
3:数组中的元素可以是任何数据类型,包括基本类型和引用类型.
4:数组变量属于引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量.数组本身就是对象,Java中对象是在堆中的,因此数组无论保持原始数据还是其他对象类型,数组本身是在堆中的.
声明数组
其中dataType为数组类型,arrayRefVar为数组名称.
代码:
int nums[];//声明一个数组,如果不声明,则定义不会成功 //也可以写成 int[] nums;
创建数组
使用new操作符来创建,语法如下:
arraySize指数组空间的大小
int nums = new int[10];//定义一个数组,数组的空间大小为10 //注:只要创建了空间,则栈内会自动分配给初始化的值 int[] a={1,21,17,81,34,25};//静态初始化,空间大小与数组的值将都不再发生改变
这个为静态初始化,空间的大小与数组的值都将不发生改变.
如何将数组中的值取出.
数组名[想要取出的是几号数]
比如我们想取出21,则打印:
System.out.println(a[1]);
数组是从0开始的,21虽然是第二个数字也需标记为1.
动态初始化如下:
遍历数组
array.length为数组的长度.
int add=0; nums[0]=1; nums[1]=2; nums[2]=3; nums[3]=7; nums[4]=11; for (int i = 0; i < nums.length; i++) {//数组的遍历是<而不是<=,因为下标是从0开始,所以比原始值小1 add+= nums[i];//add不参加运算的时候会输出初始化值 } System.out.println(add);
动态初始化包含默认初始化
查找数组中值最大的数:
int max = nums[0]; for (int j = 0; j < nums.length; j++) { if (nums[j] > nums[0]) { max = nums[j]; } } System.out.println(max);
2:三种初始化及内存分析
声明数组,其实就是在栈中开辟一个空间,而给数值进行初始化,则是在堆里分内存.
三种初始化:1:静态初始化,2:动态初始化,3:引用初始化.
其中静态与动态我们上文中已经说过了,现在我们来看一下引用初始化:
首先我们要创建一个名叫Man的类,然后初始化数组:
数组的边界
数组下标越界异常;
int add=0; nums[0]=1; nums[1]=2; nums[2]=3; nums[3]=7; nums[4]=11; for (int i = 0; i <= nums.length; i++) { add+= nums[i]; } System.out.println(add);
还是拿这个来举例,此数组的长度为5,当i等于nums.length时i为5,但是因为数组是从零开始的,只能指向4,i等于5是产生数组下标越界.
数组的使用
a:加强for循环来对数组进行遍历:
int[] array ={1,3,6,7,9,8}; for(int x :array){//加强for循环 System.out.print(x+" "); }
b:输出反转数组
public static int[] reverse(int array[]){ int rArray[]; rArray = new int[array.length]; for (int i = 0,j=array.length-1; i < array.length; i++,j--) { rArray[j]=array[i]; } return rArray;//此处数组作为返回值 }
3:多维数组
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一堆数组,其每一个元素都是一个一维数组.
创建一个多维数组并对数组的值进行输出:
//二维数组 public static void main(String[] args) { int[][] arrays = {{1,2},{2,3},{4,7},{9,1},{5,6},{3,2}}; for (int i = 0; i <arrays.length ; i++) { for (int j = 0; j < arrays[i].length; j++) {//i的长度为2 System.out.print(arrays[i][j]+" "); } } }
Arrays类
查看JDK帮助文档:待补
a:对数组进行排序:Arrays.sort();
b:打印数组:使用toString
c:对数组进行填充:fill
d:判断两数组是否完全相等.(数组的每一个元素都相同)equals
public static void main(String[] args) { int a[]={23,24,31,9,7,26,4,31}; int d[]={3,4,31,9,72,2,41,3}; Arrays.sort(a);//对数组进行排序 System.out.println(Arrays.toString(a));//toString打印数组 String b[]=new String[7]; Arrays.fill(b,2,4,"Hello");//给数组b进行填充,对2 与4进行填充,未填充的为null System.out.println(Arrays.toString(b)); if(Arrays.equals(a,d)){//equals只能用在相同类型的两个数组之间,而不是判断数组中的两个元素 //数组必须要所有元素都相等才叫做相等 System.out.println("他们相等耶"); }else { System.out.println("他们不相等耶"); } }
4:冒泡排序:
比较相邻两个元素的大小,如果更大,则交换两元素的位置.
因为是嵌套循环,直接可以算出时间复杂度为O(n2).
public class Text20 { public static void main(String[] args) { int a[]={6,3,4,23,9,78,65,6,4,34,23,21,59}; int b[]=sort(a); System.out.println(Arrays.toString(a)); } public static int[] sort(int arrays[]){ //确定代码循环的次数 int tom = 0; for (int i = 0; i <arrays.length-1 ; i++) { boolean flag = false; //每次循环都要么找到最大值要么找到最小值,所以,可以减少一次循环的次数 for (int j = 0; j < arrays.length-1-i; j++) { //当发现前一个元素的值大于后一个元素的值的时候交换两者的位置 while(arrays[j]>arrays[j+1]){ tom=arrays[j]; arrays[j]=arrays[j+1]; arrays[j+1]=tom; flag = true; } } if(flag==true){ break; } } return arrays; } }
输出结果:
5:稀疏数组
当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组.
稀疏数组的处理方式是:
记录数组一共有几行几列,有多少个不同值
把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模.
打印如下的稀疏数组:
public static void main(String[] args) { int arrays[][]=new int[6][7]; arrays[0][3]=22; arrays[0][6]=15; arrays[1][1]=11; arrays[1][5]=17; arrays[2][3]=-6; arrays[3][5]=39; arrays[4][0]=91; arrays[5][2]=28; //遍历一下原数组然后输出 for (int m = 0; m <arrays.length ; m++) { for (int n = 0; n <arrays[m].length ; n++) { System.out.print(arrays[m][n]+" "); } System.out.println(); } //首先输出稀疏数组的头部,因为输出的也是数组则再定义一个数组 int arrays2[][]=new int[9][3]; //可以知道几个确定值,先给arrays2 arrays2[0][0]=6; arrays2[0][1]=7; arrays2[0][2]=8; //将原数组的对应元素的行、列与值,赋给稀疏数组的对应元素 int count=0; for (int i = 0; i <arrays.length ; i++) { for (int j = 0; j <arrays[i].length ; j++) { if(arrays[i][j]!=0){ count++; arrays2[count][0]=i; arrays2[count][1]=j; arrays2[count][2]=arrays[i][j]; } } } //打印稀疏数组 for (int q = 0; q <arrays2.length ; q++) { for (int k = 0; k <arrays2[q].length ; k++) { System.out.print(arrays2[q][k]+" "); } System.out.println(); } //将稀疏数组还原 int arrays3[][]=new int[arrays2[0][0]][arrays2[0][1]]; //将数组2的每个元素给数组三对应的位置 //遍历数组2并传值给数组三 for (int o = 1; o < arrays2.length; o++) { arrays3[arrays2[o][0]][arrays2[o][1]]=arrays2[o][2]; } for (int f = 0; f <arrays3.length ; f++) { for (int g = 0; g <arrays3[f].length ; g++) { System.out.print(arrays[f][g]+" "); } System.out.println(); } }
三:什么是面向对象
1:面向对象的本质:以类的方式组织代码,以对象的方式组织(封装)数据。
2:创建对象
使用new关键字创造对象,用new关键字创造时,除了分配内存空间之外,还会给创造好的对象进行默认的初始化以及对类中构造器的调用.
new ImageIcon(resource).getImage();//获取图像
3:构造器
类中的构造器也称为构造方法,是在进行创建对象的时候就必须要调用的.并且构造器有以下两个特点:
1:必须和类的名字相同
2:必须没有返回类型,也不能写void
new一个对象的本质其实是在创建一个构造器
无参构造器与有参构造器
public class Text1 { String name; //无参构造器可以初始化对象 public Text1(){ this.name="王三鸭"; } //有参构造器 public Text1(String name){ this.name = name;//第一个name指的是主类中的name,第二个指的是构造器中的name } }
this代表当前这个类,也就是class Text1,this.name也就是这个类下的name,也就是String name中的name.
构造器可以实例化初始值:
初始值在后续可以进行重新赋值与改变.
如果我们同时有传参与初始化参数,最后输出的会是什么呢:
结果仍然是我们传进去的参数.
一个类即使什么都不写,它也会存在一个方法,显示定义构造器.
注意哦定义有参构造之后,如果想使用无参构造,需要显示的定义一个无参构造.
四:封装
程序设计要追求"高内聚,低耦合".高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用.
封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。在电子方面,封装是指把硅片上的电路管脚,用导线接引到外部接头处,以便与其它器件连接。
有了private之后我们想通过对象来调用属性就不行啦.但是我们可以通过getset方法来传参,封装简单来说就是getset方法的使用.
上图还可以改成我们只想要对方拿到我们想给的范围:
输出的年龄为3.
五:继承
继承是面向对象软件技术当中的一个概念,与多态、封装共为面向对象的三个基本特征。继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。
继承用extends来表示.
1:继承后子类拥有父类的所有方法
2:如果父类是有参构造,则无法调用无参构造,不能直接写super.
3:如何调用父类中的属性? super.属性名
4:方法可以直接调用.
虽然方法可以直接调用,但是方法太多时,我们无法分清哪个是子类的方法哪个是父类的方法,这时可以用super.方法名().
当一个类继承了父类,也意味着继承了父类的父类.
也可以说,当实例化子类时,可以通过子类调用子类的父类的方法:
直接写一个super是在调用父类的构造器.(如果是有参构造器需要在super里传参)
注:1:super构造器必须要放在子类的第一行.
2:super必须只能出现在子类的方法或者构造方法中!
3:super和this不能同时调用构造方法.
补:方法的重写
首先讲一下方法
如果我们有两个类,Soo1继承了Faa1,写成这样的形式:
Faa1 b = new Soo1();
此时b可以调用Soo1和Faa1中的方法,还是只能调用Faa1中的方法呢.
答案是方法的调用看左边,所以b实际上是实例化父类的方法.
再看这个:
Faa1 c = new Faa1();
如果我们想通过c调用Soo1中的方法该怎么办呢.
使用方法的强转:
((Soo1)c).C();
强转还可以写成:Soo1 d=(Soo1)c;
那什么叫做方法的重写呢?
当子类继承父类,子类可以重写父类的方法:
重写需要满足
1:方法名必须相同
2:参数列表必须相同
3:修饰符:范围可以扩大
public>protected>default>private
4:抛出的异常:范围,可以被缩小,但不能被扩大
不能重写的方法:
1:static方法,属于类,不属于任何实例.
2:被final修饰的,在常量池
3:private修饰
六:多态
在编程语言和类型论中,多态(英语:polymorphism)指为不同数据类型的实体提供统一的接口。 多态类型(英语:polymorphic type)可以将自身所支持的操作套用到其它类型的值上。
instanceof,它的作用是判断两个类之间是否存在父子关系,如果存在则返回true.
System.out.println(object instanceof Object); System.out.println(object instanceof Soo1); System.out.println(object instanceof Faa1); System.out.println(object instanceof String); Faa1 f = new Soo1(); System.out.println(f instanceof Soo1);
注:object是所有类的父类
所以关系:object>Faa1>Soo1
最后输出的结果:true true false true
但是instanceof只能识别一条支线也就是object>Faa1>Soo1,如果object>Faa1>Father,则object与Father不是父子关系.
同样的因为object与String是另外一条线,所以也返回false.
如果是同级之间,没有任何关系会报错.
类之间的强制类型转换(发生在高转低之间)
//高 低 Person obj = new Persion(); Student obj1=(Student)obj;
如果是低转高,直接转就好了
Student obj = new Student(); Person person = obj; //子类转换为父类可能丢失自己的本来的一些方法
匿名代码块
{ //代码块 }
静态代码块
static{ //代码块 }
我们来对每个代码块输出进行测试:
public class Exx { { System.out.println("这,是一个匿名代码块"); } static{ System.out.println("这,是一个静态块");//第一个执行 } public Exx(){ System.out.println("这是一个构造块"); } public static void main(String[] args) { Exx e = new Exx(); } }
输出:
注意,static只执行一次.
二次调用时:
拓展:当一个类被final修饰后就无法被继承.
static之间的调用:
抽象类
有abstract在类前叫抽象类,在方法前叫做抽象方法
抽象类里可以有普通方法,普通类里不可以有抽象方法
抽象类不允许调用,只能继承
一旦继承,就要调用抽象类里的所有方法
抽象类无法自我实现,只能通过子类的继承来实现.
来看抽象类与抽象方法:
public abstract class AAA { public abstract void A(); }
普通类来实现抽象方法:
public class BBB extends AAA{ //如果BBB也是抽象类则不能改写其方法,直到下一个继承为止 @Override public void A(){ } }
接口
只有规范!自己无法写方法~专业的约束!
约束和实现分离:面向接口编程.
接口不能实例化
接口没有构造方法
imple可以实现多个接口
必须要重写接口中的所有方法
接口的写法:
public interface JieKoo { //接口,可以多继承,其中的方法都只有名字,没有内容 //接口中的方法默认为public abstract // 接口中只有常量,常量用 public final来修饰 //所以连接接口也像abstract一样需要写出其中的所有方法 void Cook(String name); void Run(String name); void Swim(String name); }
全称为public abstract void run();
为什么可以省略?
因为接口中的方法默认全部是抽象的.
实现接口:
public class Jii implements JieKoo,JieKou{ @Override public void Cook(String name){ } @Override public void Run(String name){ } @Override public void Swim(String name){ } @Override public void ToSleep(String name){ } }
接口中也可以定义属性,接口中定义的属性都是常量:
public static final int AGE =99;
七:内部类
外部类就是我们创建的java大类,我们在Java大类中再创建一个类这个类就是内部类.
public class Outer { int age=10; public void Ouu(){ System.out.println("这是外部类的方法"); } public class Inner {//当调用时需要加上public public void Inn() { System.out.println("这是内部类的方法"); } //内部类可以调用外部类的变量 } }
内部类可以调用外部类的私有属性
那如果我们想调用这个类的内部类该怎么调用呢?
//调用外部类 Outer outer = new Outer(); outer.Ouu(); //调用内部类 //1:有static时直接调用 Outer.Inner.Inn(); //2:没有static修饰时,通过外部类来调用内部 outer.new Inner().Inn(); //也可以写成Outer.Inner a = outer.new Inner(); outer.new Inner().getAge();
注:一个Java类中可以有多个class类,但是只能有一个public class类.
局部内部类:在方法中写一个类.
匿名内部类
和内部类的区别:内部类在大类的里面,匿名内部类在大类的外面,其实相当于重新建了一个class.
public class Inner { public static void main(String[] args) { new Apple().eat(); } } //匿名内部类 class Apple{ public void eat(){ System.out.println("来个苹果吧"); } }
匿名内部类还可以是接口,而且我们可以调用接口重写方法:
public class Inner { public static void main(String[] args) { new Free(){ @Override public void Eat(String name) { } };//注意这里有逗号哦 } } //匿名内部类 interface Free{ void Eat(String name); }
八:异常
首先我们来看一个很常见的错误
public class Text { public static void main(String[] args) { new Text().a(); } public void a(){ b(); } public void b(){ a(); } }
什么是异常?
异常是指程序运行中出现的不期而至的各种情况,如:文件找不到、网络连接失败、非法参数等.
异常发生在程序运行期间,它影响了正常的程序执行流程.
但是可喜可贺的是Java把异常当作对象来处理,并定义了一个基类java.lang.Throwable作为所有异常的超类.
在Java API 中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常
抛出异常与捕获异常
public class Text02 { public static void main(String[] args) { int a=1; int b=0; try{ System.out.println(a/b); }catch (ArithmeticException e){ System.out.println("程序出现异常,变量b不能为0"); }finally { System.out.println("finally"); } } }
我们看看这时的输出结果:
可以不要finally.
catch中填写的是想要捕获的异常类型.
如果不知道填什么就填throwable,因为Throwable的级别最高,能捕获throwable的其他都能捕获.
而且java可以同时不只捕获一个异常写多个catch,但是注意需要把最大的异常写在最下面.
和ifelse差不多,满足一个就不会执行其他else 的内容,满足一个catch,就不会执行其他catch中的内容:
public static void main(String[] args) { int a=1; int b=0; try{ System.out.println(a/b); }catch (Error e){ System.out.println("程序出现异常,变量b不能为0"); }catch(Exception e){ System.out.printf("Exception"); }catch(Throwable t){ System.out.println("Throwable"); } finally { System.out.println("finally"); } }
输出结果:
包裹异常的快捷键:
Ctrl+Alt+t
我们还可以主动抛出异常:
public class Text03 { public static void main(String[] args) { new Text03().test(3,0); } public void test(int a,int b){ if(b==0){ throw new ArithmeticException();//主动抛出异常,一般在方法中使用 } System.out.println(a/b); } }
也可以主动在方法中抛出异常:
(当这个方法中处理不了这个异常的时候)
public class Text03 { public static void main(String[] args) { try { new Text03().test(3,0); } catch (ArithmeticException e) { e.printStackTrace(); } } public void test(int a,int b)throws ArithmeticException{ if(b==0){ //主动抛出异常,一般在方法中使用 //主动抛出时,上面要用try catch进行捕获 throw new ArithmeticException(); } } }
自定义异常
使用Java内置的异常类可以描述在编程时出现的大部分异常情况.除此之外,用户还可以自定义异常.用户自定义异常类,只需要继承Exception类即可.
在程序中使用自定义异常类,大体可分为以下几个步骤:
1:创建自定义异常类.
2:在方法中通过throw关键字抛出异常对象.
3:如果在当前抛出异常的方法处理异常,可以使用try-catch语句捕捉并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作.
4:在出现异常方法的调用者中捕获并处理异常.
后记
写完了,在写的过程中越来越知道自己想要了解什么.在写自定义异常的时候读懂了异常的源码.在instanceof中开始好奇判断类的关系当父子类绑定后会出现什么样的变化.写完了冒泡排序,另外七个排序是不是也可以开始啦.内部类外部类匿名内部类的堆栈存储方式感觉也可以研究好久.
想观察接口还可以实现什么.为什么内部类的调用和实例化类的调用并不相同.
每一个章节都可以专研好久,
在接下来的学习过程中,决定有更多深入理解与整理的文章.而不是仅仅会用就
这篇关于Java基础代码语法讲解下的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-16ShardingSphere 如何完美驾驭分布式事务与 XA 协议?
- 2024-11-16ShardingSphere如何轻松驾驭Seata柔性分布式事务?
- 2024-11-16Maven资料入门指南
- 2024-11-16Maven资料入门教程
- 2024-11-16MyBatis Plus资料:新手入门教程与实践指南
- 2024-11-16MyBatis-Plus资料入门教程:快速上手指南
- 2024-11-16Mybatis资料入门教程:新手必看指南
- 2024-11-16MyBatis资料详解:新手入门与初级实战指南
- 2024-11-16MyBatisPlus资料:初学者入门指南与实用教程
- 2024-11-16MybatisPlus资料详解:初学者入门指南