——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
本章内容较多…
方法
格式:修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2...) {
方法体语句;
return 返回值;
}
参数分类:
实参:实际参与运算的数据
形参:方法上定义的,用于接收实际参数的变量
(1)写方法时首先明确:
返回值类型:结果的数据类型
参数列表:参数的个数及对应的数据类型
(2)方法的注意事项
方法之间是平级关系,不能嵌套定义
(3)方法重载
在同一个类中,方法名相同,参数的个数、参数的对应数据类型不同。与返回值无关。
数组
(1)数组的初始化
A:动态初始化
int[] arr = new int[3];
B:静态初始化
int[] arr = new int[]{1,2,3};
简化版:int[] arr = {1,2,3};
(2)Java的内存分配
A:栈 存储局部变量(定义在方法内的变量)。数据使用完毕,就消失
B:堆 存储所有new出来的东西。每一个new出来的东西都有地址。数据使用完毕后变成垃圾,在垃圾回收器空闲的时候回收。
C:方法区(面向对象部分详细说明)
D:本地方法区(系统相关)
E:寄存器(CPU使用)
注意:每一个变量都有默认值
byte,short,int,long 0
float,double 0.0
char '\u0000'
boolean false
引用类型 null
(3)数组内存图
两个栈变量指向同一个堆内存 int[] arr = new int[3]; int[] arr2=arr;可通过arr2修改arr的值,两个数组指向同一个堆内存
(4)数组操作常见异常
ArrayIndexOutOfBoundsException 数组越界,访问了不存在的索引
NullPointerException 空指针,在数组已经不再指向堆内存时继续访问(如:int[] arr ={1,2,3}; arr=null; sout arr[0]; 此时就会抛出空指针异常)
二维数组
(1)格式:
A:数据类型[][] 数组名 = new 数据类型[m][n];
B:数据类型[][] 数组名 = new 数据类型[m][];
C:数据类型[][] 数组名 = new 数据类型[][]{{...},{...},{...}};
D:数据类型[][] 数组名 = {{…},{...},{...}};
(2)内存分配图:
数组练习题
1.把数组逆序
public static void arrReverse(int[] arr){
//操作前一半就行
for (int i = 0;i<(arr.length)/2;i++){
//这里运用了b = (a+b)-(a=b); 方式和后半部分对应的数交换位置
arr[arr.length-(i+1)] = (arr[i]+arr[arr.length-(i+1)])-(arr[i] = arr[arr.length-(i+1)]);
}
}
2.查找指定元素第一次在数组中出现的索引
public static int arrFind(String abc,String[] arr){
for (int i=0;i<arr.length;i++){
if (abc==(arr[i])){
return i;
}
}
return -1; //若要查找的元素在数组中没有 则返回-1
}
3.打印杨辉三角形,行数自定义
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
分析:从第2行开始,每行数据=上一行该列数据+上一行前一列数据
public static void yangHui(int line) {
if (0 < line && line < 3) {
System.out.println("最少三行");
} else if (line <= 0) {
System.out.println("数据有误");
} else {
int[][] yanghui = new int[line][]; //创建二维数组,二维数组里每个元素是每行数据组成的一维数组
yanghui[0] = new int[]{1}; //录入第一行,第二行数据
yanghui[1] = new int[]{1, 1};
System.out.println(1); //打印第一二行数据
System.out.println(1 + "\t" + 1);
for (int x = 2; x < line; x++) { //开始遍历,从第三行开始
System.out.print(1 + "\t"); //打印该行第一个数1
yanghui[x] = new int[x + 1]; //初始化该行数组
for (int y = 1; y < x; y++) { //遍历该行数组,从第二列开始 到 倒数第二列
yanghui[x][0] = 1; //添加该行第一列数1和最后一列数1
yanghui[x][x] = 1;
yanghui[x][y] = yanghui[x - 1][y] + yanghui[x - 1][y - 1]; //计算该行其余列的数据并储存
System.out.print(yanghui[x][y] + "\t");
}
System.out.println(1); //打印该行最后一个数1
}
以上代码较复杂,改进思路:先不打印,只计算、储存数据。最后再用for遍历打印,代码会更整洁易懂
4.加密一个8位整数,加密规则:
首先将数据倒序,然后每位数字+5,再用和除以10的余数代替该数
最后将第一位和最后一位数字交换,打印
获取每个数字的方法:个位 = 12345678 % 10 = 8 ; 十位:12345678/10 % 10 = 7;以此类推
public static String jiami (int key){
int[] arr = new int[8];
// for (int i = 0;i<7;i++){
// arr[i]=(int)((key/Math.pow(10,(7-i))) % 10); //将输入的数据前七位放入数组 double强转int
// }
// arr[7]=key%10; //最后一位不用除以10 所以单独放进去
// arrReverse(arr); //倒序
/**
* 方法改进
*/
int index = 0,num=key;
while(num>0){ //因为首先要倒序,所以直接从个位开始录入数组
arr[index] = num%10;
index++;
num/=10;
}
for (int i =0;i<index;i++){ //+5求余
arr[i]=(arr[i]+5)%10;
}
arr[0] = arr[0]^arr[index-1]; //交换
arr[index-1] = arr[0]^arr[index-1];
arr[0] = arr[0]^arr[index-1];
String s = ""; //转换为字符串
for (int i=0;i<index;i++){
s += arr[i];
}
return s;
}
5.写一个打印数组方法
public static void printArr (int[] arr){
System.out.print("[");
for (int i = 0 ;i<arr.length;i++){
if (i != arr.length-1)
System.out.print(arr[i]+",");
else
System.out.print(arr[i]);
}
System.out.println("]");
}
Java中的参数传递问题
Java中只有值传递。
基本类型:形式参数的改变不影响实际参数
引用类型:形式参数的改变直接影响实际参数
例如:main方法里定义了int a=10,b=20两个实参,把a,b传入另一个方法change,change方法里对a,b的值修改,不会影响到main方法里a,b的值,因为ab都是基本数据类型,所以传入参数的时候传递的是值,在change方法里操作数据a=40;b=50;后main方法里ab的数据还是10,20。若传入的是数组等引用数据类型,那么传入的数据实际上是那个地址,所以change方法里改变数据,main方法里的数组也会被改变。
面向对象
(1)面向对象是基于面向过程的编程思想
(2)面向对象的思想特点
A:是一种更符合我们思考习惯的思想
B:把复杂的事情简单化
C:让我们从执行者变成了指挥者
如何让我们的操作更符合面向对象思想呢?
A:有哪些类
B:每个类有哪些成员
C:类与类的关系
(3)类与对象
A:现实世界的事物
属性 事物的基本描述
行为 事物的功能
B:Java语言中最基本的单位是类。所以,我们要用类来体现事物
C:类:是一组相关的属性和行为的集合。是一个抽象的概念。
成员变量 即事物属性
成员方法 即事物行为
对象:是该类事物的具体存在,是一个具体的实例。(对象)
举例:
学生:类
班长:对象
(4)类的定义及使用
类的定义
成员变量 在类中,方法外
成员方法 定义格式和以前一样,就是去掉了static。
(5)Java程序的开发,设计和特征
A:开发:就是不断的创建对象,通过对象调用功能
B:设计:就是管理和维护对象间的关系
C:特征:封装,继承,多态
成员变量和局部变量的区别
(1)在类中的位置不同
(2)在内存中的位置不同
成员变量:在堆中
局部变量:在栈中
(3)生命周期不同
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
(4)初始化值不同
成员变量:有默认值
局部变量:没有默认值,必须定义,赋值,然后才能使用
(5)局部变量名称可以和成员变量一样,使用时是就近原则
匿名对象
(1)没有名字的对象 new Student();
(2)应用场景
A:调用方法,仅仅只调用一次的时候。new Student().show();
b:可以作为实际参数传递。sd.method(new Student());
(3)优点:匿名对象调用完毕就成了垃圾,可以被垃圾回收器回收
封装
(1)隐藏实现细节,提供公共的访问方式,把不想让外界知道的实现细节给隐藏起来,提供公共的访问方式
(2)private是封装的一种体现。
(3)private关键字
特点:被private修饰的后的成员只能在本类中被访问。private方法也只能在本类中调用,不能被外部类调用(需要通过公共方法访问)
this关键字
(1)代表当前类的引用对象
记住:哪个对象调用方法,该方法内部的this就代表那个对象
(2)应用:
A:方法的形参与类的成员变量同名时
B:一个类中的构造器调用同一类中另一个构造器时
class Person{
String name; int age;
public Person(String name){
this.name = name; //this.name表示这个对象的name =号右边的name是构造方法传入的形参
}
public Person(String name,int age){
this(name); //调用本类其他构造方法
this.age = age;
}
}
构造方法
(1)作用:用于对对象的数据进行初始化
思考题:构造方法中可不可以有return语句呢?
可以。而是我们写成这个样子就OK了:return;
其实,在任何的void类型的方法的最后你都可以写上:return;
(2)构造方法的注意事项
A:如果我们没写构造方法,系统将提供一个默认的无参构造方法
B:如果我们给出了构造方法,系统将不再提供默认构造方法。如果这个时候要使用无参构造方法,就必须自己给出。
(3)给成员变量赋值的方式
A:setXxx()
B:带参构造方法
Student s = new Student();做了哪些事情?
(1)把Student.class文件加载到内存
(2)在栈内存为s开辟空间
(3)在堆内存为学生对象申请空间
(4)给学生的成员变量进行默认初始化。null,0
(5)给学生的成员变量进行显式初始化。林青霞,27
(6)通过构造方法给成员变量进行初始化。刘意,30
(7)对象构造完毕,把地址赋值给s变量
static关键字
(1)静态的特点:
A:随着类的加载而加载
B:优先于对象存在
C:被类的所有对象共享
D:可以通过类名调用
既可以通过对象名调用,也可以通过类名调用,一般用类名调用。
(2)静态的内存
静态的内容在方法区的静态区
(3)静态的注意事项;
A:在静态方法中没有this对象。静态变量是随着类的加载而加载,this是随着对象的创建而存在。静态比对象先存在。
B:静态方法只能访问静态成员变量和静态成员方法
(4)静态变量和成员变量的区别
A:所属不同
静态变量:属于类,类变量
成员变量:属于对象,对象变量,实例变量
B:内存位置不同
静态变量:方法区的静态区
成员变量:堆内存
C:生命周期不同
静态变量:静态变量随着类的加载而加载,随着类的消失而消失
成员变量:成员变量随着对象的创建而存在,随着对象的消失而消失
D:调用不同
静态变量:可以通过对象名调用,也可以通过类名调用
成员变量:只能通过对象名调用
制作、使用帮助文档
(1)写一个类
ps:在同一个文件夹下,类定义在两个文件中和定义在一个文件中是一样的。
把构造方法private后,外界将不能创建对象,只能通过类名调用静态变量和静态方法
(2)加入文档注释
@param 表示参数
(3)通过javadoc工具生成即可
javadoc -d 目录 -author -version ArrayTool.java
(4)学习查看API
java.lang包不需要导入
查看API步骤:
先看类的结构
再看 成员变量:字段摘要。
构造方法:构造方法摘要。
成员方法:方法摘要)
再看构造方法 有or没有、参数列表
再看成员方法 是否静态、返回值类型、方法名、参数列表
代码块
(1)用{}括起来的代码。
(2)分类:
A:局部代码块
用于限定变量的生命周期,及早释放,提高内存利用率。
B:构造代码块
在类中的成员位置,把多个构造方法中相同的代码可以放到这里,构造代码块优先于构造方法执行。
只要调用构造方法,就会优先执行构造代码块
class Code{
{
sout10;//sout表示System.out.println();
}
public Code( ){
sout30;
}
{
sout20;
}
//输出结果为10 20 30
}
C:静态代码块
在构造代码块前加static。优先于构造代码块执行
用于对类的数据进行初始化,只执行一次,以后再加载该类,都不执行了。
(3)静态代码块,构造代码块,构造方法的顺序问题?
静态代码块 > 构造代码块 > 构造方法
(4)综合题,看代码分析结果
public class Test1 {
static {
System.out.println("Test1的静态代码块");
}
{
System.out.println("Test1的构造代码块");
}
public Test1(){
System.out.println("Test1的构造方法");
}
public static void main(String[] args) {
System.out.println("我是main方法");
Zoo.method();
Zoo s = new Zoo();
Zoo s2 = new Zoo();
}
}
class Zoo{
static void method(){
System.out.println("Zoo的静态方法");
}
public Zoo(){
System.out.println("Zoo构造方法");
}
{
System.out.println("Zoo构造代码块");
}
static {
System.out.println("Zoo静态代码块");
}
}
输出结果为
Test1的静态代码块
我是main方法
Zoo静态代码块
Zoo的静态方法
Zoo构造代码块
Zoo构造方法
Zoo构造代码块
Zoo构造方法
若将main方法内容改为如下:
System.out.println("我是main方法");
Zoo s = new Zoo();
s.method();
Zoo s2 = new Zoo();
则输出结果为
Test1的静态代码块
我是main方法
Zoo静态代码块
Zoo构造代码块
Zoo构造方法
Zoo的静态方法
Zoo构造代码块
Zoo构造方法
继承
(1)继承的好处:
A:提高了代码的复用性
B:提高了代码的维护性
C:让类与类产生了一个关系,是多态的前提
(2)继承的弊端:
A:让类的耦合性增强。这样某个类的改变,就会影响其他和该类相关的类。
开发原则:低耦合,高内聚。
耦合:类与类的关系
内聚:自己完成某件事情的能力
B:打破了封装性
(3)Java中继承的特点
A:Java中类只支持单继承
B:Java中可以多层(重)继承(继承体系)
(4)继承的注意事项:
A:子类不能继承父类的私有成员
B:子类不能继承父类的构造方法,但是可以通过super去访问
C:不要为了部分功能而去继承
(5)什么时候使用继承呢?
采用假设法,A是B的一种,或者B是A的一种,则可以用继承
(6)super关键字
用于访问父类
比如子类成员变量、父类成员变量和子类方法内部都定义了num,子类方法若访问方法内部的num就直接调用,访问子类的num要用this,访问父类的num就用super
(7)Java继承中的成员关系
A:成员变量
子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢?
子类的方法访问变量的查找顺序:
在子类方法的局部范围找,有就使用。
在子类的成员范围找,有就使用。
在父类的成员范围找,有就使用。
找不到,就报错。
B:构造方法
a:子类中所有构造方法都会默认会去访问父类的无参构造方法,并且先执行父类的构造方法,再执行子类的构造方法
why?because子类初始化前必须要先把父类初始化
子类每一个构造方法的第一条语句都默认为super(); 是Java自动加上的
b:父类中如果没有无参构造方法,怎么办?
要么在子类构造方法中通过super去明确调用父类带参构造,注意,super(…);必须是该方法第一条语句。若不是第一条,就可能对父类的数据进行多次初始化,所以必须第一条;
要么子类通过this(...);调用本身的其他构造方法,但是被调用的这个构造方法必须有用super调用父类带参构造。即子类中至少要有一个构造方法去访问父类的构造方法;
要么在父类中加一个无参构造。
C:成员方法
子类的成员方法和父类中的成员方法名称一样,这个怎么访问呢?
通过子类对象访问一个方法的查找顺序:
在子类中找,有就使用
在父类中找,有就使用
找不到,就报错
(8)两个面试题:
A:Override和Overload的区别?Overload是否可以改变返回值类型?
重写要求子类方法同父类方法声明完全一样(参数列表、返回值类型、方法名、是否静态)。
重写后若需要调用被重写的父类方法,则加上super.方法名(..);即可实现子类继承父类方法后增加新的功能
注意:A.父类中的私有方法不能被重写,因为根本都无法继承
B.重写方法的访问权限不得低于被重写方法的访问权限 public大于默认(不写访问修饰符)
重载要求参数列表不一样,方法名一样,返回值类型无所谓
B:this和super的区别和各自的作用?
this代表本类对象的引用。super代表父类存储空间的标识(可以理解为父类引用,可以操作父类成员)
用法区别
A:访问成员变量 this.成员变量 super.成员变量
B:访问构造方法 this(..) super(..)
C:访问成员方法 this.成员方法() super.成员方法()
例题:
public class Z extends X{
Y y = new Y();
Z(){
System.out.print("z");
}
public static void main(String[] args) {
new Z();
}
}
class X{
Y b = new Y();
X(){
System.out.print("x");
}
}
class Y{
Y(){
System.out.print("y");
}
}
打印结果为yxyz
原因:
初始化步骤是先父后子(分层初始化),先默认初始化,后显式初始化(即成员变量int a = 10;直接初始化),最后构造方法初始化
super()在子类构造方法中只代表先初始化父类
分析过程:
创建Z对象,Z继承自X,所以需先访问X构造方法,所以先初始化X类,于是执行X类里的Y b = new Y();所以最先创建Y对象并打印出y。然后执行X构造方法打印x。然后回到Z类初始化,先Y y = new Y();于是又打印y,然后执行z构造方法打印z