构造方法是一个比较特殊的方法,通过构造方法可以完成对象的创建,以及实例变量的初始化(注意:实例变量没有赋值时系统会默认赋值,是在对象创建的时候赋值,在构造方法执行的过程中完成初始化的)
无参构造方法虽然里面什么都没写,但是这个方法体里面进行的实例变量默认值初始化。
只要没有给变量赋值,系统都会赋默认值
public class Student{ int no; String name; int age; public Student(){ System.out.println("!!!"); } public Student(int i){ no=i; } }
1.当一个类没有提供任何构造方法,系统会自动提供一个无参数的构造方法,该构造方法被称为:缺省构造器
2.当一个类中提供了构造方法,系统不会再提供无参构造方法
3.无参数构造方法,有参数构造方法都可以调用,支持方法重载,一个类中构造方法可以有多个。
方法重载特点:在同一个类中,方法名相同,参数列表不同。
构造方法通过new运算符调用
构造方法的语法结构:
[修饰符列表] 构造方法名(形式参数列表){
构造方法体
通常在构造方法体中给属性赋值,完成属性的初始化
}
注意:修饰符列表统一写public,不要写public static
构造方法名和类名必须一致
构造方法不需要指定返回值类型,也不能写void
普通方法的语法结构:
[修饰符列表] 返回值类型 方法名(形式参数列表){
方法体
}
public class Main{ public static void main(String[] args){ //调用普通方法 :类名.方法名 Main.doSome(); doSome();//在一个类里面可以省略类名 //调用构造方法 Student x=new Student(); } public static void doSome(){ System.out.println("do some!!"); } }2.封装
作用:保证内部结构的安全性,屏蔽复杂、暴露安全
1.属性私有化
2.1个属性对外提供两个set和get方法,可以在set方法中设立关卡保证数据的安全性。
对外只提供接口
注意:java开发规范中有要求,set方法和get方法要满足以下格式。
public 返回值类型 get+属性名首字母大写(无参){
return xxx;
}
public void set+属性名首字母大写(有1个参数){
xxx = 参数;
}
public class Main{ public static void main(String[] args){ } } public class Person{ //通过private关键字 private int age; //对外提供简单的调用入口,set,get方法,并且这两个方法都是实例方法 public int getAge(){ return age; } public void setAge(int nianling){ //在此位置上设置关卡 if(nianling<0||nianling>150){ System.out.println("对不起,年龄值不合法!"); return; } age=nianling; } }3.static
对象被称为实例。
实例相关的有:实例变量、实例方法。
实例变量是对象变量,实例方法是对象方法。
实例相关的都需要先new对象,通过"引用."的方法去访问。
public class Main{ public static void main(String[] args){ //带有static的方法通过“类名.”的方式访问 Main.doSome(); //在同一个类中“类名"可以省略 doSome(); //需要先new出来,创建对象,然后访问 Main mt=new Main();//Main类有一个无参构造方法 mt.doOther(); } public static void doSome(){ System.out.println("do Some"); } //这个方法没有static,这样的方法被称为:实例方法(对象方法,对象级别的方法) public void doOther(){ } }
//空指针异常 //本质原因:空引用访问“实例相关的数据” //实例变量,实例方法 public class NullPointer{ public static void main(String[] args){ User u=new User(); System.out.println(u.id);//0 u.doSome(); //引用变成null u=null; //id的访问需要对象的存在 //System.out.println(u.id);//空指针异常 //一个实例方法的调用也必须有对象的存在 //u.doSome();//空指针异常 } } class User{ int id; //实例方法(对象相关的方法,对象级别的方法,对应对象级别的行为) public void doSome(){ System.out.println("do Some"); } }
static翻译为“静态的”,所有static修饰的都是类相关的,类级别的。
所有static修饰的都是采用"类名."的方式访问
static修饰的变量:静态变量
static修饰的方法:静态方法
变量的分类:
方法体中声明的变量:局部变量
方法体外声明的变量:成员变量
成员变量分为
实例变量
静态变量
只要是方法不管是静态方法、实例方法、构造方法,它们在运行的时候都是需要压栈
堆里存实例变量,栈里存局部变量
静态变量是在类加载时初始化,存储在方法区
如果这个类型的所有对象的某个属性值都是一样的,不建议定义为实例变量,浪费内存空间,建议定义为类级别特征,定义为静态变量,在方法区中只保留一份,节省内存开销。
实例变量一定使用""引用.",静态的也可以但是不建议
class VarTest{ //以下实例的都是对象相关的,访问时采用"引用.”的方式访问,需要先new对象 //成员变量中的实例变量 int i; //实例方法 public void m1(){ } //以下静态的,都是类相关的,访问时采用“类名.”的方式访问。不需要new对象 //成员变量中的静态变量 static int k; //静态方法 public static void m2(){ } }
类=属性+方法
属性描述状态,方法描述行为动作
public class StaticTest02{ public static void main(String[] args){ Chinese c1=new Chinese("111","张三"); Chinese c2=new Chinese(); System.out.println(Chinese.country); System.out.println(c2.name); System.out.println(c1.idCard); //不会出现空指针异常 c1=null; System.out.println(c1.country); } } class Chinese{ String idCard; String name; static String country="中国"; public Chinese(){ //无参数 } public Chinese(String num,String n){ idCard=num; name=n; } }
静态方法不能访问实例变量
如果方法中直接访问了实例变量,该方法必须是实例方法
工具类方法一般都是静态的
静态代码块
静态代码块在类加载时执行且只执行一次
在main方法执行之前执行,按照自上而下顺序执行
作用:1.不常用
2.特殊的时刻,类加载,记录日志
public class StaticTest06{ static{ System.out.println("A"); } static{ System.out.println("B"); } //入口 public static void main(String[] args){ System.out.println("D"); } static{ System.out.println("C"); } }
实例代码块
实例语句块在类加载时不执行
只要是构造方法执行,在构造方法执行之前一定执行实例语句块
public class InstanceCode{ //入口 public static void main(String[] args){ System.out.println("Main begin"); new InstanceCode(); } //实例语句块 { System.out.println("实例语句块执行"); } public InstanceCode(){ System.out.println("无参数构成方法"); } public InstanceCode(String name){ System.out.println("有参数构成方法"); } }4.执行顺序
public class Main{ //静态变量在类加载时初始化,存在方法区 static int i=100; //静态代码块在类加载时执行 //只要时代码都存在方法区 static{ //可以访问i System.out.println("i="+i); } int k=111;//实例变量,在构造方法执行时内存空间才会开辟。 static{ //不能访问k System.out.println("k="+k); } //入口(main方法执行之前实际上执行了很多代码) public static void main(String[] args){ } }
1.对于一个方法来说,方法体中的代码有顺序,自上而下
2.静态代码块1和静态代码块2
3.静态代码块和静态变量
一个类体中的方法没有顺序
5.this1.关键字
2.一个对象,一个this,this是一个变量一个引用,保存当前对象的内存地址,指向自身
-
this存储在堆内存中对象内部
-
this只能使用在实例方法中,谁调用这个实例方法,this就是谁。所以this代表的是:当前对象
-
this.大部分情况下是可以省略的
增强可读性且防止因为就近原则导致的误解
参数名和实例变量重名,实例变量在该方法中使用this.方式访问
-
不能使用在静态方法中
public class ThisTest02{ int i=100; static int k=111; public static void main(String[] args){ //错误,无法从静态上下文中引用非静态变量 //System.out.println(i); System.out.println(ThisTest02.k); System.out.println(k); ThisTest02 tt=new ThisTest02(); System.out.println(tt.i); } }
public class Last{ public static void main(String[] args){ Husband h1=new Husband("111","张三","1999-10-11",null); Wife w1=new Wife("222","李四","1989-11-10",h1); h1.wife=w1; } } class Husband{ String idCard; String name; String birth; Wife wife;//引用类型 public Husband(){ } public Husband(String s1,String s2,String s3,Wife w){ idCard=s1; name=s2; birth=s3; wife=w; } } class Wife{ String idCard; String name; String birth; Husband husband; public wife(){ } public Wife(String s1,String s2,String s3,Husband h){ idCard=s1; name=s2; birth=s3; Husband=h; } }
this除了可以使用在实例方法中,还可以使用在构造方法中
新语法:通过当前的构造方法去调用另一个本类的构造方法,可以使用以下语法格式.代码复用
需要注意的是:两个构造方法在同一个类中
且其只能出现在该构造方法中第一句,且只能出现一次
this(实际参数列表)
class Date{ private int year; private int month; private int day; public Date(){ this(1970,1,1); } public Date(int year,int month,int day){ this.year=year; this.month=month; this.day=day; } public void setYear(int year){ this.year=year; } public int getYear(){ return year; } public void setMonth(int month){ this.month=month; } public int getMonth(){ return month; } public void setDay(int day){ this.day=day; } public int getDay(){ return day; } }6.继承extends
作用:代码复用,有了继承关系才有了后期的方法覆盖和多态机制。
缺点:耦合度高,父类修改,子类受到牵连
特性:①java中只支持单继承,不支持多继承
class E extends A,B{ } //错误
②子类继承父类,除构造方法不能继承之外,剩下的都 可以继承。但是私有的属性无法在子类中直接访问。
③java中的类没有显示的继承任何类,则默认继承Object类,即一个类与生俱来就有Object类中所有的特征
System.out.println()
System是一个类名,直接使用System.out,说明out是一个静态变量
System.out返回一个对象,然后采用“对象."的方式访问println()方法
当输出一个引用的时候,println方法会自动调用引用的toString()方法,因此重写其很有必要
7.方法的覆盖Override和多态方法覆盖
什么时候考虑方法覆盖Override:当子类继承父类之后,当继承过来的方法无法满足子类当前的业务需求时,子类有权对该方法重新编写,有必要进行”方法的覆盖"
什么时候考虑方法重载Overload:当一个类中如果功能相似,建议将名字定义一样
条件一:两个类必须要有继承关系
条件二:重写之后的方法和之前的方法具有:相同的返回值类型(对于返回值类型是基本数据类型时必须一样,引用数据类型变小可以,但意义不大,实际开发中没人这么写)、相同的方法名、相同的参数列表
条件三:访问权限(public>protected>private)不能更低,可以更高
条件四:重写之后的方法不能比之前的方法抛出更多的异常,可以更少
父类抛exception,子类可以抛也可也不抛也可以抛出范围更小的
注意事项:1.方法覆盖只是针对于方法与属性无关
2.私有方法无法覆盖
3.构造方法不能被继承,也不能被覆盖
4.方法覆盖只是针对于实例方法,静态方法覆盖没有意义
方法覆盖需要同多态机制联合起来才有意义
多态和对象有关系,而静态方法的执行不需要对象。
//静态方法不存在方法覆盖 public class OverrideTest05{ public static void main(String[] args){ Animal a=new Cat(); //静态方法和对象没有关系 a.doSome();//父类的方法,虽然使用"引用."来调,但是还是使用父类的方法 } } class Animal{ public static void doSome(){ System.out.println("An"); } } class Cat extends Animal{ public static void doSome(){ System.out.println("Ca"); } }
私有方法无法覆盖
方法覆盖的返回值类型
public class OverrideTest07{ public static void main(String[] args){ } } class Animal{ } class Cat extends Animals{ } class MyClass1{ public Animal getAnimal(){ return null; } } class MyClass2{ public Cat getAnimal(){ return null; } }多态
1.多态的基础语法
java中允许向上转型(子-》父)与向下转型(父-》子),要求必须有继承关系
多态指的是:父类型引用指向子类型对象。包括编译阶段和运行阶段
编译阶段:绑定父类的方法
运行阶段:动态绑定子类型对象的方法
分析程序一定要分析编译阶段的静态绑定和运行阶段的动态绑定。
只有编译通过的代码才能运行,没有编译轮不到运行。
什么时候使用向下转型:访问的方法是子类中特有的方法,此时必须使用向下转型
ClassCastException类型转换异常
运算符:instanceof
①可以在运行阶段动态判断指向引用的对象的类型
②语法:(引用 instanceof 类型)
③运算结果只能是:true/false
④假设c是一个引用,c变量保存了内存地址指向了堆中的对象
(c instanceof Cat)为true表示:c引用指向的堆内存的java对象是一个Cat
(c instanceof Cat)为false表示:c引用指向的堆内存的java对象不是一个Cat
if(a6 instanceof Cat){ Cat y=(Cat)a6; y.catchMouse(); }
2.多态在开发中的作用
软件开发原则:最基本原则:开闭原则(ocp):对扩展开放,对修改关闭
面向父类型编程
降低程序的耦合度,提高程序的扩展力
面向抽象编程
public class Homework{ public static void main(String[] args){ //创建各种乐器对象 Erhu erhu=new Erhu(); Piano piano=new Piano(); Violin violin=new Violin(); Musician m=new Musician(); m.play(erhu); m.play(piano); m.play(violin); //还可以 m.play(new Erhu()); m.play(new Piano()); m.play(new Violin()); } } //乐器父类 class Instrument{ public void makeSound(){ } } //乐手 class Musician{ puclic void play(Instrument i){ //编译阶段makeSound方法是Instrument的,运行阶段不一定是谁的 i.makeSound(); } } //子类 class Erhu extends Instrument{ public void makeSound(){ System.out.println("二胡的声音"); } } //子类 class Piano extends Instrument{ public void makeSound(){ System.out.println("钢琴的声音"); } } //子类 class Violin extends Instrument{ public void makeSound(){ System.out.println("小提琴的声音"); } }super
1.this 能出现在实例方法中和构造方法中,不能使用在静态方法中
this.
this()只能出现在构造方法中,通过当前的构方法去调用“本类"中其他的构造方法,目的是:代码复用
2.super 能出现在实例方法中和构造方法中,不能使用在静态方法中
super.
super()只能出现在构造方法中,通过当前的构造方法去调用”父类“中的构造方法,目的时:创建子类对象的时候,先初始化父类特征。
当一个构造方法第一行,既没有this()又没有super()的话,默认会又一个super();表示通过当前子类的构造方法调用父类的无参数构造方法。所以必须保证父类的无参数构造方法是存在的。
注意:this(),super()不能共存
父类的构造方法一定会执行
在java语言中无论是构造什么方法,Object类的无参构造方法(处在栈顶)一定最先执行
class A{ public A{ } public A(int i){ } } class B{ public B(){ //调用父类中有参数的构造方法 super(100); } }
在恰当的时间使用super(实际参数列表);
super代表“当前对象(this)”的父类型特征
注意:虽然在构造方法的执行过程中调用了父类的构造方法,父类的构造方法又向下继续调用其父类的构造方法,但是实际上对象只创建了一个
super用来创建当前父类型特征,super关键字代表的就是当前对象的那部分父类特征。
public class SuperTest04{ public static void main(String[] args){ Vip v=new Vip("张三"); v.shopping(); } } class Customer{ String name; public Customer(){} public Customer(String name){ super(); this.name=name; } } class Vip extends Customer{ public Vip(){} public Vip(String name){ super(name); } //super和this都不能出现在静态方法中。 public void shopping(){ //this表示当前对象 System.out.println(this.name+"正在购物!"); //super表示的是当前对象的父类型特征 System.out.println(super.name+"正在购物!"); //同一 System.out.println(name+"正在购物!"); } }
当父类和子类中有同名属性,想访问父类中的属性需要加super.
super不是引用,也不保存内存地址,也不指向任何对象
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)