成员变量和局部变量:
在 eat 与 sleep 方法中都是 String 类型的 name, 说明不同的方法,可以有同名的局部变量
当成员变量与局部变量名称相同时,局部变量更具有优先级
使用 this. 属性,代表成员变量
成员变量有默认 , 引用数据类型统统默认为 null, int -- 》 0,double --> 0.0 boolean --> false
局部变量,必须声明,赋值,再使用,否则编译报错,尚未初始化变量
成员变量的作用域为整个类 , 局部变量只是所定义的方法中或语句块中起作用
成员变量存在堆内存 , 局部变量存在栈内存
栈内存与堆内存的区别:
栈内存:
存放局部变量
先进先出,自下而上存储
方法执行完毕,自动释放空间
堆内存:
存放new出来的对象
需要垃圾回收器回收
方法区:
存放类的信息(代码),static变量,字符串常量符
构造方法和实例方法的区别:
(1)构造方法没有返回值,而实例方法必须写返回值,没有返回值,也必须写void
(2)构造方法的名称必须与类名同名,而实例方法的名称可以自己定义(要求:见名知意)
(3)构造方法的作用,用于创建对象(实例化对象,)成员方法的作用是描述对象的行为 (对象具备的功能)
(4)构造方法在创建对象时调用,每调用一次,创建一个对象,而成员方法可以被同一个对象调用N多次
(5)成员方法必须使用对象调用,构造方法使用new 调用
this关键字:
this:这个,代表当前对象,用于存储当前对象的内存地址
(1)当局部变量与成员变量名称相同时,使用this代表成员变量
(2)使用this可以调用本类中的方法 this.方法名(),this可以省略不写
(3)使用this调用本类中的属性, this.属性名, this可以省略不写
(4)调用本类中的构造方法 this() ,this(实参列表) ,要求 必须 是构造方法中第一句代码
static关键字
(1)修饰成员变量
(2)修饰成员方法
因为static的属性或方法,在类加载到内存时,一同加载到内存,而这个时候还没有创建对象呢,所以不能使用this,,当前更不能使用this.name 成员变量,也不能使用成员方法
成员方法可以使用成员变量,可以使用静态变量,也可以调用静态方法
(3)可以修饰内部类
(4)可以修饰代码块
[1]普通代码块:在方法中定义
[2]构造代码块 :在类中定义的 ,每创建一个对象,都将执行一次,而且优先于构造方法先执行
[3]静态代码块:在构造代码块前加static,就称为静态代码块
静态代码块在类加载到内存时,一同加载,而且只加载一次,无论创建多少个对象,静态代码块只执行一次
优先于构造代码块先执行
静态代码块--------------->构造代码块------------------------>构造方法
面向对象的三大特征之一, (封装,继承,多态)
封装
为什么需要封装?
因为可以使用不合法的数据进行给属性赋值
如何进行封装?
[1] 属性私有化
[2] 提供公有的取值,赋值方法 , 可以只有取值,也可以只有赋值
[3] 在赋值的方法中进行合法性验证
this:
当前对象, Person p1=new Person (); this指代就是p1 this与p1所存储的内存相同,都是内存地址
(1)调用本类的属性 this.属性名
(2)本类中的非static方法 this.方法名(实参列表);
(3)调用本类的构造方法 this(), this(实参列表); 要求必须是构造方法中第一句代码
(4)当局部变量与成员变量名称相同时,使用this代表的是成员变量
static:
(1)成员变量 -->类变量,静态变量 static String city; Person 类中的 Person.city
(2)成员方法 --> 类方法 ,静态方法 public static void show(){} Person类中 Person.show()
(3)代码块 -->静态代码块 ,用于给类的静态变量初始化数据
(4)修饰类
codeBlock:
(1)普通代码块
(2)构造代码块
(3)静态代码块
封装 :好处,提高程序的安全性
封装的优点
-
1. 良好的封装能够减少耦合。
-
2. 类内部的结构可以自由修改。
-
3. 可以对成员变量进行更精确的控制。
-
4. 隐藏信息,实现细节。
【1】属性私有化
【2】提供赋值取值方法
【3】在赋值方法中对值进行合法性验证
实际上就是隐藏细节,提供对方操作的方法 用活中处处用到了封装
package com.bjsxt.pro;
public class Teacher{ // 讲师类
//[1] 属性私有化
private String name ;
private int teachAge ;
private String sex ;
private String course ;
//[2]4 对方法,赋值的方法,取值的方法
public void setName(String name ){
this . name = name ;
}
public String getName(){
return name ;
}
public void setTeachAge( int teachAge ){
//[3] 在赋值的方法中,对值进行合法性验证
if ( teachAge <0){
this . teachAge =1;
System. out .println( " 教龄赋值有误,已设为默认值 " );
} else
this . teachAge = teachAge ;
}
public int getTeachAge(){
return teachAge ;
}
public void setSex(String sex ){
if (! " 男 " .equals( sex )&&! " 女 " .equals( sex )){
this . sex = " 男 " ;
} else {
this . sex = sex ;
}
}
public String getSex(){
return sex ;
}
public void setCourse(String course ){
this . course = course ;
}
public String getCourse(){
return course ;
}
//[3] 构造方法
public Teacher(){
}
public Teacher(String name , int teachAge ,String sex ,String course ){
this . name = name ;
this .setTeachAge( teachAge ); // 调用给教龄赋值的方法
this .setSex( sex );
this . course = course ;
}
}
测试:
package com.bjsxt.pro;
public class TestTeacher{
public static void main(String [] args){
//[1] 创建 Teacher 类的对象
Teacher t= new Teacher( " 张三十 " ,-10, " 女 " , "java" );
System.out.println(t.getName()+ "\t" +t.getTeachAge()+ "\t" +t.getSex()+ "\t" +t.getCourse());
}
}
继承
好处:提高代码的复用性
继承所使用关键字为extends
写代码: 先写父类,再写子类
父类:
package com.bjsxt.pro;
public class Person { // 父类
//[1] 私有属性
private String name ; // 姓名
private String sex ; // 性别
//[2] 公有的取值,赋值方法
public String getName() {
return name ;
}
public void setName(String name ) {
this . name = name ;
}
public String getSex() {
return sex ;
}
public void setSex(String sex ) {
this . sex = sex ;
}
//[3] 构造方法
public Person(String name , String sex ) {
this . name = name ;
this . sex = sex ;
}
public Person() {
//System.out.println("Person 类的无参构造方法 ");
}
public void speak(){
System. out .println( " 自我介绍 :" );
System. out .println( " 大家好,我叫 :" + name + " ,性别是 :" + sex );
}
}
子类一:
package com.bjsxt.pro;
public class Teacher extends Person { //Teacher 继承自 Person
// 私有属性
private int teachAge ;
private String course ;
// 公有的取值,赋值方法
public int getTeachAge() {
return teachAge ;
}
public void setTeachAge( int teachAge ) {
this . teachAge = teachAge ;
}
public String getCourse() {
return course ;
}
public void setCourse(String course ) {
this . course = course ;
}
// 构造方法
public Teacher(String name , String sex , int teachAge , String course ) {
super ( name , sex ); // 调用父类的构造方法
this . teachAge = teachAge ;
this . course = course ;
}
public Teacher() {
//super(); // 调用父类的无参构造方法, super() 可以省略不写,即使用省略默认调用父类无参构造
//System.out.println("Teacher 类中的无参构造方法 ");
}
}
子类二:
package com.bjsxt.pro;
public class Student extends Person {
// 私有属性
private String stuNo ;
private int age ;
public String getStuNo() {
return stuNo ;
}
public void setStuNo(String stuNo ) {
this . stuNo = stuNo ;
}
public int getAge() {
return age ;
}
public void setAge( int age ) {
this . age = age ;
}
// 构造方法
public Student(String name , String sex , String stuNo , int age ) {
super ( name , sex );
this . stuNo = stuNo ;
this . age = age ;
}
public Student() {
super ();
}
}
测试:
package com.bjsxt.pro;
public class Test {
public static void main(String[] args ) {
Teacher t = new Teacher( "mary" , " 女 " ,10, "java" );
t .speak(); // 这个方法是 Person 类中的方法
Student stu = new Student( "jack" , " 男 " , "sxt1001" , 20);
stu .speak();
}
}
继承的特性:
【1】单根性 : 一个子类只能直接继承一个父类
【2】传递性 :
public class A {
public int money =100000000;
}
public class B extends A {
}
public class D extends B {
public void show(){
System. out .println( super . money );
}
}
public class TestD {
public static void main(String[] args ) {
D d = new D();
d .show();
}
}
一个类如果没有显示写extends,那么默认继承Object类 ,Object是所有的类的直接或间接父类
public class Person {
}
相当于
public class Person extends Object{
}
继承
:先写父类,再写子类, 子类使用extends继承父类
(1)继承非private的属性
(2)继承非private的方法
(3)构造方法,子类可以调用,但不能继承
当父类提供的方法不能满足子类的需求,子类需要重写这个方法
重写:
[1]在子类
[2]方法的名称必须与父类的方法名称相同
[3]方法的参数必须与父类中定义的方法的参数个数,顺序,类型完全相同
[4]子类重写方法的返回值类型与父类中的方法的返回类型相同,或者是父类方法返回值的子类
package com.bjsxt.pro;
public class Father {
public Father show(){
//Father f=new Father();
//return f;
return new Father();
}
}
子类重写之后,与父类方法的返回值类型相同
package com.bjsxt.pro;
public class Son extends Father {
@Override
public Father show() {
// TODO Auto-generated method stub
return super .show();
}
}
或者,子类重写之后,是父类方法返回值类型的子类
package com.bjsxt.pro;
public class Son extends Father {
@Override
public Son show() {
// TODO Auto-generated method stub
return new Son();
}
}
[5]访问权限大于等于父类方法的访问权限
如果父类方法的访问权限为protected,那么子类重写时,可以为protected或public
类的成员 (属性和方法)
private: 只能本类中访问
default: 只能本包中访问
protected:只能子类访问
public:公共的,访问权限最大的
子类不能重写父类的哪些方法?
(1)子类不能重写父类的private方法
(2)子类不能重写父类的构造方法
(3)子类不能重写父类的static方法
一个类如果没有使extends继承任何类,默认继承Object,Object类是所有的类的直接或间接父类
super关键字
this:代表当前对象 ,可以调用本类的属性,本类的方法,本类的构造方法(要求必须是第一句代码)
super:指向直接父类,只是一个关键字而已,这个关键字只能出现在子类中
(1)调用父类的非private属性
(2)调用父类的非 private方法
(3)调用父类的构造方法 super() ,super(实参列表)
只要创建子类对象就会调用父类的构造方法,如果没有指定,默认调无参
父类:
package com.bjsxt.super1;
public class Person {
private String name = " 张三 " ;
int age ;
public String getName() {
return name ;
}
public void setName(String name ) {
this . name = name ;
}
public Person(String name , int age ) {
super (); // 调用的是 Object 类的无参构造方法
this . name = name ;
this . age = age ;
}
public Person() {
super ();
System. out .println( "Person" );
}
}
子类:
package com.bjsxt.super1;
public class Employee extends Person { // 工人
private String deptment = "java 学院 " ; // 部门
public String getDeptment() {
return deptment ;
}
public void setDeptment(String deptment ) {
this . deptment = deptment ;
}
public void show(){
System. out .println( super.getName() + "\t" + super .age );
}
public Employee(String name , int age , String deptment ) {
super(name, age); // 调用父类的带参构造方法
// 默认调用无参
this . deptment = deptment ;
}
public Employee() {
super(); // 可以省略不写
}
}
测试:
package com.bjsxt.super1;
public class Test {
public static void main(String[] args ) {
Employee e = new Employee( " 李四 " , 20, " 财务部 " );
System. out .println( e );
}
}
封装与继承的区别:
封装是提高代码的安全性(属性私有化,提供共有的取值赋值方法,在赋值方法中对值进行合法性验证)
继承提高代码的复用性(子类继承父类,重写父类中的非private属性,非private方法,调用构造方法)
面向对象的三大特征
(1)封装 :提高程序的安全性
(2)继承 :提高代码的复用性
extends , --》Object (toString(),equals(Object obj))
父类 :属性(每个子类都会具有的属性)
成员方法(每个子类都具有的行为)
构造方法 (可以提供给子类调用)
子类:属性(子类特有的属性)
成员方法(每个子类特有的行为)
构造方法
方法重写: 如果父类提供方法,不能满足子类的需求,子类就可以重写父类中的方法
(1)方法的名称,参数的类型,个数,顺序必须与父类中的方法完全相同
(2)返回值可以与父类的返回值相同,也可以是父类方法返回值的子类
(3)子类在重写时,访问权限与父类相同,或者访问权限比父类
访问权限修饰符:
(1)修饰类时:两种
default(package), public
(2)修饰成员时:4种
private :本类
default:本包
protected:子类
public:都可以访问
super关键字:
它只能出现在子类中,用于访问父类的成员 (非private的成员)
调用父类的构造方法 super() super(实参列表)
多态
多态有前提条件是继承,没有继承无从谈多态
使用多态的步骤:
(1)编写父类
(2)编写子类,子类重写父类中的方法
(3)使用父类指向子类对象
多态有两种表现形式
(1)父类作方法的形式参数
Object类中的equals( Object obj )
(2)父类作方法的返回值
类型转换
(1)向上类型转换/自动类型转换 :子转父 --》只能调用父类中的方法(继承的方法或者重写的方法)
(2)向下类型转换/强制类型转换 :父转子 --》 可以调用父类中的方法及子类中特有的方法
向下转换容易产生异常 ClassCastException类型转换异常, 要求向下转换必须转换成真实的子类对象
Car tc = new TaxiCar( " 北京现代 " , " 京 B23234" , " 景顺 " );
Car mc = new MyCar( " 奥迪 A8" , " 京 P88434" , " 武大郎 " );
c.start();
c.stop();
System. out .println( "\n---------------------------------\n" );
mc.start();
mc.stop();
public class TestEquals {
public static void main(String[] args ) {
// 父类 new 子类对象 -- 》进行了向上类型转换,转成了 Object 类型
Object c = new Car (); //
//c 只能调用 Object 类中的方法
//c.start(); 9 行与 10 行报错,因为这两个方法是子类 Car 特有的方法
//c.stop(); 如果想调用这两个方法,必须向下类型转换
MyCar my= (MyCar)c; //ClassCastException 类型转换异常,向下转型时,必须转换成真实的子类对象
my .start();
my .stop();
//System.out.println(" 男 ".equals(c));
}
}
在向下转型时,通常需要进行真实子类类型的判断, instanceof 进行判断判断,返回值为true或false
小结:
(1)多态的操作步骤: 父类,子类,子类重写方法, 父类创建子类对象
(2)父类作方法的返回值,父类作方法的形式参数
(3)类型转换
final关键字
(1) 修饰变量 (成员变量,局部变量)
public static final double PI =3.1415926; // 静态常量
final修饰局部变量时,不允许使用 public static
(2) 方法 不能被子类重写,但是子类可以调用
不能从Object类中重写这个final方法
(3) 类 (太监类) :不能有子类的
TestFinal类不能是终级类Math类的子类,因为API 中Math类的定义为final
public final class Math
final可以与static一起使用
final不能与abstract一起使用
abstract抽象
(1)修饰类 :抽象类
public abstract class Father {
}
抽象类可不可以有构造方法? 可以
抽象类中的构造方法的作用? 提供给子类调用
父类:
public abstract class Father {
private String name ;
public Father(){
}
public Father(String name ){
this . name = name ;
}
}
子类:
public class Son extends Father {
public Son() {
super();
// TODO Auto-generated constructor stub
}
public Son(String name ) {
super(name);
}
}
abstract类中可以有如下方法 (final修饰的方法,成员方法,static方法 ,构造方法)
public abstract class Father {
public final void show(){
}
// 成员方法
public void fun(){
}
//static 方法
public static void method(){
}
}
(2)修饰方法: 抽象方法 :含 有抽象方法的类必须是抽象类
public abstract class Animal {
public abstract void shout();
}
如果子类不实现父类的抽象方法,那么子类也必须是抽象类
public abstract class Cat extends Animal {
}
重写与实现在的关系:
子类可以重写父类中的方法,也可以不重写 (绿色实心三角)
子类必须实现父类中的抽象方法,如果不实现,必须也是抽象类 (白色三角)
interface接口
如果一个类中所有的方法都是抽象方法,那么可以把这个类定义为interface
接口的初步了解
public interface A {
public abstract void show();
public abstract String fun();
public abstract int [] method();
public abstract Car [] perList();
}
可以改写为
public interface A {
void show();
String fun();
int [] method();
Car [] perList();
}
接口中所有的方法均为公共的抽象方法,所以可以将public abstract省略不写
接口中不允许定义构造方法
接口中只能有公共的静态常量 public static final
public static final String name = " 张三 " ;
那么public static final可以省略不写
public interface A {
String name = " 张三 " ;
}
接口中的方法均为public abstract方法,这些方法需要类去实现,所以接口与类的关系为实现关系,使用关键字
implements
public class AImple implements A {
@Override
public void show() {
// TODO Auto-generated method stub
}
}
如果一个类即存在继承关系又存在实现关系 要求extends在前,implements后
一个类只能继承一个父类但可以实现N多接口
智能手机 is a 手机 has a 拍照的功能, has a 上网的功能, has a 播放视频的功能
防盗门 is a 门 has a 锁的功能
防盗 门 is a 锁 --》 不成立
一个类只能直接继承一个父类,但可以实现N多接口
接口的特征:
【1】多继承
public interface InterA {
public void show();
}
public interface InterB {
public void fun();
}
public interface InterC extends InterA, InterB {
}
【2】传递性
多态的操作步骤:
【1】编写父类 / 接口
【2】编写子类,重写父类中的方法 / 实现接口中的方法
【3】父类new子类对象 (父类引用指向子类对象) / 接品new 实现类
在API中java.util.Comparator接口,用于比较两个对象的大小,实现排序用
接口的应用
package com.bjsxt.inter3;
import java.util.Comparator;
public class ComLength implements Comparator { //Comparator 接口具备了比较大小的能力
@Override
public int compare(Object o1 , Object o2 ) { // 父类 Object 作方法的形式参数
// 向下类型转换
String str1 =(String) o1 ;
String str2 =(String) o2 ;
/*if(str1.length()>str2.length()){
return 1;
}else if(str1.length()<str2.length()){
return -1;
}
return 0;*/
return str1 .length()- str2 .length();
}
}
测试:
package com.bjsxt.inter3;
import java.util.Arrays;
import java.util.Comparator;
public class Test {
public static void main(String[] args ) {
String [] str ={ "grape" , "banana" , "apple" , "pink" };
Arrays. sort ( str );
System. out .println(Arrays. toString ( str ));
/** 不希望按字母升序排,我想接照单词的字每长度排序 */
//(1) 自己写比较规则
//(2) 定义一个类实现 Comparator 的接口
//(3) 实现接口中的方法 , 在方法写比较规则
//(4) 使用接口 new 实现类
Comparator com=new ComLength ();
//(5) 调用排序的 sort 方法
Arrays. sort (str, com);
System. out .println(Arrays. toString ( str ));
}
}