1.this(当前对象的/或/构造器正在初始化的对象)
1.他在方法内部使用,即这个方法所属对象的引用
2.它在构造器内部使用,表示"该构造器正在初始化的对象"
3.this表示"当前对象的",可以调用类的属性、方法和构造器
? ?3.1? 在类的方法中,我们可以使用“this.属性”或“this.方法”的方式,调用当前对象属性或方法,但? ? ? ? ? ? 是通常情况下,我们都选择省略"this."。特殊情况下,如果方法的形参和类的属性同名时,? ? ? ? ? ? 我们必须显式的使用“this.变量”的方式,表明此变量是属性,而非形参。
public void setRadius(double radius) {
this.radius = radius;
}
public girl{
public int compare(Girl girl) {
return this.age - girl.age;//this:当前对象的 girl:形参girl
}
? ?3.2? 在类的构造器中,我们可以使用“this.属性”或“this.方法”的方式,调用当前正在创建的对象属性或方法,但是通常情况下,我们都选择省略"this."。特殊情况下,如果方法的形参和类的属性同名时,?我们必须显式的使用“this.变量”的方式,表明此变量是属性,而非形参。
public Circle(double radius) {
this.radius = radius;
}
? ?3.3? this调用构造器
? ? ? ? ? A.? 我们在类的构造器中,可以显式的使用“this(形参列表)”方式,调用本类中指定的其他? ? ? ? ? ? ? ? ?构造器
? ? ? ? ? B.? 构造器中不能通过"this(形参列表)"方式调用自己
? ? ? ? ? C.? 如果一个类中有n个构造器,则最多有 n -1 构造器中使用了"this(形参列表)"
? ? ? ? ? D.? 规定:"this(形参列表)"必须声明在当前构造器的首行
? ? ? ? ? E.? 构造器内部,最多只能声明一个"this(形参列表)",用来调用其他的构造器
public Person(){//空参构造器
this.eat();
}
public Person(String name){
this();//调用上面的空参构造器
this.name = name;
}
public Person(String name){
this();//调用上面的空参构造器
this.age = age;
}
public Person(String name,int age){
this(age);//调用上面的带参构造器
this.name = name;
}
4.什么时候使用this关键字呢?
? ?当在方法内需要用到调用该方法的对象时,就用this
? ?具体的:我们可以用this来区分局部变量和属性。
this.name = name;//对象.属性,所以第一个是属性
2.super(父类的)
2.1? super调用属性和方法
2.1.1? 我们可以在子类的方法或构造器中,通过使用"super.属性"或"super.方法"的方式,显示的调用父类中声明的属性或方法,但是,通常情况下,我们习惯省略"super."
2.1.2? 特殊情况,当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须是显式的使用"super.属性"的方式,表明调用的是父类中声明的属性。
public class Person{
int id = 1001;//身份证
}
public class Student extends Person{
int id = 1002;//学生证
public void Show(){
System.out.println("id = " + id);//1001
System.out.println("id = " + super.id);//1002调用父类属性id
}
}
2.1.3? 特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须是显式的使用"super.方法"的方式,表明调用的是父类中被重写的方法。
public class Person{
public void eat(){
System.out.println("人:吃饭");
}
public void walk(){
System.out.println("人:走路");
}
}
public class Student extends Person{
@Override
public void eat(){
System.out.println("学生:多吃有营养的食物");
}
}
public class SuperTest{
public static void main(String[] args){
Student s = new Student();
s.eat();//学生:多吃有营养的食物
super.eat();//人:吃饭
this.walk();//子类没有重写父类的方法,先在子类中找,没找到,再去父类找
super.walk();//直接去父类找
}
}
2.2? super调用构造器
2.2.1? 我们可以在子列的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
2.2.2? "super(形参列表)"的使用,必须声明在子类构造器的首行!
2.2.3? 我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二选一,不能同时出现
public class Person{
public Person(String name,int age){
this.name = name;
this.age = age;
}
}
public class Student extends Person{
public Student(String name,int age){
super(name);
this.age = age;
}
public Student(String name,int age,String major){
super(name,age);
//this(name,age);//只能二选一
this.major = major;
}
}
2.2.4? 在构造器的首行,没有显式的声明"this(形参列表)"或"super(形参列表)",则默认调用的是父类中空参的构造器
public class Person{
public Person(){
System.out.println("我无处不在!");//证明调用了空参构造器
}
public Person(String name,int age){
this.name = name;
this.age = age;
}
}
public class Student extends Person{
public Student(String major){
//super();//即使不写,默认调用此空参构造器
this.major = major;
}
}
public class SuperTest{
public static void main(String[] args){
Student s = new Student();
//执行会输出:我无处不在!
}
}
2.2.5? 在类的多个构造器中,至少有一个类的构造器中使用了"super(形参列表)",调用父类中的构造器
3.static(静态的)
1. static可以用来修饰:属性、方法、代码块、内部类
2. 使用static修饰属性:静态变量(或类变量)
? ?2.1? 属性:按是否使用static修饰,又分为:静态属性 vs 非静态属性(实例变量)
? ? ? ? ? 实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性,当修改其中一个对象中的非静态属性时,不会导致其他对象中同样的属性值的修改。
? ? ? ? ? 静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量,当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的。
2.2 static修饰属性的其他说明:
? ?2.2.1 静态变量随着类的加载而加载,可以通过"类.静态变量"的方式进行调用
类名.方法()
public class InvokeMethod{
public static void main(String[] args){
InvokeMethod.t2();
}
public static void t2(){
}
}
? ?2.2.2 静态变量的加载要早于对象的创建
? ?2.2.3 由于类只会加载一次,则静态变量在内存中也只会存在一份,存在方法区的静态域中。
// static声明的属性被所有对象所共享
private static int init = 1001;// 目前,内存当中只有唯一的一份init,
private int init_ = 1002;//每个对象都有一份init_;
? ?2.2.4? ? ? ? ? ? ? ? ? ? ? ? ? ? ?类变量? ? ? ? ? ? ? ? 实例变量
? ? ? ? ? ? ? ? ? ? ? ? 类? ? ? ? ? ? yes? ? ? ? ? ? ? ? ? ? ? ? no
? ? ? ? ? ? ? ? ? ? ? ? 对象? ? ? ? yes? ? ? ? ? ? ? ? ? ? ? ? yes
3.使用static修饰方法:静态方法(不允许被重写!)
? ? ? ? A.随着类的加载而加载,可以通过"类.静态方法"的方式进行调用
? ? ? ? B.? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 静态方法? ? ? ? ? ? ? ? 非静态方法
? ? ? ? ? ? ? ? ? ? ? ? 类? ? ? ? ? ? ? ? ? ? ? ? yes? ? ? ? ? ? ? ? ? ? ? ? ? no
? ? ? ? ? ? ? ? ? ? ? ? 对象? ? ? ? ? ? ? ? ? ? ?yes? ? ? ? ? ? ? ? ? ? ? ? ?yes
? ? ? ? C.静态方法中,只能调用静态的方法或属性
? ? ? ? ? ? 非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性
class Circle {
private static int total;// 记录创建圆的个数
public static int getTotal() {// 属性是static,则操作属性的方法也是static;
return total;
}
}
? ? ? ? 静态属性举例:System.out;Math.PI;
4.static注意点:
? ?4.1 在静态的方法内,不能使用this关键字、super关键字
? ?4.2 关于静态属性和静态方法的使用,大家都从生命周期的角度去理解。
5.开发中,如何确定一个属性是否要声明为static的?
? ?>?属性是可以被多个对象所共享的,不会随着对象的不同而不同的
? ?>?类中的常量也常常声明为static
? ?开发中,如何确定一个方法是否要声明为static的?
? ?>?操作静态属性的方法,通常设置为static的
? ?> 工具类中的方法,习惯上声明为static的,比如:Math、Arrays、Collections
6.static代码块
用途:形成静态代码块以优化程序性能(由于它只会在类的加载时执行一次)
class Person{
private Date birthDate;
public Person(Date brithDate){
this.birthDate = birthDate;
}
boolean isBornBoomer(){
Date startDate = Date.valueOf("1946-1-1");
Date endDate = Date.valueOf("1964-12-31");
return brithDate.compareTo(startDate) >= 0 && brithDate.compareTo(endDate) < 0;
}
}
isBornBoomer是用来这个人是否是1946-1964年出生的,而每次isBornBoomer被调用的时候,都会生成startDate和brithDate两个对象,造成了空间浪费?,改成这样会更好:
class Person{
private Date birthDate;
private static Date startDate,endDate;
static{
Date startDate = Date.valueOf("1946-1-1");
Date endDate = Date.valueOf("1964-12-31");
}
public Person(Date brithDate){
this.birthDate = birthDate;
}
boolean isBornBoomer(){
return brithDate.compareTo(startDate) >= 0 && brithDate.compareTo(endDate) < 0;
}
}
7. static能作用于局部变量吗?
在Java中切记:static是不允许用来修饰局部变量。不为什么,这是Java语法的规定。
public void test(){
static int a = 1;//会报异常
}
理由: (看到别人的好介绍)
A.局部变量最好不要设成静态变量,局部变量是有生命周期的,用完后JAVA很快就回收资源了;如果设成静态变量,那JAVA咋莫回收被其占用的内存
B.在方法里面定义的变量是局部变量,就是说他有一定的作用范围和生命周期,就只能在方法里面使用而不能将其扩展到别的地方,这个变量在方法结束后就会被回收器回收,就不再存在了 ,而你要强制将其加上static就是要把它的作用范围扩展到整个类,这就与你开始定义这个变量时违背了,这是语法上的错误
C.static变量是给类用的。这样类初始化的时候,就会给static进行初始化;如果你在方法里面定义一个static,这时候编译器就不知道你这个变量咋莫初始化了,这个是和java的设计相关的。java全是面向对象设计的,单独一个方法不能持有一块空间。
D.一个类中,一个static变量只会有一个内存空间,虽然有多个类实例,但这些类实例中的这个static变量会共享同一个内存空间,所以声明为static的变量实质上就是全局变量。所以static不能修饰局部变量。此外,局部变量是存放在栈中的,程序运行完立即释放,他只能在定义它的方法内部使用,所以不用static修饰符。
8.关于static修饰内部类在(JAVA类即成员那片博客里介绍了)
4.final(最终的)
? ? ?1.final 可以用来修饰的结构:类、方法、变量 2.final 用来修饰一个类:此类不能被其它类所继承。 ?比如:String类、System类、StringBuffer类(这些类的功能很全,基本不用再扩充) 3.final 用来修饰方法:表明此方法不可以被重写 ?比如:Object类中getClass(); ?4.final 用来修饰变量:此时的“变量”就称为是一个常量;常量建议大写,每个单词之间采用下划线连接 ?4.1 final修饰属性:可以考虑赋值的位置有:显示初始化、代码块中初始化、构造器中初始化
注意:final修饰的实例变量,系统不负责赋默认值,要求程序员必须手动赋值;这个手动赋值,在变量后面可以,在代码块、构造器中也可以;但是final修饰的变量,系统不负责默认初始化赋值,方法中也不可以(因为在JVM加载过程中,构造器是加载的最后一道关卡,构造器调完对象就出生了若此时还未赋值,那就没意义了,方法加载的太晚)
class finalTest{
final int WIDTH = 0;//显式初始化
final int LEFT;
final int RIGHT;
{
LEFT = 1;//代码块中初始化
}
public finalTest(){
RIGHT = 2;//构造器中初始化
}
public finalTest(int n){
RIGHT = n;//如果多个构造器构成重载,则每个构造器必须被赋值
}
}
?4.2 final修饰局部变量: ?尤其是使用final修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参,一旦赋值以后,就只能在方法体内使用此实参,但不能进行重新赋值。
class finalTest{
public void show(){
final int NUM = 10;//常量
//NUM += 20;//错误,常量不能被操作
}
public void show(final int num){
//num = 20;//错误,final修饰的形参只能被调用,不能被重新赋值
}
}
?static final用来修饰属性:全局变量(接口中用的多)
public static final double PI = 3.1415926;
5.abstract(抽象的)
abstract可以用来修饰的结构:类、方法?
1.abstract修饰类:抽象类
? ?1.1 此类不能被实例化
? ?1.2 抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全过程)
? ?1.3 开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作
2.abstract修饰方法:抽象方法
? ??2.1 抽象方法只有方法的声明,没有方法体
public abstract void eat();//抽象方法
? ? 2.2 包含抽象方法的类,一定是一个抽象类,反之,抽象类中可以没有抽象方法的
? ? 2.3 若子类重写了父类中的所有的抽象方法后,此子类方可实例化
? ? ? ? ? 若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修? ? ? ? ? ? 饰
abstract使用上的注意点:
1.abstract不能用来修饰:属性、构造器等结构
2.abstract不能用来修饰私有方法(声明为private的方法不能被重写)、静态方法(不能被重写)、final的方法(不能被重写)、final的类
6.interface(接口)和implements
接口的使用(用于实现功能!!!!!!!!) ?1.接口使用interface来定义 ??2.Java中,接口和类是并列的两个结构 ?3.如何定义接口:定义接口中的成员 ?? ?3.1 JDK7及以前,只能定义全局常量和抽象方法(不能定义变量) ? ? ? ? ? >全局常量:public static final的,但是书写时,可以省略不写 ?? ? ? ? ?>抽象方法:public abstract的 ?? ?3.2JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法? ? ??
// 静态方法
public static void method1() {
System.out.println("CompareA:北京");
}
// 默认方法
public default void method2() {
System.out.println("CompareA:上海");
}
?4.接口中不能定义构造器!意味着接口不可以实例化。 ?5.Java开发中,接口通过让类去实现(implements)的方式来使用。 ? ? 如果实现类覆盖率接口中的所有抽象方法,则此实现类就可以实例化。 ? ? 如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类;即接口的实现类必须? ? ? 实现接口的全部方法 ?6.Java类可以实现多个接口--->弥补了Java单继承性的局限性 ? ? 格式:class AA extends BB implements CC,DD,EE ?7.接口与接口之间可以继承(通过extends),而且可以多继承 ?8.接口的具体使用,体现多态性(这里详细介绍了关于创建接口匿名实现类的对象)
public class USBTest {
public static void main(String[] args) {
Computer com = new Computer();
//1.创建了接口的非匿名实现类的非匿名对象
Flash flash = new Flash();//接口USB不能造对象,只能造实现类的对象,多态性的体现
com.transferData(flash);
//2.创建了接口的非匿名实现类的匿名对象
com.transferData(new Printer());
//3.创建了接口的匿名实现类的非匿名对象
USB phone = new USB() {
@Override
public void start() {
System.out.println("手机开始工作");
}
@Override
public void stop() {
System.out.println("手机结束工作");
}
};
com.transferData(phone);
//4.创建了接口的匿名实现类的匿名对象
com.transferData(new USB() {
@Override
public void start() {
System.out.println("mp3开始工作");
}
@Override
public void stop() {
System.out.println("mp3结束工作");
}
});
}
}
interface USB{
//常量:定义了长、宽、最大最小的传输速度等
void start();
void stop();
}
class Computer{
public void transferData(USB usb) {
usb.start();//执行结果:U盘开启工作
System.out.println("具体传输数据的细节");
usb.stop();//执行结果:U盘结束工作
}
}
class Flash implements USB{
@Override
public void start() {
System.out.println("U盘开启工作");
}
@Override
public void stop() {
System.out.println("U盘结束工作");
}
}
class Printer implements USB{
@Override
public void start() {
System.out.println("打印机开启工作");
}
@Override
public void stop() {
System.out.println("打印机结束工作");
}
}
?9.接口,实际上可以看作是一种规范 ?接口的使用 ?1.接口使用上也满足多态性 ?2.接口,实际上就是定义了一种规范 ?3.开发中,体会面向接口编程!
java8关于接口的5个新规范
public class SubClassTest {
public static void main(String[] args) {
SubClass s = new SubClass();
// 知识点1:接口中定义的静态方法,只能通过接口来调用。
CompareA.method1();
// 知识点2:通过实现类的对象,可以调用接口中的默认方法。
// 如果实现类重写了接口中的默认方法,调用时,仍然用的是重写以后的方法
s.method2();
// 知识点3:如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的方法。
// 那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法。-->类优先原则
// 知识点4:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法。
// 那么在实现类没有重写此方法的情况下,报错:---->接口冲突。
// 那就需要我们必须在实现类中重写此方法
// 5在下面
s.method3();
}
}
public interface CompareA {
// 静态方法
public static void method1() {
System.out.println("CompareA:北京");
}
// 默认方法
public default void method2() {
System.out.println("CompareA:上海");
}
default void method3() {
System.out.println("CompareA :上海");
}
}
public interface CompareB {
default void method3() {
System.out.println("CompareB:上海");
}
}
class SubClass extends SuperClass implements CompareA, CompareB {
@Override
public void method2() {
System.out.println("SubClass:上海");
}
@Override
public void method3() {
System.out.println("SubClass:深圳");
}
// 知识点5:如何在子类(或实现类)的方法中调用父类,接口中被重写的方法
public void myMethod() {
method3();// 调用自己定义的重写的方法
super.method3();// 调用的是父类中声明的
// 调用接口中的默认方法
CompareA.super.method3();
CompareB.super.method3();
}
}
7.instanceof(也可实现接口)
|