void setInformation(){} void setInformation(String name){} int sum(int data1,int data2){}
return;
对于返回值为void的方法也可以使用return语句,此时该语句的作用仅仅在于结束方法调用。
抽象数据类型:可以理解为将不同类型的数据的集合组成一个整体用来描述一种新的事务。
定义类的成员变量:
class 类名{ 成员变量类型 变量名称; …… }
成员变量的类型 | 默认初始值 |
---|---|
数值类型(byte、short、int、long、char、float、double) | 0 |
boolean型 | false |
引用类型 | null |
定义类的方法:
class 类名{ 修饰词 返回值类型 方法,名称([参数列表]){ 方法体…… } …… }
new 类名();
除了8种基本类型之外,用类、接口、数组等声明的变量都称之为引用类型变量,简称“引用”。
Student s = new Student(); s.name = "lisi" s.age = 18;
//错误举例: public class Cashier{ public boolean pay(double money){……} public boolean pay(double money){……} } //正确举例: public class Cashier{ public boolean pay(double money){……} public boolean pay(String cardId,String cardPwd){……} }
public class Cashier{ public boolean pay(double money){……} public boolean pay(String cardId,String cardPwd){……} }
[访问修饰符] 类名(){ //构造方法体 }
class Student{ String name; int age; Student(String name1,int age1){ name = name1; age = age1; } } class TestStudent{ public static void main(String[] args{ Student s = new Student("lisi",25); } }
创建对象时,构造方法写在new关键字后,可以理解为——“new”创建了对象,而构造方法对该对象进行了初始化。
this关键字用在方法体中,用于指向调用该方法的当前对象;简单来说——“哪个对象调用方法,this指的就是哪个对象。”严格来讲在方法中需要通过this关键字指明当前对象。
public void study(){ System.out.println(this.name+"在学习!"); }
为了方便起见,在没有歧义的情况下可以省略this。
public void study(){ System.out.println(name+"在学习!"); }
在构造方法中,用来初始化成员变量的参数一般和成员变量取相同的名字,这样会有利于代码的可读性,但此时就必须通过this关键字来区分成员变量和参数了(this不可省略)。
Student(String name,int age){ this.name = name; thia.age = age; }
class Student{ String name; int age; Student(String name1,int age1){ name = name1; age = age1; } } class TestStudent{ public static void main(String[] args){ Student s = new Student(); //编译错误,当定义了构造方法之后,编译器就不会提供默认的构造方法了! } }
为了使用方便,可以对一个类定义多个构造方法,这些构造方法都有相同的名称(类名),方法参数不同;称之为构造方法的重载。
在创建对象时,Java编译器会根据不同参数调用不同的构造方法。
Student s1 = new Student("lisi",18); //对应的构造方法为: Student(String name1,int age1){ …… } Student s2 = new Student(); //对应的构造方法为: Student(){ …… }
Student(String name1,int age1){ name = name1; age = age1; } Student(){ this("baby",1); }
数组的元素都可以看成数组对象的成员变量(只不过类型全部一样)。
Student[] array = new Student[3]; array[0] = new Student(); array[1] = new Student(); array[2] = new Student();
int[][] array = new int[3][]; array[0] = new int[2]; array[1] = new int[3]; array[2] = new int[2];
array指向一个数组,该数组有三个元素,每一个元素都是int类型数组,长度分别是2,3,2。
int[][] array = new int[3][4];
这样的数组可以用来表示“矩阵”这样的数据结构;在其他语言中有专门表示这样结构的所谓二维数组,而严格来讲,Java中没有真正的二维数组。
class Teacher extends Person{ …… }
个人理解:
Java不像其他的语言,可以继承多个超类;这样的好处就是“继承树”比较明了;也便于后面的相应操作(譬如对于一组类进行一个特性的更改,那么只要更改他们共同的超类就行了!);也就是说,所有类的超类都是Object类。
另外,Java还有接口来辅助实现多种属性的继承,在一定意义上近乎实现了“多继承”。
public Student(){ super();//编译器会自动加入 …… }
注意:super关键字必须位于派生类构造方法的第一行。
个人理解:其实就如同建房子,不打地基,如何建房,所以先建立超类的对象,再建立派生类的对象!
class Person{ String name; int age; Person(String name,int age){ this.name = name; this.age = age; } } class Student extends Person{ double grade; Student(String name,int age,double grade){ super(name,age); this.grade = grade; } public void setGrade(double grade){ this.grade = grade; } public static void main(String[] args){ Person p = new Student("lisi",18,97); //超类的引用可以指向派生类的对象。 } }
class Person{ String name; int age; Person(String name,int age){ this.name = name; this.age = age; } } class Student extends Person{ double grade; Student(String name,int age,double grade){ super(name,age); this.grade = grade; } public void setGrade(double grade){ this.grade = grade; } public static void main(String[] args){ Person p = new Student("lisi",18,97); p.setGrade(60);//error! } }
注意:Java编译器会根据引用的类型,而不是对象的类型来检查调用是否合理匹配!
子类可以重写(覆盖)继承自父类的方法,即方法名和参数列表与父类的方法相同;但方法的实现不同。
重写遵循的原则——“两同两小一大”原则:
public class Person { public void Print(){ System.out.println("这是一个人!"); } } public class Teacher extends Person{ @Override public void Print() { System.out.println("这是一个老师!"); } public static void main(String[] args) { Person p = new Teacher(); p.Print(); Teacher t = new Teacher(); t.Print(); } } //output: // 这是一个老师! //这是一个老师!
补充:当子类对象的重写方法被调用时(无论是通过子类的引用调用,还是通过父类的引用调用),运行的是子类的重写后的版本。
public class Person { public void Print(){ System.out.println("这是一个人!"); } } public class Teacher extends Person{ @Override public void Print() { super.Print(); System.out.println("这是一个老师!"); } public static void main(String[] args) { Person p = new Teacher(); p.Print(); Teacher t = new Teacher(); t.Print(); } } //output: //这是一个人! //这是一个老师! //这是一个人! //这是一个老师!
补充:子类重写方法中的super.Print();调用了父类的版本,这样的语法通常用于子类的重写方法在父类方法的基础上进行功能扩展。
个人理解:有点像C++里面的命名空间,将彼此之间间隔开来,形成不同的作用域。
package 包名; class 类名{ …… }
补充:package语句必须写在Java源程序文件的最开始,在类定义之前。一旦使用package语句指定了包名,此时类的全称应该是“包名.类名”;这就使得在不同的包中定义相同的类而不会混淆。
package 包名1.包名2...包名n;
package org.apache.commons.lang.StringUtils
解释:StringUtils是类名,而org.apache.commons.lang是多层包名,其含义如下:org.apache表示公司或组织的信息(是这个公司或者组织域名的反写);commons表示项目的名称信息;lang表示模块的名称信息。
com.baidu.www.commons.lang.StringUtils stringutils = new com.baidu.www.commons.lang.StringUtils();
import 类的全局限定名(包名+类名)
import com.baidu.www.commons.lang.StringUtils; class Test{ public static void main(String[] args){ StringUtils stringutils = new StringUtils(); } }
补充:public修饰的内容是对外提供可以被调用的功能,需要相对稳定;private修饰的内容是对内实现的封装,如果“公开”会增加维护的成本。
修饰符 | 本类 | 同一包中的类 | 子类 | 其他类 |
---|---|---|---|---|
public | 可以 | 可以 | 可以 | 可以 |
protected | 可以 | 可以 | 可以 | 不能 |
默认 | 可以 | 可以 | 不能 | 不能 |
private | 可以 | 不能 | 不能 | 不能 |
个人理解:所以后续功能可扩展性方法一定不能声明为final类型。
个人理解:你只能用它,不能进一步通过继承该类修改、添加其功能。
class Student{ private int studentId; private static int count; public Student(int studentId){ this.studentId = studentId; System.out.println(++count); } public static void main(String[] args){ Student s1 = new Student(2018); Student s2 = new Student(2020); } }
class Student{ private int studentId; public setId(int studentId){ this.studentId = studentId; } public int getId(){ return this.studentId; } public static void main(String[] args){ Student s = new Student(); int id = s.setId(2018);//后续解释 } }
解释:调用setId方法时,除了传递"2018"参数外,还隐式的传递了"s"作为参数,在方法中的this关键字即表示该参数。
double d = Math.sqrt(3.0*3.0+4.0*4.0);
注意:
- 该方法在调用时,没有隐式的传递对象引用,因此在static方法中不可以使用this关键字。
- 由于static在调用时没有具体的对象,因此在static方法中不能对于非static成员(对象成员)进行访问。
static{ //语句 }
class Data{ public static final int Max = 100; } class Test{ public static void main(String[] args){ System.out.println(Data.Max); //代码编译时,会替换成:System.out.println(100); } }
补充:static final常量Data.Max会在编译时被替换成其常量值(100),在运行Test类时,Data类不需要被载入。
abstract class Person{ int age;//抽象类中也可以包含变量 abstract void Print(); } class Teacher extends Person{ String name; Teacher(String name,int age){ this.name = name; this.age = age; } @Override void Print() { System.out.println("名字是:"+name); System.out.println("年龄是:"+age); } public static void main(String[] args) { Teacher t = new Teacher("Tom",12); t.Print(); } }
Person p = new Person();
外部类名.this
class Outer{ private int time; private Inner inner; Outer(int time){ this.time = time; inner = new Inner(); inner.timeInc(); } public void Print(){ System.out.println(time); } class Inner{ public void timeInc(){ time++; } } public static void main(String[] args){ Outer outer = new Outer(100); outer.Print(); } } //output: //101
解释:在Outer构造方法中创建的Inner对象会有一个隐式的引用指向创建它的Outer对象,调用Inner对象的timeInc方法,即会对Outer的time属性进行操作。
补充:在jdk1.8之前,匿名内部类中若想访问外面的变量,则该变量必须是final。
//抽象类,作为匿名内部类的父类进行创建 abstract class Worker{ abstract public void Show(); abstract public void SetString(String s); } public class Test{ public static void main(String[] args) { String name = "Tom"; Worker w = new Worker() { String course; public void SetString(String s) { this.course = s; } public void Show() { System.out.println(course); System.out.println(name); //这里可以直接用,仅仅限于JDK1.8及之后,之前版本要用的话,得加final。 } }; w.SetString("Hello World!"); w.Show(); } }
class Test implements function1,function2,...{ //实现接口中定义的所有方法。 }
function1 f1 = new Test();
个人理解:就像《向上造型》那一篇笔记讲的原理类似,由父类来引用子类对象,但是在使用的时候会有所限制。
public interface Runner { public int Max = 100; public abstract void run(); } public interface Function extends Runner{ public void function(); } class implements Function{ //Test必须实现Runner接口和Function接口中的所有方法! }
/** * 用于一些代码的测试 * @author YiWen Wan */ abstract class Person{ abstract public void Print(); } class Teacher extends Person{ @Override public void Print() { System.out.println("这是一个老师!"); } } class Worker extends Person{ @Override public void Print() { System.out.println("这是一个工人!"); } } class Student extends Person{ @Override public void Print() { System.out.println("这是一个学生!"); } public String getName(){ return "Tom"; } } class ElementarySchoolStudent extends Student{ @Override public void Print() { System.out.println("这是一个小学生!"); } public double getScore(){ return 100; } } class MiddleSchoolStudent extends ElementarySchoolStudent{ @Override public void Print() { System.out.println("这是一个中学生!"); } public String getSubject(){ return "理科"; } } class CollegeStudent extends MiddleSchoolStudent{ @Override public void Print() { System.out.println("这是一个大学生!"); } public String getMajor(){ return "计算机科学与技术"; } } public class Test{ public static void main(String[] args) { //同一类型的引用指向不同的对象 Person p1 = new Teacher(); p1.Print(); Person p2 = new Worker(); p2.Print(); Person p3 = new Student(); p3.Print(); System.out.println("分隔线*******************"); //同一个对象造型成不同类型 CollegeStudent collegeStudent = new CollegeStudent(); System.out.println(collegeStudent.getMajor()); MiddleSchoolStudent middleSchoolStudent = collegeStudent; System.out.println(middleSchoolStudent.getSubject()); ElementarySchoolStudent elementarySchoolStudent = collegeStudent; System.out.println(elementarySchoolStudent.getScore()); Student student = collegeStudent; System.out.println(student.getName()); ; } } //output: //这是一个老师! //这是一个工人! //这是一个学生! //分隔线******************* //计算机科学与技术 //理科 //100.0 //Tom
使用规则:
个人理解:相当于中间转了一道,先是一个超类(父类)变量接收一个派生类的对象,然后又将该超类(父类)变量又强制转换回派生类。
如果在强制转换过程中出现了违背上述的两个前提,将会抛出ClassCastException异常。
/** * 用于一些代码的测试 * @author YiWen Wan */ interface Printer{ public abstract void Print(); } class Student implements Printer{ private int age; private String name; Student(int age,String name){ this.age = age; this.name = name; } @Override public void Print() { System.out.println("姓名:"+this.name+" 年龄:"+this.age+"!"); } } public class Test extends Student{ Test(int age, String name) { super(age, name); } public static void main(String[] args) { Student s = new Test(18,"Tom"); s.Print(); Test t = (Test) s; Printer printer = t; Test t1 = (Test) printer; } } //output: //姓名:Tom 年龄:18!
/** * 用于一些代码的测试 * @author YiWen Wan */ abstract class Person{ abstract public void Print(); } class Teacher extends Person{ @Override public void Print() { System.out.println(); System.out.println("这是一个老师!"); } } class HeadMater extends Teacher{ @Override public void Print() { super.Print(); System.out.println("这也是一个校长!"); } } public class Test{ public static void main(String[] args) { Person p = new Teacher(); p.Print(); System.out.println(p instanceof Person); System.out.println(p instanceof Teacher); System.out.println(p instanceof HeadMater); Person h = new HeadMater(); h.Print(); System.out.println(h instanceof Person); System.out.println(h instanceof Teacher); System.out.println(h instanceof HeadMater); } } //output: //这是一个老师! //true //true //false // //这是一个老师! //这也是一个校长! //true //true //true
/** * 用于一些代码的测试 * @author YiWen Wan */ abstract class Person{ abstract public void Print(); } class Teacher extends Person{ @Override public void Print() { System.out.println("这是一个老师!"); } } class HeadMater extends Teacher{ @Override public void Print() { super.Print(); System.out.println("这也是一个校长!"); } } public class Test{ public static void main(String[] args) { Person k = new HeadMater(); Person h = (Teacher)k;//强制类型转换之后的实验! h.Print(); System.out.println(h instanceof Person); System.out.println(h instanceof Teacher); System.out.println(h instanceof HeadMater); } } //output: //这是一个老师! //这也是一个校长! //true //true //true