5.2、有参和无参
有参数:小括号当中有内容,当一个方法需要一些数据条件,才能完成任务的时候,就是有参数。
例如:两个数相加相乘需要知道具体参数。
无参数:小括号当中留空。一个方法不需要任何数据条件,自己就能独立完成任务。就是无参。
例如:打印字符。
注意事项:
1.方法应该定义在类当中,但是不能在方法当中再定义方法。不能嵌套。
2.方法定义的前后顺序无所谓。
3.方法定义之后不会执行,如果希望执行,一定要调用:单独调用、打印调用、赋值调用。
4.如果方法有返回值那么必须写上“return 返回值;”不能没有。
5.return后面的返回值数据,必须和方法的返回值类型,对应起来。
6.对于一个void没有返回值,不能写return后面返回值,只能写return自己。
7.对于void方法当中最后一行的return可以省略不写。
8.一个方法当中可以有多个return语句,但是必须保证同时只有一个会被执行到,两个return不能连写。
1. 形参:方法定义中的参数
等同于变量定义格式,例如:int number
public static void getMax(int a, int b)
2. 实参:方法调用中的参数
等同于使用变量或常量,例如: 10 number
int a = 10; int b = 20;
public class MethodTest { public static void main(String[] args) { //在main()方法中调用定义好的方法(使用常量) getMax(10,20); //调用方法的时候,人家要几个,你就给几个,人家要什么类型的,你就给什么类型的 //getMax(30); //getMax(10.0,20.0); //在main()方法中调用定义好的方法(使用变量) int a = 10; int b = 20; getMax(a, b); } //定义一个方法,用于打印两个数字中的较大数,例如getMax() //为方法定义两个参数,用于接收两个数字 public static void getMax(int a, int b) { //使用分支语句分两种情况对两个数字的大小关系进行处理 if(a > b) { System.out.println(a); } else { System.out.println(b); } } }
5.3、方法的重载(overload)
方法重载概念 方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载
多个方法在同一个类中
多个方法具有相同的方法名
多个方法的参数不相同,类型不同或者数量不同
注意:
重载仅对应方法的定义,与方法的调用无关,调用方式参照标准格式
重载仅针对同一个类中方法的名称与参数进行识别,与返回值无关,换句话说不能通过返回值来判定两个方法是否相互构成重载
多个方法的名称一样,但是参数列表不一样。
好处:只需要记住唯一一个方法名称,就可以实现类似的多个功能。
方法重载与下列因素有关:
1.参数个数不同
2.参数类型不同
3.参数多类型顺序不同
方法重载与下列因素无关:
1.与参数的名称无关
2.与方法的返回值类型无关
方法名称(参数类型(参数列表) 参数名称,......)
public class t13 { public static void main(String[] args) { //调用方法 System.out.println(compare(10, 10)); System.out.println(compare((byte) 10, (byte) 20)); System.out.println(compare((short) 10, (short) 20)); System.out.println(compare(10L, 20L)); } //int public static boolean compare(int a, int b) { System.out.println("int:"); return a == b; } //byte public static boolean compare(byte a, byte b) { System.out.println("byte:"); return a == b; } //short public static boolean compare(short a, short b) { System.out.println("short:"); return a == b; } //long public static boolean compare(long a, long b) { System.out.println("long:"); return a == b; } }
六、数组
6.1、数组的定义格式
1、数组的概念:是一种容器,可以同时存放多个数据值
2、数组的特点:
1.数组是一种引用数据类型。
2.数组当中的多个数据,类型必须统一。
3.数组的长度在程序运行期间不可改变。
3、数组的初始化:在内存当中创建一个数组,并且向其中赋予一些默认值。
两种常见的初始化方式:
1.动态初始化(指定长度):在创建数组的时候,直接给定数组当中的数据元素个数。
格式:
数据类型【】 数组名称=new 数据类型【数组长度】;
int[] A=new int[300];
//动态创建 int a[]=new int[5]; //静态创建 int b[]=new int[]{1,2,3,4,5,6} ; int b[]={1,2,3,4,5,6};
解析含义:
左侧数据类型:也就是数组当中的保存的数据,全都是统一的什么类型。
左侧的中括号:代表我是一个数组。
左侧数组名称:给数组取一个名字。
右侧的new:代表创建数组的动作。
右侧数据类型:必须和左边的数据类型保持一致。
右侧中括号的长度:也就是数组当中,到底可以保存多少个数据,是一个int数字。
2.静态初始化(指定内容):在创建数组的时候,不直接给定数据个数多少,而是直接将具体的数据内容进行指定。
基本格式:数据类型【】 数组名称=new 数据类型【】{元素1,元素2,。。。。。};
int[] A=new int[]{1,2,3};
省略格式:数据类型【】 数组名称={元素1,元素2,。。。。。};
int[] A={1,2,3};
1)虽然静态初始化没有直接告诉长度,但是根据大括号里面的元素内容,也可以自动推算出来长度。
2)静态初始化标准格式可以拆分成两个步骤。
3)动态初始化也可以拆分成两个步骤。
4)静态初始化一旦使用省略格式,就不能拆分成两个步骤了
使用建议:
如果不确定数组当中的具体内容,用动态初始化,否者,已经确定了具体内容,用静态初始化。
4、数组访问
访问数组的元素的格式:数组名称【索引值】
索引值,就是一个int数字,代表数组当中元素的编号。
注意:索引值从0开始,一直到“数组的长度-1”为止
使用动态初始化数组的时候,其中的元素将会自动拥有一个默认值,规则如下:
如果是整数类型,那么默认为0;
如果是浮点类型,那么默认为0.0;
如果是字符类型,那么默认为"\u0000";
如果是布尔类型,那么默认为false;
如果是引用类型,那么默认为null;
注意事项:静态初始化其实也有默认值的过程,只不过系统自动马上将默认值替换成为大括号当中的具体数值。
6.2、数组的内存图
内存划分为五部分:
1.栈(stack):存放的都是方法中的局部变量。方法的运行一定要在栈当中运行。
局部变量:方法的参数,或者是方法{ }内部变量。
作用域:一旦超出作用域,立刻从栈内存当中消失。
2.堆(heap):凡是new出来的东西,都在堆当中。
堆内存里面的东西都有一个地址值:16进制
堆内存里面的数据,都幽默认值。
规则:
如果是整数类型,那么默认为0;
如果是浮点类型,那么默认为0.0;
如果是字符类型,那么默认为"\u0000";
如果是布尔类型,那么默认为false;
如果是引用类型,那么默认为null;
3.方法区(Method Area):存储 .class相关信息,包含方法的信息。
4.本地方法栈(Native Method Stack):与操作系统相关。
5.寄存器(pc Register):与CPU相关。
寄存器:给CPU使用,和我们开发无关。
本地方法栈:JVM在使用操作系统功能的时候使用,和我们开发无关。
方法区:存储可以运行的class文件。
堆内存:存储对象或者数组,new来创建的,都存储在堆内存。
方法栈:方法运行时使用的内存,比如main方法运行,进入方法栈中执行。
一、单个数组
二、多个数组
三、
6.3、数组异常
数组的索引编号从0开始,一直到“数组的长度为-1”为止。
如果访问数组的元素的时候,索引编号并不存在,那么将会发生数组索引越界异常。
原因:索引编号写错。
解决:修改成为存在的正确索引编号。
所有的引用类型变量,都可以赋值为一个null值。但是代表其中什么都没有。
数组必须进行new 初始化才能使用其中元素。
如果只是赋值了一个null,没有进行new创建。
那么将会发生:空指针异常 NullPointerException
原因:忘了new
解决:补上new
int [] array=null; array=new int[3];
6.4数组运算
1、如何获取数组长度,格式:
数组名称.length
这将会得到一个int数字。代表数组长度。
int[] arr={}; int len=arr.length; System.out.println(len);
数组一旦创建,程序运行期间,长度不可改变。
在Java中,
length方法用于获取数组的长度。
int[] arr = new int[10]; System.out.println(arr.length);
而length()用于获取String字符串中字符的个数。
String str = "HelloJava"; System.out.println(str.length());
//String字符串的方法和String[]的属性的区别 int a[]=new int[]{1,2,3,4,5,7,6,45,54,5};//length属性 System.out.println(a.length); String b="ABSHJDBG";//length方法 System.out.println(b.length());
2、遍历输出:
说的是对数组当中的每一个元素进行逐一、挨个儿处理。默认的处理方式就是打印输出。
求反数:
从小到大遍历
Arrays.sort(a); //自动遍历:从小到大输出
System.out.println(Arrays.toString(a)); //遍历输出
//从小到大遍历 import java.util.Arrays; public class t6 { public static void main(String[] args) { int a[]={1,2,35,3,23,656,121,45}; Arrays.sort(a);//自动遍历:从小到大输出 System.out.println(Arrays.toString(a));//遍历输出 } }
方法参数传递引用类型
结论: 对于引用类型的参数,形式参数的改变,影响实际参数的值
结论依据: 引用数据类型的传参,传入的是地址值,内存中会造成两个引用指向同一个内存的效果,所以即使方法 弹栈,堆内存中的数据也已经是改变后的结果
public class t1 { public static void main(String[] args) { int[] a={10,20,30}; System.out.println("第一次输出"+a[1]); change(a);//先到int[] a={10,20,30};再到change(int[] a);最后改变a[1]输出 System.out.println("第二次输出"+a[1]); } public static void change(int[] a){ a[1]=200; } }
3、java split()的用法:
Java中split主要用于分隔字符串。
具体分析如下:
1、如果用“.”作为分隔的话,必须是如下写法,String.split("\\."),这样才能正确的分隔开,不能用String.split(".")。
2、如果用“|”作为分隔的话,必须是如下写法,String.split("\\|"),这样才能正确的分隔开,不能用String.split("|"),“.”和“|”都是转义字符,必须得加"\\"。
3、如果在一个字符串中有多个分隔符,可以用“|”作为连字符,比如,“acount=? and uu =? or n=?”,把三个都分隔出来,可以用String.split("and|or")。
String a1="12341`1234`5456"; String[] a2=a1.split("\\`"); System.out.println(Arrays.toString(a2));
Java中split使用注意事项:
1.要被分解的String对象或文字,该对象不会被split方法修改。
2.字符串或正则表达式对象,它标识了分隔字符串时使用的是一个还是多个字符。如果忽略该选项,返回包含整个字符串的单一元素数组。
3.该值用来限制返回数组中的元素个数(也就是最多分割成几个数组元素,只有为正数时有影响)。
4.split 方法的结果是一个字符串数组,在 stingObj 中每个出现 separator 的位置都要进行分解。separator不作为任何数组元素的部分返回。
//随机生成数,并输出 import java.util.Arrays; import java.util.Random; public class t8 { public static void main(String[] args) { int a[]=new int[10]; for(int i=0;i<a.length;i++){ int b=new Random().nextInt(20);//随机生成20以内的10个数 a[i]=b; } System.out.println(Arrays.toString(a)); } }
4、拷贝
拷贝若超过原数组的长度,会出现扩容现象。不够位置用0补齐。
import java.util.Arrays; public class t7 { public static void main(String[] args) { int a[]=new int[]{1,8,9,7,5,6,54,56,8,6,53,34,45,56}; System.out.println(a.length);//数组长度 int[] copyof=Arrays.copyOf(a,14); System.out.println(Arrays.toString(copyof));//复制数组a到copyof int[] copyof1=Arrays.copyOf(a,18);//超过原数组的长度,会出现扩容现象。不够位置用0补齐。 System.out.println(Arrays.toString(copyof1)); int[] copyof2=Arrays.copyOf(a,6);//小于原数组的长度复制几位输出几位。 System.out.println(Arrays.toString(copyof2)); }}
5、冒泡排序
冒泡排序是一种比较简单的排序算法,它循环走过需要排序的元素,依次比较相邻的两个元素,如果顺序错误就交换,直至没有元素交换,完成排序。
若对n个人进行排序,我们需要n-1次比较,所以第k次比较需要进行n-k次比较。排序算法通过以数据对象的两两比较作为关键,所以可以得出,冒泡排序需要进行的
比较次数为:(n-1) + (n-2) + … + 1 = n*(n-1) / 2,因此冒泡排序的时间复杂度为O(n^2)
//1.冒泡排序-s--两两比较,大的和小的换位置 let dataList=[12,2,3,46,1,2,8]; let hasSort=[]; //第一遍循环 n-1 次 (n=dataList.length) for(let i=0;i<dataList.length;i++){ //第二遍循环 n-i-1 次 for(let j=0;j<i;j++){ if(dataList[i]>dataList[j]){ let _data = dataList[i] dataList[i] = dataList[j] dataList[j]=_data } } hasSort.push(dataList[i]); } console.log("hasSort:"+hasSort) //1.冒泡排序-end public static void ArraySortTest() { int[] ages= {21,27,31,19,50,32,16,25}; System.out.println(Arrays.toString(ages)); //控制比较轮数 for(int i=1;i<ages.length;i++) { //每轮比较多少 for(int j=0;j<ages.length-i;j++) { if(ages[j]>ages[j+1]) { int tmp=0; tmp=ages[j]; ages[j]=ages[j+1]; ages[j+1]=tmp; }}} System.out.println(Arrays.toString(ages)); }
4、传递地址
数组可以作为方法的参数。
当调用方法的时候,向方法的小括号进行传参,传递进去的其实是数组的地址值。
6、值传递和引用传递的区别
1:按值传递是什么
指的是在方法调用时,传递的参数是按值的拷贝传递。
[java] view plain copy public class TempTest { private void test1(int a){ //做点事情 } public static void main(String[] args) { TempTest t = new TempTest(); int a = 3; t.test1(a);//这里传递的参数a就是按值传递 } } //按值传递重要特点:传递的是值的拷贝,也就是说传递后就互不相关了。 [java] view plain copy public class TempTest { private void test1(int a){ a = 5; System.out.println("test1方法中的a="+a); } public static void main(String[] args) { TempTest t = new TempTest(); int a = 3; t.test1(a);//传递后,test1方法对变量值的改变不影响这里的a System.out.println(”main方法中的a=”+a); } }
2:按引用传递是什么
指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。
[java] view plain copy public class TempTest { private void test1(A a){ } public static void main(String[] args) { TempTest t = new TempTest(); A a = new A(); t.test1(a); //这里传递的参数a就是按引用传递 } } class A{ public int age = 0; }
3:按引用传递的重要特点
传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。
[java] view plain copy public class TempTest { private void test1(A a){ a.age = 20; System.out.println("test1方法中的age="+a.age); } public static void main(String[] args) { TempTest t = new TempTest(); A a = new A(); a.age = 10; t.test1(a); System.out.println(”main方法中的age=”+a.age); } } class A{ public int age = 0; } 运行结果如下: [java] view plain copy test1方法中的age=20 main方法中的age=20
public class Poker { public static void main(String[] args) { //创建一个牌盒,也就是定义一个集合对象用ArrayList集合 ArrayList<String> array=new ArrayList<>(); //往牌盒里面装牌 /* ♦2,♦3,♦4...♦K,♦A ♣2,... ♥2,... ♠2,... 小王,大王 */ //定义花色数组 String[] colors={"♦", "♣", "♥", "♠"}; //定义点数数组 String[] numbers={"2","3","4","5","6","7","8","9","10","J","Q","K","A"}; for(String color:colors){ for(String number:numbers){ array.add(color+number); } } array.add("大王"); array.add("小王"); //洗牌,也就是把牌打散,用collection的shuffle()方法实现 Collections.shuffle(array); //发牌。也就是遍历集合,发给三个玩家发牌 ArrayList<String> lqxArray=new ArrayList<String>(); ArrayList<String> lyAArray=new ArrayList<String>(); ArrayList<String> lqyArray=new ArrayList<String>(); ArrayList<String> dpArray=new ArrayList<String>(); for (int i = 0; i < array.size(); i++) { String poker=array.get(i); if(i>=array.size()-3){ dpArray.add(poker); }else if(i%3==0){ lqxArray.add(poker); } else if (i % 3 == 1) { lyAArray.add(poker); } else if (i % 3 == 2) { lqyArray.add(poker); } } //看牌,也就是三个玩家分别遍历自己的牌 lookPoker("林青霞",lqxArray); lookPoker("柳岩",lyAArray); lookPoker("风清扬",lqyArray); lookPoker("底牌",dpArray); } //看牌方法 public static void lookPoker (String name,ArrayList<String> array){ System.out.println(name +"的牌是"); for (String poker:array) { System.out.println(poker+" "); } System.out.println(); } }
七、面向对象:类
7.1基本概念
1、面向过程:当需要实现一个功能的时候,每一个具体的步骤都要亲力亲为,详细处理每一个细节。
2、面向对象:当需要实现一个功能的时候,不关心具体的步骤,而是找一个已经具有该功能的人,来帮我做事。
面向对象是基于面向过程而言。
三大特点:封装、继承和多态
使用面向对象:找到一个JDK 给我们提供好的Arrays类;其中有一个toString方法,直接就能把数组变成想要的格式的字符串
int[] arr={1,2,5,3,5}; System.out.println(arr.toString(arr));
对象三个特点:对象的状态、对象的行为和对象的标识
类
类的理解
类是对现实生活中一类具有共同属性和行为的事物的抽象
类是对象的数据类型,类是具有相同属性和行为的一组对象的集合
简单理解:类就是对现实事物的一种描述
类的组成
属性:指事物的特征,例如:手机事物(品牌,价格,尺寸)
行为:指事物能执行的操作,例如:手机事物(打电话,发短信)
类和对象的关系
类:类是对现实生活中一类具有共同属性和行为的事物的抽象
对象:是能够看得到摸的着的真实存在的实体
简单理解:类是对事物的一种描述,对象则为具体存在的事物
7.2 类的定义
类的组成是由属性和行为两部分组成
属性:在类中通过成员变量来体现(类中方法外的变量)
行为:在类中通过成员方法来体现(和前面的方法相比去掉static关键字即可)
类的定义步骤:
①定义类
②编写类的成员变量
③编写类的成员方法
public class 类名 { // 成员变量 变量1的数据类型 变量1; 变量2的数据类型 变量2; … // 成员方法 方法1; 方法2; }
package cn.day02.demo01; public class Student { //成员变量 String name;//姓名 int age;//性别 //成员方法 public void eat(){ System.out.println("吃饭了"); } public void sleep(){ System.out.println("睡觉"); } public void study(){ System.out.println("学习"); } }
2、对象的创建及使用
通常情况下,一个类并不能直接使用,需要根据类创建一个对象,才能使用。
1.导包:也就是指出需要使用的类,在什么位置。
import 包名称.类名称;
import cn.itcast.day06.demo01.Student;
对于和当前类属于同一个包的情况,可以省略导包语句不写。
2.创建,格式:
类名称 对象名=new 类名称();
Student stu=new Student();
3.使用,分为两种情况;
使用成员变量:对象名.成员变量名
使用成员方法:对象名.成员方法名(参数);
也就是,想用谁,就用对象名点儿谁。
注意事项:如果成员变量没有进行赋值,那么将会有一个默认值,规则和数组一样。
public class Student { //成员变量 String name;//姓名 int age;//性别 //成员方法 public void eat(){ System.out.println("吃饭了"); } public void sleep(){ System.out.println("睡觉"); } public void study(){ System.out.println("学习"); } } public class Demo02Stuident { public static void main(String[] args) { // 1.导包 // 我需要使用的Student类,和我自己Demo02Stuident位于同一个包下,所以省略导包语句不写. // // 2.创建,格式: // 类名称 对象名=new 类名称(); // 根据Student类,创建了一个名为Stu的对象 Student stu=new Student(); //3.使用其中的变量,格式: //对象名.成员变量名 System.out.println(stu.name);//null System.out.println(stu.age);//0 System.out.println("============"); //改变对象当中的成员变量数值内容 //将右侧的字符串,赋值交给stu对象当中的name成员变量 stu.name="张三"; stu.age=14; System.out.println(stu.name);//张三 System.out.println(stu.age);//14 System.out.println("============"); //4.使用对象的成员方法,格式: //对象名.成员方法(); stu.eat(); stu.sleep(); stu.study(); }}
练习手机:
类:
/* 定义一个类,用来模拟“手机”事务。 属性:品牌、价格、颜色 行为:打电话、发短信 对应到类当中: 成员变量(属性): String brand; //品牌 double price;//价格 String color;//颜色 成员方法(行为): public void call(String who){} //打电话 public void sendMessage(){}//群发信息 */ public class Phone { //成员变量 String brand; //品牌 double price;//价格 String color;//颜色 //成员方法 public void call(String who){ System.out.println("给"+who+"打电话"); } //打电话 public void sendMessage(){ System.out.println("群发信息"); }//群发信息 } 函数: public class Demo01PhoneOne { public static void main(String[] args) { //根据Phone类,创建一个名为one的对象 //格式:类名称 对象名=new 类名称(); Phone one=new Phone(); //使用其中的变量,格式: //对象名.成员变量名 System.out.println(one.brand);//null System.out.println(one.price);//0.0 System.out.println(one.color);//null System.out.println("==========="); //改变对象当中的成员变量数值内容 //将右侧的字符串,赋值交给one对象当中的name成员变量 one.brand="苹果"; one.price=8888557.0; one.color="黑色"; System.out.println(one.brand);//苹果 System.out.println(one.price);//8888557.0 System.out.println(one.color);//黑色 System.out.println("==========="); //使用对象的成员方法,格式: //对象名.成员方法(); one.call("乔布斯"); one.sendMessage(); Phone two=new Phone(); System.out.println(two.brand);//null System.out.println(two.price);//0.0 System.out.println(two.color);//null System.out.println("==========="); two.brand="三星"; two.price=4057.0; two.color="蓝色"; System.out.println(two.brand);//三星 System.out.println(two.price);//4057.0 System.out.println(two.color);//蓝色 one.call("欧巴"); one.sendMessage(); } }
堆与栈的区别很明显:
1.栈内存存储的是局部变量而堆内存存储的是实体;
2.栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;
3.栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。
堆:当需要一个对象时,只需用new写一行简单的代码,当执行这行代码时,会自动在堆里进行存储分配。
情况一.1:一个对象的内存图
情况一:两个引用指向同一个方法的内存图 Phone two=new Phone(); System.out.println(two.brand);//null System.out.println(two.price);//0.0 System.out.println(two.color);//null System.out.println("==========="); two.brand="三星"; two.price=4057.0; two.color="蓝色"; System.out.println(two.brand);//三星 System.out.println(two.price);//4057.0 System.out.println(two.color);//蓝色 one.call("欧巴"); one.sendMessage(); } }
情况三 使用对象类型作为方法的参数 public class Demo01PhoneTwo { public static void main(String[] args) { Phone one=new Phone(); one.brand="苹果"; one.price=8888557.0; one.color="黑色"; method(one); } private static void method(Phone param) { System.out.println(param.brand); System.out.println(param.price); System.out.println(param.color); } }
情况四:使用对象类型作为方法的返回值 public class Demo01PhoneThree { public static void main(String[] args) { Phone two=getPhone(); System.out.println(two.brand);//苹果 System.out.println(two.price);//545.0 System.out.println(two.color);//金玫瑰 } private static Phone getPhone() { Phone one=new Phone(); one.brand="苹果"; one.price=545.0; one.color="金玫瑰"; return one; } }
八、成员变量和局部变量的区别:
类中位置不同:成员变量(类中方法外)局部变量(方法内部或方法声明上)
内存中位置不同:成员变量(堆内存)局部变量(栈内存)
生命周期不同:成员变量(随着对象的存在而存在,随着对象的消失而消失)局部变量(随着方法的调用而 存在,醉着方法的调用完毕而消失)
初始化值不同:成员变量(有默认初始化值)局部变量(没有默认初始化值,必须先定义,赋值才能使用)
1.定义的位置不一样【重点】
局部变量:在方法的内部
成员变量:在方法的外部,直接写在类当中
public class Student { private String name;//成员变量 private int age;//成员变量 public void method1(){ int num=20;//局部变量 } } public class t1 { //成员变量:类的成员 static静态资源 static int a=10;//10 static int b;//0 static float b1;//0.0 static char b2;//空 static String c;//null public static void main(String[] args) { method(); } private static void method() { int a=20;//局部变量 //就近原则 System.out.println(a);//20 System.out.println(b);//0 System.out.println(b1);//0.0 System.out.println(b2);//空 System.out.println(c);//null } }
2.作用范围不一样【重点】
局部变量:只有方法当中才可以使用,出了方法就不能再用
成员变量:整个类全都可以通用
3.默认值不一样【重点】
局部变量:没有默认值,如果要想使用,必须手动进行赋值
成员变量:如果没有赋值,会有默认值,规则和数组一样
4.内存的位置不一样(了解)
局部变量:位于栈内存
成员变量:位于堆内存
5.生命周期不一样(了解)
局部变量:随着方法进栈而诞生,随着方法出栈而消失(时间短)
成员变量:随着对象创建而诞生,随着对象被垃圾回收而消失(时间长)
public class t1 { String name;//成员变量 public void methodA(){ int num=20;//局部变量 System.out.println(num); System.out.println(name); } public void methodB(int param){//方法的参数就是局部变量 //参数在方法调用的时候,必然会被赋值 System.out.println(param); int age;//局部变量 // System.out.println(age);//没赋值不能用 // System.out.println(num);//错误写法 System.out.println(name); } }
九、面向对象三大特征
封装、继承、多态
9.1封装
private是一个修饰符,可以用来修饰成员(成员变量,成员方法)
被private修饰的成员,只能在本类进行访问,针对private修饰的成员变量,如果需要被其他类使用,提供相 应的操作
提供“get变量名()”方法,用于获取成员变量的值,方法用public修饰
提供“set变量名(参数)”方法,用于设置成员变量的值,方法用public修饰
对于封装而言,一个对象它所封装的是自己的属性和方法,所以它是不需要依赖其他对象就可以完成自己的操作。使用封装有三大好处:
1、良好的封装能够减少耦合。
2、类内部的结构可以自由修改。
3、可以对成员进行更精确的控制。
4、隐藏信息,实现细节。
在Java中的体现
1.方法就是一种封装
2.关键字private也是一种封装
封装就是将一些细节信息隐藏起来,对外界不可见。
作用:
1)提高安全性
2)提高重用性
练习题1:
public class Demo01 { public static void main(String[] args) { int[] array={5,15,25,20,100}; int max=getMax(array); System.out.println("最大值"+max); } //给我一个数组,我还给你一个最大值 private static int getMax(int[] array) { int max=array[0]; for(int i=1;i<array.length;i++){ if(array[i]>max){ max=array[i]; } } return max; }} 练习题2: /* 问题描述:定义Person的年龄时,无法阻止不合理的数值被设置进来。 解决方案:用private关键字将需要保护的成员变量进行修饰。 一旦使用了private进行修饰,那么本类当中仍然可以随意访问。 但是!超出了本类范围之外就不能在直接访问了。 间接访问private成员变量,就是定义一对儿Getter/Setter方法 格式: 必须叫setXxx或者是getXxx命名规则。 对于Getter来说,不能有参数,返回值类型和成员变量对应; 对于Setter来说,不能有返回值,参数类型和成员变量对应。 */ public class Person { String name; //姓名 private int age;// 年龄 public void show(){ System.out.println("我叫:"+name+",年龄:"+age); } //成员方法,专门用于向age设置数据 public void setAge(int num){//set方法设置值,不需要返回值,需要参数 if (num<100&&num>=9){ age=num;//如果是合理情况 }else{ System.out.println("数据不合理!"); } } //这个成员方法,专门私语获取age的数据 public int getAge(){//get方法取值,不需要参数,需要返回值 return age; } } public class Demo03Person { public static void main(String[] args) { Person person=new Person(); person.show(); person.name="赵丽颖"; //person.age=-20;//直接访问private内容,错误写法! person.show(); person.setAge(20); System.out.println(); } } private定义学生类 /* 对于基本类型当中的boolean值,Getter方法一定要写成isXxx的形式,而setXxx规则不变。 */ public class Student { private String name;//姓名 private int age;//年龄 private boolean male;//是不是爷们 //是不是爷们boolean public void setMale(boolean b){ male=b; } public boolean isMale(){ return male; } //姓名 public void setName(String str){ name=str; } public String getName(){ return name; } //年龄 public void setAge(int num){ age=num; } public int getAge(){ return age; }} public class Demo01Student { public static void main(String[] args) { Student stu=new Student(); stu.setName("鹿晗"); stu.setAge(22); stu.setMale(true); System.out.println("姓名:"+stu.getName()); System.out.println("年龄:"+stu.getAge()); System.out.println("是不是爷们儿:"+stu.isMale()); } }
9.2 this关键字
this修饰的变量用于指代成员变量,其主要作用是(区分局部变量和成员变量的重名问题)
方法的形参如果与成员变量同名,不带this修饰的变量指的是形参,而不是成员变量。
方法的形参没有与成员变量同名,不带this修饰的变量指的是成员变量。
当方法的局部变量和类的成员变量重名的时候,根据”就近原则“,优先使用局部变量。
如果需要访问本类当中的成员变量,需要使用格式
this.成员变量
"通过谁调用的方法,谁就是this."
/* 当方法的局部变量和类的成员变量重名的时候,根据”就近原则“,优先使用局部变量。 如果需要访问本类当中的成员变量,需要使用格式 this.成员变量 "通过谁调用的方法,谁就是this." */ public class Person { //成员变量 String name;//我自己的名字 //参数name是对方的名字 //成员变量name是自己的名字 //局部变量 public void sayHello(String name){ System.out.println(name+",你好!我是:"+this.name); System.out.println(this); } } public class demo01Person { public static void main(String[] args) { Person person=new Person(); //设置我自己的名字 person.name="王健林"; person.sayHello("王世聪"); System.out.println();//地址值 } }
this内存原理【理解】
this代表当前调用方法的引用,哪个对象调用的方法,this就代表哪一个对象
封装思想【理解】
1. 封装概述 是面向对象三大特征之一(封装,继承,多态) 是面向对象编程语言对客观世界的模拟,客观世界 里成员变量都是隐藏在对象内部的,外界是无法直接操作的
2. 封装原则 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏 信息的操作和访问 成员变量private,提供对应的getXxx()/setXxx()方法
3. 封装好处 通过方法来控制成员变量的操作,提高了代码的安全性 把代码用方法进行封装,提高了代码的复用 性
9.3 构造方法和定义一个标准类
构造方法是一种特殊的方法
作用:创建对象 Student stu = new Student();
格式:
public class 类名{
修饰符 类名( 参数 ) { }
}
功能:主要是完成对象数据的初始化
构造方法的创建:
如果没有定义构造方法,系统将给出一个默认的无参数构造方法 如果定义了构造方法,系统将不再提供默认的构造 方法。
构造方法的重载 :
如果自定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参数构造方法 。
推荐的使用方式 :
无论是否使用,都手工书写无参数构造方法。
重要功能!
可以使用带参构造,为成员变量进行初始化
构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法。
格式:
public 类名称(参数类型 参数名称){
方法体
}
注意事项:
1.构造方法的名称必须和所在的类名称完全一样,就连大小写也要一样。
2.构造方法不要写返回值类型,连void都不写。
3.构造方法不能写return一个具体的返回值。
4.如果没有编写任何构造方法,那么编译器将会默认赠送一个构造方法,没有参数、方法体什么事情都不做。
public Student(){}
5.一旦编写至少一个构造方法,那么编译器将不再赠送。
6.构造方法也是可以进行重载的。
重载:方法名称相同,参数列表不同。
/* 构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法 格式: public 类名称(参数类型 参数名称){ 方法体 } 注意事项: 1.构造方法的名称必须和所在的类名称完全一样,就连大小写也要一样。 2.构造方法不要写返回值类型,连void都不写。 3.构造方法不能写return一个具体的返回值。 4.如果没有编写任何构造方法,那么编译器将会默认赠送一个构造方法,没有参数、方法体什么事情都不做。 public Student(){} 5.一旦编写至少一个构造方法,那么编译器将不再赠送。 6.构造方法也是可以进行重载的。 重载:方法名称相同,参数列表不同。 */ public class Student { //成员变量 private String name; private int age; //无参数的构造方法 public Student(){ System.out.println("无参构造方法执行了!"); } //全参数的构造方法 public Student(String name,int age){ System.out.println("全参构造方法执行了!"); this.name=name; this.age=age; } //Getter Setter public void setName(String name){ this.name=name; } public String getName(){ return name; } public void setAge(int age){ this.age=age; } public int getAge() { return age; } } public class Demo02Student { public static void main(String[] args) { Student stu1=new Student();//无参构造 System.out.println("============"); Student stu2=new Student("赵丽颖",20);//全参构造 System.out.println("姓名:"+stu2.getName()+", 年龄"+stu2.getAge()); //如果需要改变对象当中的成员变量数据内容,仍然还需要使用setXxx方法 stu2.setAge(21);//改变年龄 System.out.println("姓名:"+stu2.getName()+", 年龄"+stu2.getAge()); } } 练习二: /* 一个标准的类通常要拥有下面四个组成部分: 1.所有的成员变量都要使用private关键字修饰。 2.为每一个成员变量编写一对儿Getter/Setter方法 3.编写一个无参数的构造方法 4.编写一个全参数的构造方法 这样标准的类也叫做JavaBean */ public class Student { private String name; private int age; //无参构造方法 public Student() { } //全参构造方法 public Student(String name, int age) { this.name = name; this.age = age; } public String getName(){ return name; } public void setName(String name){ this.name=name; } public int getAge(){ return age; } public void setAge(int age){ this.age=age; } } public class Demo01Student { public static void main(String[] args) { Student stu1=new Student(); stu1.setAge(20); stu1.setName("迪丽热巴"); System.out.println("姓名:"+stu1.getName()+",年龄"+stu1.getAge()); System.out.println("============="); Student stu2=new Student("张思",23); System.out.println("姓名:"+stu2.getName()+",年龄"+stu2.getAge()); stu2.setAge(45); System.out.println("姓名:"+stu2.getName()+",年龄"+stu2.getAge()); } }
9.4 API标准概述和使用步骤
什么是API API (Application Programming Interface) :应用程序编程接口。
java中的API 指的就是 JDK 中提供的各种功能的 Java类,这些类将底层的实现封装了起来,我们不需要关心这些类是如何 实现的,只需要学习这些类如何使用即可,我们可以通过帮助文档来学习这些API如何使用。
9.5 Scanner
可以实现键盘输入数据,到程序当中
1、Scanner概述及API的使用
Scanner类的功能:可以实现键盘输入数据,到程序当中。 引用类型的一般使用步骤: 1.导包 import 包路径.类名称; 如果需要使用的目标类,和当前类位于同一个包下,则可以省略导包语句不写。 如果java.long包下的内容不需要导包,其他的包都需要import语句。 2.创建 类名称 对象名=new 类名称(); 3.使用 对象名.成员方法名();
2、Scanner使用步骤 /* 获取键盘输入的一个int数字:int num=sc.nextInt(); 获取键盘输入的一个字符串:String str=sc.next(); */ //1.导包 import java.util.Scanner; public class Demo01Scanner { public static void main(String[] args) { // 2.创建:备注:System.in代表从键盘进行输入 // 类名称 对象名=new 类名称(); Scanner sc=new Scanner(System.in); //3.获取键盘输入的一个int数字: int num=sc.nextInt(); System.out.println("输入的int数字:"+num); //4.获取键盘输入的一个字符串 String str=sc.next(); System.out.println("输入的字符串是:"+str); } } 3、Scanner练习 习题一: /* 题目:键盘输入两个数,并求出和值。 思路: 1.既然需要键盘输入,那么就用Scanner 2.Scanner的三个步骤:导包、创建、使用 3.需要的是两个数字,所以要调用两次nextInt方法 4.得到两个数字,就需要加在一起 5.将结果打印输出 */ import java.util.Scanner; public class Demo03Scanner { public static void main(String[] args) { System.out.println("输入第一个数:"); //Scanner sc=new Scanner(System.in); //int x=sc.nextInt(); int x=new Scanner(System.in).nextInt(); System.out.println("输入第二个数:"); //int y=sc.nextInt(); int y=new Scanner(System.in).nextInt(); int sum=x+y; System.out.println("求和:"+sum); } } 习题二: /* 题目:键盘输入三个int数字,然后求出其中的最大值。 思路: 1.既然是键盘输入,肯定需要用到Scanner 2.Scanner三个步骤:导包、创建、使用nextInt()方法 3.既然是三个数字,那么调用三次nextInt()方法,得到三个int变量 4.无法同时判断三个数字谁最大,应该转换成为两个步骤 4.1首先判断前两个当中谁最大,拿到前两个的最大值 4.2拿着当前两个中的最大值,再和第三个数字比较,得到三个数字当中的人最大值 5.打印最终结果 */ public class Demo02Scannersum { public static void main(String[] args) { System.out.println("输入第一个数字"); int x=new Scanner(System.in).nextInt(); System.out.println("输入第二个数字"); int y=new Scanner(System.in).nextInt(); System.out.println("输入第三个数字"); int z=new Scanner(System.in).nextInt(); int t=x>y?x:y; int max=t>z?t:z; System.out.println("最大值:"+max); } } 4、匿名对象的说明 public class Person { String name; public void showName() { System.out.println("我叫:" + name); }} /* 创建对象的标准格式: 类名称 对象名=new 类名称(); 匿名对象就是只有右边的对象,没有左边的名字和赋值运算符。 new 类名称(); 注意事项:匿名对象只能使用唯一的一次下次再用不得不再创建一个新对象。 使用建议:如果确定有一个对象只需要使用唯一的一次,就可以用匿名对象。 */ public class Demo01Anonymous { public static void main(String[] args) { //类名称 对象名=new 类名称(); Person one=new Person(); one.name="高圆圆"; System.out.println(one.name); one.showName();//我叫:高圆圆 //匿名对象 new Person().name="赵又廷"; new Person().showName();//?我叫null } } 5、匿名对象作为方法的参数和返回值 public class Demo02Anonymous { public static void main(String[] args) { System.out.println("请输入数字:"); //普通使用方式 //int sc=new Scanner(System.in).nextInt(); //匿名对象方式 //int num=new Scanner(System.in).nextInt(); //System.out.println("输入的是:"+num); //使用一般写法传入参数 //Scanner sc=new Scanner(System.in); //methodParam(sc); //使用匿名对象来进行传参 //methodParam(new Scanner(System.in)); Scanner sc=methodReturn(); int num=sc.nextInt(); System.out.println("输入的是:"+num); } public static void methodParam(Scanner sc){ int num=sc.nextInt(); System.out.println("输入的数字是:"+num); } public static Scanner methodReturn(){ //Scanner sc=new Scanner(System.in); // return sc; return new Scanner(System.in); } }