概要
入門
概要概要
前に説明したループ操作でコードの重複の問題を解決できますが、この時点で繰り返されるコードは定期的である必要があります。それで、ループ操作はすべてのコード重複を解決できますか?答えは間違いなくノーです。たとえば、繰り返される操作の特定の機能では、ループを実現できません。メソッドを使用できます。
飛行機の戦争ゲームを書くとき、プログラムは実行プロセス中に継続的に弾丸を発射する必要があります。弾丸を発射する機能のために200行のコードを書く必要があるとすると、弾丸を発射するたびにこれらの200行のコードを繰り返し書く必要があります。このようなプログラムは低すぎます。開発では、DRYの原則(Do n't Repeat Youself)に従う必要があります-繰り返しは多くのメンテナンスコストを意味するため、独自のコードを繰り返さないでください。関数型コードを変更する場合は、繰り返されるすべての場所を変更する必要があります。繰り返されるすべての場所を変更できることをあえて確認しますか?退屈しませんか?
関数型コードの繰り返し記述の問題を解決するために、弾丸を発射するコードを抽出してコードブロック({}のペア)に入れ、このコードに一意の名前を付けることができます。弾丸が発射される弾丸を発射するための機能コードは、この名前で直接呼び出すことができます。このコードブロックをメソッドと呼びます。
関数操作の操作を実行するステートメントをまとめてパッケージ化することです。
利点
- 手順を短く明確にします。
- プログラムのメンテナンスに役立ちます。
- プログラム開発の効率を向上させることができます。
- コードの再利用性が向上しました。
定義と使用
ステートメント形式:
[修饰符] 方法返回值类型 方法名(形参列表) {
方法体;
return 返回值;
}
//有返回值类型的方法
public static int add(int a, int b, int c ){
//求和
int k = a + b + c;
return k;
}
//没有返回值的方法,没有形参
public static void printStar(){
//打印5行5列的星星
for(int i=1;i<=5;i++){
for(int j=1;j<=5;j++){
System.out.print("* ");
}
System.out.println();
}
}
-
**アクセス修飾子:**メソッドがアクセスできるアクセス許可の範囲。
-
**戻り値のタイプ:**メソッドが値を返さない場合はvoidとして指定します。メソッドに戻り値がある場合は、戻り値のタイプを指定し、メソッド本体でreturnステートメントを使用する必要があります。値を返します。
-
**メソッド名:**メソッドの名前を定義します。取引主体識別子を使用する必要があります。名前の意味を参照してください。
-
**正式なパラメータリスト:**複数のパラメータが存在する可能性があります。複数のパラメータはコンマで区切られます。各パラメータは、スペースで区切られたパラメータタイプとパラメータ名で構成されます。
転送:
メソッドを定義した後、それを使用する場合は、メソッドを呼び出す必要があります。呼び出し中に、呼び出しの制御がメソッド呼び出し元からメソッドに移されます。メソッドがreturnまたは}終了を検出すると、呼び出し元の権利が呼び出し元に返されます。それは「どこからどこへ行くか」というルーチンです。
方法名([实参列表])
注意:
-
メソッドは呼び出されず、実行されません
-
戻り値、受信変数または匿名受信(出力または呼び出し)があります
-
仮パラメータを指定するメソッドを定義し、実際のパラメータを指定するメソッドを呼び出します
-
メソッド呼び出しには、同じ数の仮パラメーターと実パラメーターが必要であり、タイプは一致します
メソッドの詳細
voidキーワード
voidメソッド。値を返しません。
public static void print() {
for(int i=1;i<=9;i++) {
for(int j=1;j<=i;j++) {
System.out.print(j+"*"+i+"="+i*j+"\t");
}
System.out.println();//换行
}
}
戻り値型のメソッドは、戻り値を引き出す必要があります。
public static int getSum(int a,int b){
return a+b;
}
キーワードを返す
returnは、exitメソッドまたは戻り値です。
注:スコープに戻った後、コードは存在できません
public static int getSum(int a,int b){
return a+b;
System.out.println("return后不能存在代码!!!"); //不可达语句
}
戻りステートメント:
-
returnステートメントは、任意のメソッドに表示できます(戻り値の有無にかかわらず)
-
returnステートメントは、戻り値のないメソッドの早い段階でメソッドを終了するために使用されます
//打印出1~5之间前两个数 public static void test(){ for(int i=1;i<=5;i++){ if(i==3){ return; //结束方法 } System.out.println(i); } }
-
returnステートメントには、戻り値を持つメソッドに2つの関数があります。メソッドを早期に終了することと結果を送信することです。
//求出1~100之间前5个能被2整除数的和 public static int getSum(int a,int b){ int sum=0; //和 for(int i=1;i<=100;i++){ sum+=i; if(i==5){ return sum; //1)提前结束方法 2) 带出返回值 } } }
-
メソッドは1つのreturnステートメントしか実行できません
-
実行する必要のあるreturnステートメントの後に、書き込まれたステートメントは到達不能ステートメントです。プログラムはこのステートメントを自動的に検出し、実行されることはなく、エラーが報告されます。
-
ループの無条件の中断の後にステートメントを書くと、到達不能なステートメントが表示されます
-
無限ループ(ブレークで終わらない無限ループ)の後にステートメントを書くと、到達不能なステートメントが表示されます
思考角度
メソッドを作成するときは、次の4つの側面について考えてください。
1)、メソッドの機能を決定します
2)、メソッドの名前を決定します
3)このメソッドが独立して実行できるかどうか、独立することはできません。正式なパラメーターを決定するための計算に参加するには、外部データが必要です。
4)このメソッドが完了した後、結果は呼び出しサイトでの後続の操作に直接影響しますか?影響する場合は戻り値の型を決定します。影響しない場合は無効です。
署名
メソッドのシグネチャは、クラスの一意性を保証します。メソッドのシグニチャは、メソッド名と仮パラメータのみを調べます
(型の数と順序)、修飾子の戻り値の型と仮パラメーター名とは関係ありません。
public static void getSum(int x,int y){
} -->getSum(int x,int y)为方法签名
タイプ互換
メソッドを呼び出すとき、フォームは実際のパラメーターに参加し、受信タイプ、戻り値のタイプ、および戻り値のタイプは互換性を維持する必要があります。
①仮パラメータ> =実パラメータ
public static void main(String[] args) {
// int i=5;
byte i=5;
int x=test(i); //i实参
}
public static int test(int d){
//d形参
return 'a';
}
②受信タイプ> =戻り値タイプ> =戻りタイプ
public static void main(String[] args) {
int x=test(5); //x为接收返回值的变量类型
}
//int为方法的返回值类型(规定return后面数据的值只能<=int)
public static int test(int d){
//d形参
return 'a'; //return后面数据的类型
}
値渡しと参照渡し
値の転送と参照の転送:
いわゆる値の転送とは、オブジェクトの値のみがターゲットオブジェクトに転送されることを意味します。これは、コピーと同等です。システムは、ターゲットオブジェクトに対して同じメモリスペースを再度開きます。
public static void main(String[] args) {
byte i=5;
test(i); //相当于test(5) -->值传递
System.out.println(i); //5
}
public static void test(int i){
i++; //局部变量i++;
}
いわゆる参照とは、メモリ内のオブジェクトのアドレスがターゲットオブジェクトに渡されることを意味します。これは、ターゲットオブジェクトと元のオブジェクトを同じメモリストレージスペースに対応させることと同じです。このとき、対象オブジェクトを変更すると、メモリ内のデータも変更されます。
public static void main(String[] args) {
Person p = new Person("张三",18);
test(p); //i实参
System.out.println(p.age); //引用传递|p指向对象的地址值
}
public static void test(Person p){
p.age++;
}
メモリ分割:
JVMメモリ分割:
スタックの機能:
ステーションによって記述された時間メソッド実行のメモリモデル。各メソッドが呼び出され、スタックフレームが作成されます()
プログラムの実行中、メソッドのメモリ分析:
public class MethodTest {
public static void main(String[] args) {
int w=5;
int h=7;
int area=getArea(w,h);
System.out.println(area);
}
//求面积
public static int getArea(int w,int h) {
return w*h;
}
}
プロセス1:
1)プログラムを実行する必要があります。javaコマンドを実行すると、クラス情報MethodTest.classがメモリにロードされます。
2)仮想マシンJVMがmainメソッドを呼び出し、mainメソッドがスタックにプッシュされ、スタック内のmainメソッドのスタックフレームが開かれ、mainに表示されるローカル変数が格納されます。
int w = 5; int h = 35;
3)メインメソッドでgetArea()メソッドが呼び出され、スタック内のgetAreaメソッドのスタックフレームが開かれます。
4)メソッドはスタックをプッシュして実行し、int w = 5; int h = 7を割り当てます。結果を計算して35を返します。結果をメソッドの呼び出し元に返します。
5)メソッドgetAreaが実行され、ポップスタックがメモリを解放します
6)mainメソッドでコンテンツの実行を続行し、ローカル変数int area = 35をスタックスペースに格納します。getAreaメソッドの戻り値を領域に割り当てます。
7)mainメソッドが実行された後、ポップスタックはメモリスペースを解放します
メソッドのオーバーロード
一般的に、同じファンクションポイントを持つメソッドはオーバーロードに適しており、オーバーロードは次の要件を満たす必要があります。
①同じクラスである必要があります
②メソッド名は同じである必要があります
③パラメータリストが異なります
public class Demo {
//一个普通得方法,不带参数,无返回值
public void add(){
//method body
}
//重载上面的方法,并且带了一个整形参数,无返回值
public void add(int a){
//method body
}
//重载上面的方法,并且带了两个整型参数,返回值为int型
public int add(int a,int b){
//method body
return 0;
}
}
注:メソッドのオーバーロードは、戻り値とは関係ありません。
パラメータリストは異なります。
パラメータの数が異なります。
パラメータの対応するデータ型が異なります。
パラメータの順序が異なります(タイプが異なれば位置を交換できます)
再帰的構造
再帰は、問題を解決する、つまり問題を徐々に単純化するための一般的な方法です。再帰の基本的な考え方は「自分自身を呼び出すことです」。再帰テクノロジーを使用する方法は、直接または間接的に自分自身を呼び出します。再帰を使用すると、単純なプログラムを使用していくつかの複雑な問題を解決できます。たとえば、ほとんどの種類は再帰アルゴリズムを使用します。
再帰構造は2つの部分で構成されています。
- 再帰ヘッダーを定義します。回答:独自のメソッドを呼び出さない場合。頭がない場合は、無限ループに陥ります。
- 再帰的なボディ。回答:いつ独自のメソッドを呼び出す必要がありますか?
public static void print(int i) {
System.out.println(i);
if(i==10){
//递归头
return; //提前结束方法
}
print(++i); //递归
}
public static void main(String[] args) {
print(1); //打印1~10之间的数据
}
public static void recursion(int i) {
System.out.println("抱着");
if (i==0) {
//临界条件
System.out.println("我的小鲤鱼");
} else {
recursion(--i); // 递归调用
}
System.out.println("的我");
}
public static void main(String[] args) {
System.out.println("吓得我抱起了");
recursion(2);
}
再帰の欠陥:
簡単な手順は、再帰の利点の1つです。ただし、再帰呼び出しは大量のシステムスタックを占有し、大量のメモリを消費します。再帰呼び出しのレベルが多い場合、速度はループよりもはるかに遅くなります。したがって、再度使用する場合は注意してください。
**注:**再帰によって解決できる問題は、反復によっても解決できます。ただし、再帰的方法は問題をより自然に反映でき、理解とデバッグが容易であり、効率が重視されない場合は再帰を使用できます。
高いパフォーマンスが必要な場合は、再帰の使用を避けてください。再帰呼び出しには時間とメモリが必要です。