方法和构造方法
方法
方法体现了面向对象三大要素中的封装的思想
构成方法的四大要素:
1.返回值
2.方法名
3.参数
4.方法体
语法:
修饰符 返回值类型 方法名(参数列表)
{
方法体
return 返回值;
}
方法的重构
使用相同的方法名,但是参数列表不同的方法签名机制,称为方法的重构。
注意,返回类型和修饰符不做要求
int add(int,int);
void add(int,int);//不能达到重构目的
构造方法
回顾对象声明并实例化的格式
类名称 对象名称=new 类名称();
1.类名称:表示定义变量的类型
2.对象名称:
3.new:作为开辟堆内存的唯一方法
4.类名称:构造方法
构造方法是对新创建对象的数据成员赋初值
注意点
1.构造方法的名称必须和类名相同
2.构造方法没有返回值也不能用void
3.构造方法可以被重载
4.构造方法不能用static,final修饰
5.构造方法不能被继承,子类使用父类构造方法需要使用super(关键字)
6.普通方法在需要时调用,构造方法在创建对象时就自动“隐式”执行。通常用它来对对象成员进行初始化。
/*
构造方法的定义方式
*/
class 类名
{
访问权限 类名称(类型1 参数1,类型2 参数2,...)
{
程序语言;
//构造方法没有返回值;
}
}
每个类中至少存在一个构造方法
如果程序员没有重写构造函数,编译器会自动为该类添加一个无参的构造函数
没有构造方法的类是不存在的
构造方法 public book(){}
和普通方法 public void book(){}的区别在于:
构造方法只在对象实例化的时候调用一次,而普通方法可以通过一个实例化对象调用多次。
构造方法的重载
普通方法可以重载,构造方法是普通方法的特例,因此也是可以重载的。
因为构造方法的方法名必须和类一样,因此只能从参数列表变现不同。
参数个数,参数类型,参数顺序这三者必须至少有一项不同
/**
* @author 86152
*练习,构造方法的重载
*/
class person //声明一个person类
{
public String name; //有两个属性,定义为private 的私有属性更好
public int age;
public person(int age) //两个构造方法,两者的参数列表不同
{
this.age=age;
name="annoymous";
}
public person(int age,String name)
{
this.name=name;
this.age=age;
}
public void talk() //有一个方法
{
System.out.print("my name is:"+name+" and my age is:"+age+"\n");
}
}
public class demo {
public static void main(String []args)
{
person person1=new person(20);
person person2=new person(21,"jack");
person1.talk();
person2.talk();
}
}
注意点:一旦我们声明了显式的构造方法,那么编译器就不再自动生成隐式的构造方法
构造方法的私有化
如果构造方法被声明为private,则该构造方法无法在其他类中被调用。
构造方法的私有化大大限制了类的使用,它的应用场景又是怎样的呢?
在特定需求的场景下,要限制一个类对象的创建,要求一个类只能有一个实例化对象
实例化对象需要构造方法,但构造方法被private私有化起来,只能在该类中用new关键字创建类的实例。通过这个方式我们确保一个类只能创建一个实例化对象。
在软件工程中,这种设计模式被称为单态设计模式
实例应用举例:
wins的回收站是所有逻辑盘共享一个回收站
/**
* @author 86152
*练习,构造方法的私有化
*/
class person
{
String name;
int age;
private person() //构造方法
{
age=21;
name="manager";
}
private static final person PERSON=new person();//final代表对象不可更改,不可被重新实例化,static表示为静态属性,全局共享一个,无论在person外声明多少个对象,最终的实例都是这一个。
public static person getperson()
{
return PERSON;
}
}
public class demo {
public static void main(String []args)
{
person person1=person.getperson();//不能使用new
System.out.print("my name is "+person1.name);
}
}
方法的递归调用
/**
* @author 86152
*练习,方法的递归调用
*/
public class demo {
public static int addrecursion(int n)
{
if(n<=1)
return n;
else
{
return n+addrecursion(n-1);
}
}
public static void main(String []args)
{
demo test=new demo(); //实例化一个对象
int result=test.addrecursion(10);//调用递归方法
System.out.print("递归结果为:"+result);
}
}
实现递归需要方法压栈和弹栈的操作,实现的速度比不同递归慢的多
代码块
代码块用大括号{}将多行代码封装在一起,形成独立的代码区域
{
//代码块
}
代码块的分类
1.普通代码块
在方法名后(方法体内)用一对{}括起来的数据块就是普通代码块。它不同单独存在于类中。
2.构造代码块
/**
* @author 86152
*练习,构造代码块
*/
class person //声明一个person类
{
public String name;
public int age;
{ //使用构造代码块节省代码空间,可以为构造方法定义相同的部分
System.out.print("构造代码块执行...\n");
age=21; //如果不加{}则age不能出现在这个位置,应该分别在构造方法中赋值
}
public person()
{
System.out.print("构造方法1执行...\n");
name="annoymous";
}
public person(String name)
{System.out.print("构造方法2执行...\n");
this.name=name;
}
public void talk()
{
System.out.print("my name is:"+name+" and my age is:"+age+"\n");
}
}
public class demo {
public static void main(String []args)
{
person person1=new person();
person person2=new person("jack");
person1.talk();
person2.talk();
}
}
3.静态代码块
使用static关键字修饰并用大括号{}括起来的代码块称为静态代码块,用来初始化静态成员变量,是最早执行的代码块。
/**
* @author 86152
*练习,静态代码块
*/
public class demo {
static
{
System.out.print("静态代码块执行-----\n");
}
{
System.out.print("构造代码块执行-------\n");
}
public demo()
{
System.out.print("构造方法1执行-------\n");
}
public demo(int n)
{
System.out.print("构造方法2执行-------\n");
}
public static void main(String []args)
{
System.out.print("main方法执行-------\n");
demo d1=new demo();
demo d2=new demo(2);
}
}
从上面的代码可以看出:
1.静态代码块的执行时间比main方法还要早,在类加载时就会被执行
2.静态代码块只执行一次。因此静态代码块可以用来初始化静态变量。静态成员变量是所有类对象共享的,不会受创建对象的个数影响。
4.同步代码块
方法和数组
在基本数据类型构成的数组的基础上抽象出数组对象,整合出一系列具有相同特点的数据,再进一步扩展,便构成功能更强大的“集合”。
数组引用传递
再java语言中,b=a的含义就是将a起个别名“b”。之后,a和b其实就是指向同一个对象。在java中,这种给变量取别名的机制称之为“引用”
一个程序若想运行,必须注入内存,而在内存中必然有其存储地址,通过内存地址,就可以找到我们想要的数据。内存的地址通常很长,不容易记忆,因此给这些地址取个名称,就是引用变量。引用变量存储在一块“堆内存”的区域。
所谓引用,就是java对象在‘堆内存’的地址赋给了多个“栈内存”的变量
C/C++的指针可以被用户直接修改,而在JAVA中对内存的直接修改是被屏蔽的
在java中,所有对象都是通过引用进行修改的。**数组也是一种对象,当数组作为参数传递给方法时,传递的实际上就是该数组对象的引用。**在方法中对数组的所有操作,都会映射到原数组,这也是JAVA面向对象的一个重要特点。
所谓的数组引用传递,就是将一块数组的堆内存空间交由多个栈内存指向。
/**
* @author 86152
*练习,方法和数组
*/
public class demo {
public static void printArr(int []arr)
{
for(int i:arr) //for(变量类型 变量名:循环对象)
{
System.out.print(i+"");
}
System.out.println();
}
public static void print(int in,int []arr)
{
System.out.println("in:"+in);
System.out.print("arr:");
printArr(arr);
}
public static void changeReferValue(int a,int[]myarr) //将myarr的前三位置0,将a加一
{
a+=1;
myarr[0]=0;
myarr[1]=0;
myarr[2]=0;
}
public static void main(String []args)
{
int in=10;
int []arr= {1,2,3,4,5,6,7,8,9,10}; //主函数中对in,arr赋初值
System.out.println("----调用数组引用函数之前---------");
print(in,arr);
System.out.println("----调用数组引用函数之后---------");
changeReferValue(in,arr);
print(in,arr);
}
}
由此可以看出,整型属于基本数据类型,in传递进方法之后,形参a和实参in没有任何关系,
而数组属于引用数据类型,实参arr和形参myarr指向的是同一块代码块,对于myarr的所有操作都会影响arr。
方法中实现排序
/**
* @author 86152
*练习,字符数组冒泡排序
*/
public class demo {
public static void sort(char []arr)
{
for(int i=0;i<arr.length;i++)
{
for(int j=i+1;j<arr.length;j++)
{
if(arr[i]>arr[j])
{
char temp;
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
}
public static void printarr(char []arr)
{
//for(int i:arr)
for(int i=0;i<arr.length;i++)
{
System.out.print(arr[i]);;
}
System.out.println();
}
public static void main(String []args)
{
char []arr= {'A','D','F','E','B','C'};
printarr(arr);
sort(arr);
printarr(arr);
}
}
与数组有关的操作方法
在Java中,针对数组操作的支持主要有两个,数组的克隆和数组的排序。
clone()方法,它将数组复制一份,返回一个新的引用,常用来复制数组。
char []newarr=arr.clone();
不使用排序算法而使用java包中的排序方法
public static void main(String []args)
{
char []arr= {'A','D','F','E','B','C'};
char []newarr=arr.clone(); //使用克隆方法
printarr(arr);
sort(arr);
printarr(arr);
System.out.println("----使用Java系统的排序方法----");
printarr(newarr);
java.util.Arrays.parallelSort(newarr); //使用排序方法
printarr(newarr);
}