クラスとは変数(フィールド)とメソッドをまとめたもの
クラス宣言
「class クラス名」で宣言する
フィールド
クラス宣言の後の「{}」の中に宣言した変数
以下は3つのフィールドを持つAccountクラス
class Account {
String name;
String no;
long balance;
}
※複数のクラスを1つのファイルに記載する場合、mainメソッドのあるクラス名をファイル名にする
インスタンス
「new クラス名()」で生成したクラス型の実体のこと
インスタンスを生成することをインスタンス化という
//Accountクラス型の変数xにインスタンスを代入
Account x = new Account();
※クラスの各フィールドは各々の規定値(0やnull)で初期化される
オブジェクト
クラスのインスタンスと配列の本体の総称
インスタンス変数
インスタンス化したフィールドのこと
フィールド(インスタンス変数)へのアクセス
メンバアクセス演算子(ドット演算子)「.」を使う
//Accountクラスのインスタンスをxに代入
Account x = new Account();
//インスタンス変数「name」に値を代入
x.name = "山田太郎";
//インスタンス変数「name」の値をstrに代入
String str = x.name;
//山田太郎と表示される
System.out.print(str);
コンストラクタ
インスタンス生成時に呼び出されるメソッドでクラス名と同じ
→主にフィールドの初期化などを行う
普通のメソッドと違い、値を返すことができない
→宣言時に戻り値の型を指定しない
//Dogクラス
class Dog {
String name;
double weight;
//コンストラクタ
//(クラス名と同じ、戻り値型の指定なし)
Dog(String str) {
name = str;
}
}
class DogTester {
public static void main(String[] args) {
//コンストラクタで名前を設定
Dog dog1 = Dog("Pochi");
}
}
デフォルトコンストラクタ
コンストラクタを全く定義していない場合、引数なしのデフォルトコンストラクタが自動的に作られる
//コンストラクタが無いクラス
class Dog {
String name;
double weight;
}
この場合、以下のデフォルトコンストラクタが自動的に作られている
======================
Dog() {
}
======================
だから、定義していないコンストラクタを呼んでもエラーにならない
class DogTester {
public static void main(String[] args) {
//デフォルトコンストラクタでインスタンスを生成
Dog dog1 = Dog();
}
}
this
自分自身のインスタンスのことを「this」と表現する
クラスのフィールドと同じ変数や仮引数をつくることができる
→その場合でフィールドにアクセスするには「this.」を変数名の前につける
class Dog {
String name;
double weight;
//仮引数とフィールドが同じ名前
Dog(String name) {
//this.nameでフィールドにアクセスできる
this.name = name;
}
}
自分のクラス内で自分のコンストラクタを呼ぶ場合「this」を使う
class Dog {
String name;
double weight;
//コンストラクタ1
Dog(String str) {
name = str;
}
//コンストラクタ2
Dog(String str, double wt) {
//自分自身のコンストラクタ1をthisで呼ぶ
this(str);
weight = wt;
}
}
メソッド
クラスにはメソッドを持たせることができる
インスタンスメソッド
インスタンスが実行するメソッドでstaticをつけない
class Dog {
String name;
Dog(String name) {
this.name = name;
}
void bow() {
System.out.print("Bow wow!");
}
}
class DogTester {
public static void main(String[] args) {
Dog dog1 = new Dog("Pochi");
//インスタンスメソッドを実行
dog1.bow(); //Bow wow!と表示される
}
}
クラスの配列
クラス型は基本型と同じように配列にできる
class Dog {
void bow() {
System.out.print("Bow wow!");
}
}
class DogTester {
public static void main(String[] args) {
//Dogクラス型の配列(要素数3)
Dog[] dogAry = new Dog[3];
for (int i = 0; i < dogAry.length; i++) {
//Dogクラス型の配列にインスタンスを格納
dogAry[i] = new Dog();
}
//配列の各要素を変数dogに取り出す
for (Dog dog : dogAry) {
//各要素毎にインスタンスメソッドを実行
dog.bow();
}
}
}
クラス変数(静的フィールド)
staticを付けて宣言したフィールドのことで、インスタンスがいくつ生成されても関係無く1つのクラスだけに属する
他のクラスがアクセスする場合は「クラス名.」でアクセスする(自分のクラスのクラス変数の場合は省略可)
class Student {
//クラス変数
static int count = 0;
//コンストラクタ
Student() {
//インスタンス生成する毎にカウントアップ
//自分のクラス変数は「クラス名.」がいらない
count++;
}
}
class StudentTester {
public static void main(String[] args) {
//クラス変数はインスタンスが無くても使える
//カウントを表示(0と表示される)
//他のクラスのクラス変数は「クラス名.」が要る
System.out.println(Student.count);
Student st1 = new Student();
//カウントを表示(1と表示される)
System.out.println(Student.count);
Student st2 = new Student();
//カウントを表示(2と表示される)
System.out.println(Student.count);
}
}
クラスメソッド(静的メソッド)
staticを付けて宣言したメソッドのことで、インスタンスがいくつ生成されても関係無1つのクラスだけに属する
他のクラスがクラスメソッドを呼ぶ場合は「クラス名.」で呼び出す(自分のクラスのクラスメソッドの場合は省略可)
クラスメソッドはインスタンス変数、インスタンスメソッドにアクセスすることはできない
(クラスからはどのインスタンスの変数、メソッドのことだか分からない為)
一方、インスタンスメソッドからは全部の変数、メソッドにアクセスできる
class Student {
//クラス変数
static int count = 0;
//インスタンス変数
int no;
//コンストラクタ
Student() {
//インスタンスメソッドからstatic変数はアクセス可
count++;
//インスタンスメソッドからインスタンス変数もアクセス可
no = count;
}
void showNo() {
//インスタンスメソッドは両方アクセス可
System.out.printf("%d/%d\n", no, count);
}
static void showCount() {
//staticメソッドからはstatic変数はアクセス可
System.out.printf("total:%d", count);
//staticメソッドからはインスタンス変数は×
//System.out.print(no);
}
static void showCount2() {
System.out.print("***");
//staticメソッドからstaticメソッドを呼ぶのはOK
//(自分のクラス内なので「クラス名.」は省略)
showCount();
System.out.println("***");
//staticメソッドからはインスタンスメソッドは×
//showNo();
}
}
class StudentTester {
public static void main(String[] args) {
Student st1 = new Student();
//インスタンスメソッド(1/1と表示)
st1.showNo();
Student st2 = new Student();
//インスタンスメソッド(2/2と表示)
st2.showNo();
//クラスメソッドは「クラス名.」で呼び出す
//(***total:2***と表示)
Student.showCount2();
}
}
デフォルトコンストラクタの注意点
コンストラクタが1つでも定義されている場合、デフォルトコンストラクタは自動的に作成されない
→つまりコンストラクタが1つも無い場合のみデフォルトコンストラクタは作られる
class Dog {
String name;
//コンストラクタ
Dog(String name) {
this.name = name;
}
}
class DogTester {
public static void main(String[] args) {
//定義されてるコンストラクタ
Dog dog1 = new Dog("Poch");
//コンパイルエラー!!
//デフォルトコンストラクタは無い!
Dog dog2 = new Dog();
}
}
アクセス修飾子
フィールドやメソッドの前に「private」と付けると他のクラスからアクセスすることができなくなる
→自分のクラスからアクセスすることはOK
フィールドやメソッドの前に「public」と付けると他のクラスにも公開され、全てのクラスがアクセス可能となる
何も付けないと同一パッケージのクラスからのみアクセスが可能となる
→異なるパッケージのクラスからはアクセスできない
class Dog {
//プライベートな変数
private String name;
//コンストラクタ
Dog(String name) {
//同じクラス内ならアクセス可能
this.name = name;
}
void showName() {
//同じクラス内ならアクセス可能
System.out.println(name);
}
}
class DogTester {
public static void main(String[] args) {
//コンストラクタ
Dog dog1 = new Dog("Pochi");
dog1.showName();
//コンパイルエラー
//他のクラスからは書き換えできない
dog1.name = "Taro";
//コンパイルエラー
//他のクラスからはアクセスできない
System.out.print(dog1.name);
}
}
アクセサ(アクセッサ)
フィールドの値を設定したり取得したりするメソッドのことで、主にプライベートなフィールドにアクセスするために作成する
セッタ(setter)
フィールドの値を設定するメソッドのことでフィールド名の前に「set」をつける
ゲッタ(getter)
フィールドの値を取得するメソッドのことでフィールド名の前に「get」をつける
class Dog {
//フィールドname(プライベート)
private String name;
//セッタ(nameを設定するメソッド)
void setName(String name) {
this.name = name;
}
//ゲッタ(nameを取得するメソッド)
String getName() {
return name;
}
}
class DogTester {
public static void main(String[] args) {
//コンストラクタ
Dog dog1 = new Dog();
//セッタでnameを設定
dog1.setName("Pochi");
//ゲッタでnameを取得
String dogName = dog1.getName();
//Pochiと表示される
System.out.print(dogName);
}
}
カプセル化
フィールドをprivateにして、その値の更新はアクセッサなどを使用(直接アクセスしない)すること
オブジェクト指向の三大要素
カプセル化、継承、ポリモーフィズム(多相性、多態性、多様性)
1クラス1ファイル
基本的に1つのファイルには1つのクラスのみを記述して、独立性を高めるべきである
→複数のクラスを1つのファイルに書くのはテスト的なもののみにする
4つのアクセス修飾子
public(公開),protected(パッケージ+継承先),無し(パッケージ),private(非公開)
コレクション
たくさんのインスタンスを管理する目的を持った、クラスやインターフェイスの総称(java.utilパッケージ)
→便利な配列のようなもの
ArrayList
コレクションの代表格
宣言
<型>(ジェネリクス)に入れたい型を書く
ArrayList<String> list=new ArrayList<String>();
→Stringを入れるArrayList
ジェネリクスには基本型が指定できないのでラッパークラスを使う
int→Integer, double→Double,・・・
ArrayList<Integer> list=new ArrayList<Integer>();
→Int(int)を入れるArrayList
要素の追加、取得
add(追加したい値)メソッドとget(取得したいindex)を使う
ArrayList<String> list=new ArrayList<String>();
list.add("Alice");
//「Alice」と表示
System.out.print(list.get(0));
要素数の取得
sizeメソッドで取得
ArrayList<String> list=new ArrayList<String>();
list.add("Alice");
list.add("Bob");
list.add("Chris");
list.add("Elmo");
for(int i=0;i<list.size();i++){
System.out.println(i+":"+list.get(i));
}
要素の削除、置き換え
remove(削除したい値)、remove(index)、
set(index, 置き換える値)を使う
//値が「Alice」の要素を削除
list.remove("Alice");
//インデックスが「3」の要素を削除
list.remove(3);
//インデックス「0」の要素を「Bob」に置換
list.set(0, "Bob");
要素にある値が含まれているかどうか
containsメソッドで判定
ArrayList<String> list=new ArrayList<String>();
list.add("Alice");
list.add("Bob");
if(list.contains("Alice")){
System.out.println("含まれています");
}else{
System.out.println("含まれていません");
}
オートボクシング、アンボクシング
ラッパークラスを使用時に自動変換してくれる
ArrayList<Integer> list=new ArrayList<Integer>();
//本来はこのように書く必要がある
list.add(new Integer(123));
//オートボクシング
list.add(456);
//本来はこのように書く必要がある
Integer num = list.get(0);
//アンボクシング
int num2 = list.add(1);
API
Application Programming Interface
システム同士がお互いにやり取りする決め事のこと
クラス型の変数の代入
クラス型の変数にインスタンスを代入すると、そのインスタンスへの参照(アドレス)がコピーされる
→インスタンスの実体はコピーされない!!
同じ参照を持つクラス型変数の参照先を変更すると、他の参照先も変更される
→同じ1つの実体に複数の参照が紐づいているから
class ClassA {
int num;
ClassA(int num) {
this.num = num;
}
}
class Test1 {
public static void main(String[] args) {
//インスタンスを生成
ClassA a = new ClassA(123);
//123と表示される
System.out.println(a.num);
//クラス型変数を代入
ClassA b = a;
//bのnumを変更したのに…
b.num = 567;
//aの内容も変更されてしまう
//567と表示される
System.out.println(a.num);
}
}
クラス型変数の比較
クラス型変数を「==」で比較しても同じ参照(アドレス)かどうかを比較するだけ
→同じクラスで全く同じフィールド値のインスタンス同士を比較してもtrueにはならない!
引数としてのクラス型変数
メソッドの引数にクラス型を渡す場合は、そのインスタンスの参照(アドレス)を渡すことになる
→インスタンスの実体が渡されるわけではない!
クラス型の配列
クラス型の配列を作ることができ、要素として格納されるのはインスタンスの参照(アドレス)である
→インスタンスの実体が格納されるわけではない!
class ClassA {
int num;
ClassA(int num) {
this.num = num;
}
}
class Test1 {
public static void main(String[] args) {
//要素数3のクラス型の配列を生成
ClassA[] ary1 = new ClassA[3];
//インスタンスを生成
ClassA a = new ClassA(1);
//クラス型の配列にインスタンスを格納
ary1[0] = a;
//生成と同時に格納もできる
ary1[1] = new ClassA(2);
//インスタンスを生成
ClassA b = new ClassA(3);
ClassA c = new ClassA(4);
ClassA d = new ClassA(5);
//配列を生成と同時に初期化もできる
ClassA[] ary2 = {b, c, d};
//インスタンスを生成しながら初期化もできる
ClassA[] ary3 = {
new ClassA(6),
new ClassA(7),
new ClassA(8),
};
}
}
同一クラス内のコンストラクタの呼び出し
this(・・・)という形式で同一クラスのコンストラクタを呼べる、ただしコンストラクタ内の先頭にしか書くことができない
→それ以外で呼ぼうとするとコンパイルエラー
class ClassA {
int num1;
int num2;
ClassA(int num1) {
this.num1 = num2;
}
ClassA(int num1, int num2) {
//ここで呼ぶのはOK
this(num1);
this.num2 = num2;
//ここで呼ぶとエラー!!
this(num1);
}
}
toStringメソッド
「public String toString()」を定義すると、そのクラス型の変数をprintなどで表示しようとしたり、文字列を連結しようとするときに自動でこのメソッドが呼ばれる
class ClassA {
int num;
ClassA(int num) {
this.num = num;
}
//toStringメソッドを実装
public String toString() {
return "-->" + num + "<--";
}
}
class Test1 {
public static void main(String[] args) {
//インスタンスを生成
ClassA a = new ClassA(1);
//printしようとするとtoStringが自動で呼ばれる
//「-->1<--」と表示される
System.out.println(a);
//文字列連結でもtoStringメソッドが自動で呼ばれる
String str = "***" + a + "***";
//「***-->1<--***」と表示される
System.out.println(str);
}
}
クラス型のフィールド
クラス型のフィールドに格納されるのはインスタンスの参照(アドレス)である
→複数のインスタンスに同じ参照を代入すると、1つ変更しただけで全て変更されてしまう!
class ClassA {
int num;
ClassA(int num) {
this.num = num;
}
}
class ClassB {
//クラス型のフィールド
ClassA a;
//引数にクラス型
ClassB(ClassA a) {
this.a = a;
}
void printNum() {
System.out.println(a.num);
}
void setNum(int num) {
a.num = num;
}
}
class Test1 {
public static void main(String[] args) {
//Aのインスタンスを生成
ClassA a = new ClassA(1);
//aを引数にBのインスタンスbを生成
ClassB b = new ClassB(a);
//「1」と表示される
b.printNum();
//aを引数にBのインスタンスcを生成
ClassB c = new ClassB(a);
//インスタンスcのnumを変更すると…
c.setNum(22);
//「22」と表示される
c.printNum();
//インスタンスbのnumも変更されてしまう
//「22」と表示される
b.printNum();
//引数としたaのnumを変更すると…
a.num = 333;
//bとcのnumも変更されてしまう
//「333」と表示される
b.printNum();
//「333」と表示される
c.printNum();
//このようにすれば問題ない
ClassB d = new ClassB(new ClassA(555));
ClassB e = new ClassB(new ClassA(666));
d.setNum(777);
//「777」と表示される
d.printNum();
//「666」と表示される
e.printNum();
}
}
クラス型を返すメソッド
クラス型のフィールドの値をメソッドの戻り値として返すと、そのフィールドへの参照(アドレス)を返すことになる
→その参照を通じてフィールドにアクセスできてしまうので、セキュリティ的に問題あり!
class ClassA {
int num;
ClassA(int num) {
this.num = num;
}
}
class ClassB {
//クラス型のフィールド
private ClassA a;
ClassB(ClassA a) {
this.a = a;
}
//クラス型のフィールド値を返す
ClassA getClassA() {
return a;
}
void printNum() {
System.out.println(a.num);
}
}
class Test1 {
public static void main(String[] args) {
//インスタンスを生成
ClassB b = new ClassB(new ClassA(1));
//「1」と表示される
b.printNum();
//クラス型のフィールドの値を取得
ClassA a = b.getClassA();
//aのnumを書き換えると…
a.num = 22;
//プライベートなbのnumが変更される
//「22」と表示される
b.printNum();
}
}
============================
class ClassB {
//このようにすれば問題なし
ClassA getClassA() {
return new ClassA(a.num);
}
============================
has-A
あるクラスがその一部として別のクラスを持つこと
→クラス型のフィールドを定義することで実現できる
コンポジション
あるインスタンスが内部に別のインスタンスを持っている構造のこと
→コンポジションはhas-Aの関係となる
コンポジションにより、あるクラスを拡張したクラスを作ることができる
class ClassA {
void sayHello() {
System.out.println("Hello");
}
}
class ClassB {
//ClassAのインスタンスを持つ
private ClassA a = new ClassA();
//ClassAのメソッドを呼ぶ
void sayHello() {
a.sayHello();
}
//ClassBだけのメソッドを追加
void sayHoge() {
System.out.println("hoge");
}
}
class Test1 {
public static void main(String[] args) {
//インスタンスを生成
ClassA a = new ClassA();
//「Hello」と表示
a.sayHello();
//コンポジションでClassAを拡張したClassB
ClassB b = new ClassB();
//ClassAと同じメソッドを持っていて…
//「Hello」と表示
b.sayHello();
//ClassB独自のメソッドを拡張できる
//「hoge」と表示
b.sayHoge();
}
}
クラス変数
staticを付けて宣言されたフィールドで、そのクラスの全インスタンスで共有すべき変数
→クラス変数の実体は1つ宣言する毎に1個だけつくられる
クラス変数のアクセス
異なるクラスのクラス変数にアクセスする場合は「クラス名.」を頭に付ける
→自分のクラス内ならば変数名だけでOK
※ただし、ローカル変数や仮引数名としてクラス変数と同じ名前を宣言できてしまうので、その場合は「クラス名.」を頭に付けてアクセスする
「インスタンス変数名.」でもアクセスできるが意味合い的にも紛らわしいのでやらない!!
class ClassA {
//クラス変数
static int num = 123;
static void display() {
//自分のクラス内ならnumでOK
System.out.println(num);
}
static void display(int num) {
//仮引数に同じ名前が使われている
System.out.println(ClassA.num + num);
}
static void display2() {
//ローカル変数に同じ名前が使われている
int num = 567;
System.out.println(ClassA.num + num);
}
}
class ClassB {
public static void main(String[] args) {
//他のクラスのクラス変数にアクセス
//「123」と表示される
System.out.println(ClassA.num);
//インスタンスを生成
ClassA a = new ClassA();
//「インスタンス変数.」でも呼べる
//しかし、紛らわしいのでやらない!!
System.out.println(a.num);
}
}
publicかつfinalなクラス変数の公開
クラスの利用者に公開すべき便利な定数はpublic static finalで宣言するとよい
→例)Math.PI…円周率
クラスメソッド
staticを付けたメソッドでクラス全体に関わる処理などを記載する
→呼び出し方はクラス変数と同じで「クラス名.」で呼べる、その他の注意点も同じ
オーバーロードはクラスメソッドとインスタンスメソッドにまたがって行える
クラスメソッド内ではインスタンス変数とインスタンスメソッドにはアクセスできない
→どのインスタンスの変数やメソッドにアクセスするのか分からない為
class ClassA {
//クラス変数
static int num = 123;
//インスタンス変数
int cnt = 999;
//クラスメソッド
static void display() {
//クラスメソッド内でクラス変数はOK
System.out.println(num);
//クラスメソッド内でインスタンス変数は×
//System.out.println(cnt);
//クラスメソッド内でクラスメソッドはOK
hoge();
//クラスメソッド内でインスタンスメソッドは×
//display(1);
}
//クラスメソッド
static void hoge() {
System.out.println("hoge");
}
//インスタンスメソッド
//staticにまたがりオーバーロード
void display(int n) {
System.out.println(n);
}
}
class ClassB {
public static void main(String[] args) {
//他のクラスのクラスメソッドを呼ぶ
ClassA.display();
//インスタンスを生成
ClassA a = new ClassA();
//「インスタンス変数.」でも呼べる
//しかし、紛らわしいのでやらない!!
a.display();
}
}
ユーティリティクラス
インスタンス変数を持たずにクラスメソッドのみを提供するクラス
→代表例としてMathクラス
クラス初期化子(イニシャライザー)
クラス宣言内のstaticを付けたブロック「{・・・}」のことで、クラスを初めて利用する前に実行されている処理
→クラス変数を初期化するために使うとよい
※クラス初期化子は一度しか実行されない
class ClassA {
//クラス変数
static int num = 0;
//クラス初期化子
static {
num += 123;
}
}
class ClassB {
public static void main(String[] args) {
//クラス初期化子が実行される
//123と表示される
System.out.println(ClassA.num);
//クラス初期化子は一度きり
//123と表示される
System.out.println(ClassA.num);
}
}
インスタンス初期化子(イニシャライザー)
クラス宣言内のブロック「{・・・}」のことで、インスタンス生成時(コンストラクタの前)に実行される処理
→全てのコンストラクタで共通に行う処理を記載するとよい
class ClassA {
//クラス変数
static int count = 0;
int num = 0;
//インスタンス初期化子
{
count++;
num = count;
}
//コンストラクタ
ClassA() {
}
//コンストラクタ(引数あり)
ClassA(int num) {
this.num += num;
}
}
class ClassB {
public static void main(String[] args) {
//インスタンス初期化子が実行
ClassA a1 = new ClassA();
//「1」と表示
System.out.println(a1.num);
//インスタンス初期化子が実行
ClassA a2 = new ClassA(10);
//「12」と表示
System.out.println(a2.num);
}
}
パッケージ
パッケージはクラスやインターフェイスをフォルダ階層にまとめたもので、名前の重複回避などの意味がある
→重複しないようにインターネットアドレスの逆順に並べたものを使うとよい(jp.co.yahooなど)
[java]
|--[util]
| |--Scanner
| |--Random
単純名、完全限定名
クラス名のみが単純名、頭にパッケージ名を付けるのが完全限定名
java.utilパッケージのScannerクラスを例にすると…
単純名:Scanner
完全限定名:java.util.Scanner
単一型インポート宣言
「import 完全限定名」でインポートすると、その完全限定名で指定したモノがソース内で単純名で利用できる
オンデマンド型インポート宣言
「import パッケージ名.*」でインポートすると、そのパッケージ内のクラスやインターフェイスが単純名で利用できる
※オンデマンド型インポートはクラス名が重複する可能性があるので多用すべきではない!!
※必要に応じてインポートされるので、そのパッケージの全てをインポートするわけではない!
java.langパッケージの自動インポート
java.langパッケージはインポートしなくても、いきなり単純名で使用できる
静的インポート宣言
静的なメンバであるクラス変数、クラスメソッドをインポートでき、宣言の方法は2種類ある
単一インポート宣言
import static 型名.識別子名;
オンデマンド静的インポート宣言
import static 型名.*;
import java.util.Scanner;
import static java.lang.Math.PI;
class Test {
public static void main(String[] args) {
//インポートしているので単純名で使える
Scanner stdIn = new Scanner(System.in);
//静的インポートしているので変数名で使える
System.out.printf("%.2f", PI);
}
}
パッケージ宣言
「packege パッケージ名;」の形式で行い、ソースコードの先頭に書かなければならない
※パッケージ宣言は無くてもよい、2個以上書くことはできない
※パッケージ名は全て小文字とすべき(クラス名と被らないようにする為)
無名パッケージ
パッケージ宣言を書かない場合は、無名パッケージに所属することになる
※テスト的なモノ以外はパッケージに所属させるべきである
同一のパッケージ内のクラスは単純名で使える
パッケージとディレクトリ
パッケージを作成する場合は、パッケージ名と同一のディレクトリの中にファイルを置く
クラスのアクセス制御
publicクラス
public宣言されたクラスでパッケージとは無関係に利用できる
※publicクラスは1ファイルに1個
非publicクラス
publicを付けずに宣言されたクラスで同一パッケージ内以外は利用できない
メンバのアクセス制御
publicクラスの場合、publicを付けたメンバが公開アクセスとなる
非publicクラスの場合、publicを付けたメンバはパッケージアクセスとなる
0 件のコメント:
コメントを投稿