java基础学习——>面向对象的三大特征:继承,封装,多态

面向对象的三大特征:继承,封装,多态
封装:变量定义private ; set/get方法; 构造方法
封装的实现:

  • private的变量

  • 提供set/get方法

练习:输出矩形的周长和面积

public class Rectangle {
	private int chang;
	private int kuan;
	public int getChang() {
		return chang;
	}
	public void setChang(int chang) {
		if(chang>=0) {
		this.chang = chang;
		}
		else {
			System.out.println("长度错误");
			return;
		}
	}
	public int getKuan() {
		return kuan;
	}
	public void setKuan(int kuan) {
		if(kuan>=0) {
			this.kuan = kuan;
			}
			else {
				System.out.println("宽度错误");
				return;
			}	
	}
	public int getMian() {
		return chang*kuan;
	}
	public int getZhou() {
		return (chang+kuan)*2;
	}
}

测试类

public class TestRectangle {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Rectangle r=new Rectangle();
		r.setChang(2);
		r.setKuan(3);
		System.out.println("面积"+r.getMian());
		System.out.println("周长"+r.getZhou());
	}
}

继承:
特点:

  • 什么继承:由已有类产生新类,这种机制叫继承

  • 父类子类:已有类->父类 新类->子类

  • 继承性:子类可以继承父类的所有成员(构造方法不能继承),有些方法不可以使用的

  • Object是顶级类,是所有类的父类

  • 满足一种关系: is a

  • extends 关键字

  • Java 单继承, 每个子类只有一个直接父类。例如下面代码将会引起编译错误。

class SubClass extends Basel , Base2 , Base3{ . .. } 

super
super:表示父类对象
super.成员
super(参数):必须是子类构造方法的第一条有效语句

访问修饰符 (visibility)
private 变量,方法 本类

default 类,变量,方法 同一个包

protected 变量,方法 同一个包,不同包(继承关系)

public 类,变量,方法 任何地方
方法重写
继承关系:
父类和子类 方法名相同,参数列表相同
方法的返回类型如果是基本数据类型同(如果是继承关系,引用数据类型,子类的类型要<=父类的)

public class A{
	
}
public class B extends A{
	
}
public class c{
	public A f() {
		return null;
	}
	
}public class D extends C{
	public B f() {
		return null;
	}
	
}

子类方法的访问修饰符>=父类
异常:子类方法的异常(非运行时异常)<=父类
子类和父类的方法可以重载

为什么重写?扩展父类方法的功能 Person和Student.java

私有方法不能被重写

继承关系中构造方法的调用规则
1)子类创建对象时,不管创建对象时是否传参,都总是默认调用父类无参的构造方法
2)如果父类没有无参的构造方法,那么子类使用使用super()调用指定的构造方法

代码1)

public class A {
	int x;
	int y;
	public A() {
		System.out.println("A1");
	}
	public A(int x,int y){
		System.out.println("A");
	 }
	 
	
}
class B extends A{
	public B(int x,int y){
		System.out.println("B");
	 }
}	

B b=new B(1,2);
//B b1=new B(); error

结果为:

A1
B

代码2)

public class A {
	int x;
	int y;
	public A(int x,int y){
		System.out.println("A");
	 }
	 
	
}
class B extends A{
	public B(int x,int y){
	      //必须加上这句 super(x,y);
		super(x,y);
		System.out.println("B");
	 } 
}	

B b=new B(1,2);

结果为:

A
B

在2)时,即使父类有了无参构造,结果依然是 A B,因为有super(x,y)

构造方法练习

class MyClass{
   public int value;
}
public class TestMyClass{
    public static void main(String args[]){
      MyClass mc1 = new MyClass();
      MyClass mc2 = new MyClass(10);   //error
      System.out.println(mc1.value);
      System.out.println(mc2.value);
   }
}

构造方法的调用

class Super{
    public Super(){
      System.out.println("Super()");
    }                                         
    public Super(String str){                 
       System.out.println("Super(String)");   
    }
}
class Sub extends Super{
     public Sub(){
        System.out.println("Sub()");
     }
     public Sub(int i){
         this();
         System.out.println("Sub(int)");
     }
     public Sub(String str){
         //如果没有super(str);这句,就默认掉父类无参构造,结果就为Super() Sub(String)
         //有了这句,就调用父类有参构造
         super(str);
         System.out.println("Sub(String)");
     }
}
public class TestSuperSub{
     public static void main(String args[]){
         Sub s1 = new Sub();    //Super() Sub()
         Sub s2 = new Sub(10);        //Super() Sub()  Sub(int)
         Sub s3 = new Sub("hello");       //Super(String) Sub(String)
     }
}

多态:
定义:一种类型的变量可以指向不同的对象
父类声明=子类创建

Animal a1=new Dog();
Animal a2=new Bird();

编译时多态:方法的重载
class A{
void f(){
…(“f”);
}
void f(int x){
…(“f”+x);
}
}

A a1=new A();
A a2=new A();

a1.f();
a2.f(1);

运行时多态:方法的重写
在Animal类中定义eat ,Dog和Bird类重写了此方法
Animal a1=new Dog();
Animal a2=new Bird();

a1.eat();
a2.eat();

在编译时,看变量的声明类型
运行时,如果子类重写了父类的方法,动态绑定到子类上,运行子类的方法
对于变量,永远是谁声明就找谁


多态练习:

class Super{
    public void method(){
        System.out.println("method() in Super");
    }
    public void method(int i){
        System.out.println("method(int) in Super");
    }
}
class Sub extends Super{
     public void method(){
         System.out.println("method() in Sub");
     }
     public void method(String str){
         System.out.println("method(String) in Sub");
     }
}
public class TestSuperSub{
     public static void main(String args[]){
         Super s = new Sub();
         s.method(10);
         s.method();
         s.method("hello");//编译错误
     }
}

练习动物:

public class Animal {
	  public void eat() {
		System.out.println("吃");
	}
}
public class Bird extends Animal{
	public void eat() {
		System.out.println("吃虫子");
	}
	public void b() {
		 System.out.println("bird");
	 }
}
public class Dog extends Animal{
	 public void eat() {
		System.out.println("吃肉骨头");
	}
	 public void d() {
		 System.out.println("dog");
	 }
}
public class AnimalTest {
	public static void main(String[] args) {
	Animal a=new Dog();
	Animal b=new Bird();
	Feeder f=new Feeder();
	f.feed(a);
	f.feed(b);
	f.test(a);  //dog
	f.test(b);  //bird
	f.test2();  //java.lang.ClassCastException

	}
	
}

多态的应用

方法的参数定义为父类类型或者接口类型

public void feed(Animal animal){
	animal.eat();
}

对象造型:(父子类之间的强制转换)
通过instanceof判断

public void test(Animal animal) {
	if(animal instanceof Dog) {
		((Dog) animal).d();
	}
	if(animal instanceof Bird) {
		((Bird) animal).b();
	}
}
public void test2() {
	Dog dog=new Dog();
	Bird bird=new Bird();
	//兄弟类不能强制转换,编译错误
	//bird=(Bird)dog;   //error
	//继承关系,父类可以强制转换成子类对象,但是可能会发生运行时异常
	Animal dog2=new Dog();
	Animal bird2=new Bird();
	bird2=(Bird)dog2;   //运行时异常
}
 Feeder f=new Feeder();
    f.test(a);  //dog
	f.test(b);  //bird
	f.test2();  //java.lang.ClassCastException

static:修饰变量,方法,静态块
占内存不释放
使用:类名.static的成员
1.修饰变量:
变量:成员-> 类变量(静态变量): 由static修饰的成员变量; 实例变量 :没有static修饰
局部
类变量和实例变量的区别:
类变量对所有对象共享,公用
实例变量是归对象所有,不是公用
静态变量可以由类名调用

静态变量:类加载器加载类的时候初始化的

    int x;
	static int y;
	public static void main(String[] args) {
		DemoStatic d1=new DemoStatic();
		d1.x=10;
		d1.y=10;
		DemoStatic d2=new DemoStatic();
		d2.x=11;
		d2.y=11;
		System.out.println(d1.x+","+DemoStatic.y);
		System.out.println(d2.x+","+DemoStatic.y);
		}

结果:

10,11
11,11

在这里插入图片描述

练习:实现堆对象的计数功能

   public class DemoStatic {
	static int count = 0;
	DemoStatic(){
		count++;
	}
	public static void main(String[] args) {
	DemoStatic d1=new DemoStatic();
	DemoStatic d2=new DemoStatic();
	System.out.println(DemoStatic.count);
	}
}

变量的初始化过程:
static int x=5;
int x = 6;

2.修饰方法
静态方法:由static修饰 ,直接访问静态成员
实例方法:没有static修饰

 int x = 1;
    static int y = 2;
    void f(){

    }
    static void f2(){

    }

    void test1(){
        x = 2;  //ok
        y = 3;
        f();   //ok
        f2();
    }

    static void test2(){
        x = 2;  //error
        y = 3;
        f();    //error
        f2();
    }

静态方法是否可以重载?可以

    public static void test1() {
		
	}
    public static void test1(String str) {
		
	}

静态方法是否可以继承?可以

public class DemoStatic3 {
	public static void test1() {
		System.out.println("1111");
	}
    public static void main(String[] args) {
    	//Demo d=new Demo();
    	Demo.test1();
    }
}
class Demo extends DemoStatic3{
	
}

结果:1111

静态方法是否可以重写?不能

class Demo extends DemoStatic3{
	public static void test1() {
		System.out.println("222222222");
	}
}
public class DemoStatic3 {
	public static void test1() {
		System.out.println("1111");
	}
    public static void main(String[] args) {
    	DemoStatic3 demo=new Demo();
    	demo.test1();
    }

}

结果:1111

构造方法是否可以定义静态的?不可以

public static DemoStatic3() {
		
	}

报错,所以不可以

静态方法是否可以使用this,super? 不可以

int x=1;
public static void test1() {
	this.x=3;
	//System.out.println("1111");
}

报错

练习:

class TestSuper {
    public static void ma(){
       System.out.println("Super ma");
    }
    public void mb(){
        System.out.println("Super mb");
    }
}
class TestSub extends TestSuper {
     public static void ma(){
        System.out.println("Sub ma");
    }
    public void mb(){
       System.out.println("Sub mb");
    }
}
public class Test {
     public static void main(Stirng[] args){
         TestSuper ts = new TestSub();
         ts.ma();    //super ma
         ts.mb();    //sub mb
     }
}

3.静态块
static{

}

写到类体中,在类加载时,仅执行一次


public class Hello{
    static{
    //输出hello
      System.out.println("hello");
      }
}

练习:

public class A{
	static int x = 9;
	static{
		x = 10;
		y = 90;
		z = 20;
	}
	static int y = 100;
	static int z;
}        
              x = 10 y = 100,z = 20 
public class Testprivate static Test tester = new Test(); //step 1
    private static int count1;               //step 2
    private static int count2 = 2;           //step 3
    public Test(){                           //step 4
        count1++;
        count2++;
        System.out.println("" + count1 + count2); // 1 1  
    }
    public static Test getTester(){          //step 5
        return tester;
    }
    
    public static void main(String[] args){
       Test.getTester();
    }

静态块和构造块

父类的静态块->子类静态块->父类的构造块->父类的构造方法->子类的构造块->子类的构造方法

class A{                      1  11   2  3  22  33
   static{
      ........("1");
   }
   {
        .......("2");
    }
    public A(){

        .......("3");
    }
}
class B extends A{
   static{
      ........("11");
   }
   {
        .......("22");
    }
    public B(){
        .......("33");
    }
}

new B();

练习:

class A{
	static D d;
	static {.....("A1"); d = new D();}
	{.........("A2");}
	public A(){.........("A3");}
}

class B extends A{
	static C c = new C();
	static {.....("B1");}
	{.........("B2");}
	public B(){.........("B3");}}

class C{
	public C(){........("C");}
}

class D extends C{
	public D(){........("D");}
	
}
new B();  A1  C  D   C   B1  A2  A3  B2  B3

final:

final可以修饰类,方法,变量
fianl修饰的变量:常量 常量值不变
(对于数组来说,指的是内存地址,并不是里面的元素)

 final int NUM={1,2,3};
   void f(){
   NUM[0]=11;
   }
   Test t=new Test();
   t.f();
 System.out.println(Arrays.toString(t.NUM));

常量名:一般名字的所有字母都大写,如果有多个单词组成,单词之间用_
格式:final int PRICE = 10;
特点:不能改

final修饰的方法:不能重写
final修饰类:不能被继承

final 修饰的方法可以被继承

final练习

public class Sp {
	public final void m1(){
	       System.out.println("m1() in Super");
	    }
	    public void m1(int i){
	       System.out.println("m1(int) in Super");
	    }
}
public class Sb extends Sp{
    public void m1(int i){
       System.out.println("m1(int) in Sub");
    }
    public void m1(double d){
       System.out.println("m1(double) in Sub");
    }
}
public class Test {
    public static void main(String args[]){
       //如果这是Sp s = new Sb();  则下面的s.m1()则报错
       Sb s = new Sb();
       s.m1();     //m1() in Super
       s.m1(10);   //m1(int) in Sub
       s.m1(1.5);   //m1(double) in Sub
    }
}

abstract
1.抽象方法:由abstract修饰的方法
2.特点:没有方法体
3.抽象类:由abstract修饰的类 ------ 模块
4.特点:不能创建对象
5.抽象类中可以没有抽象方法
6.抽象类由子类创建对象
7.子类可以创建对象,要实现所有的抽象方法,
没有实现全部的抽象方法,当前类声明为抽象类

练习:定义一个类表示形状,提供获取周长和面积的方法,
然后给这个类提供子类:矩形 - 正方形,椭圆 - 圆形

1)定义抽象类Shape,两个抽象方法double getArea()和
double getLength()
2)定义子类Rectangle,(构造方法传参)
3)定义子类Oval,(构造方法传参) 周长:3.14ab
面积:23.14b+4*(a-b)
4)定义Rectangle的子类Square
5)定义Oval的子类Circle
6)测试:计算各种图形的面积周长

public abstract class Shape {
	public abstract double getArea();
	public abstract double getLength();
}
public class Rectangle extends Shape{
	double chang;
	double kuan;
    public Rectangle(double chang,double kuan) {
		this.chang=chang;
		this.kuan=kuan;
	}
	public double getArea() {
		// TODO Auto-generated method stub
		return chang*kuan;
	}
	public double getLength() {
		// TODO Auto-generated method stub
		return 2*(chang+kuan);
	}

}
public class Square extends Rectangle{
	double s;
	public Square(double s) {
		super(s,s);		
	}
}
public class Test {
	public static void main(String[] args) {
		Shape r=new Rectangle(1,2);
		System.out.println(r.getArea());
		System.out.println(r.getLength());
		Rectangle s=new Square(1);
		System.out.println(s.getArea());
		System.out.println(s.getLength());
	}
}

interface

1.定义接口
interface 接口名{
变量:int x = 10; 默认public static final修饰的
方法:抽象方法:默认访问修饰符:public abstract
普通方法:jdk8开始 default或者static
}

2.使用接口 implements

实现接口的类,要实现接口中的所有方法,才可以创建对象
如果不实现接口中的所有方法,当前类必须为abstract的类

3.接口和接口之间是继承关系

interface A{}
interface B extends A{}
interface C{}

4.类和接口之间是实现,可以实现多个接口
class Demo extends Object1 implmenents B,C{}

练习:

1.利用接口做参数,写个计算器,能完成加减乘除运算。

(1)定义一个接口ICompute
含有一个方法int computer(int n, int m)。

(2)设计四个类Add,Sub, Mul,Div分别实现此接口,完成加减乘除运算。

(3)设计一个类UseCompute,类中含有方法:
public void useCom(ICompute com, int one, int two),
此方法能够用传递过来的对象调用computer方法完成运算,并输出运算的结果。

(4)设计一个主类Test,调用UseCompute中的方法useCom来完成加减乘除运算。

public interface IComputer {
	int computer(int n,int m);
}
public class Add implements IComputer{
	public int computer(int n, int m) {
		return n+m;
	}
}
public class Sub implements IComputer{
	public int computer(int n, int m) {
		// TODO Auto-generated method stub
		return n-m;
	}
}
public class UserComputer {
	public void useCom(IComputer com,int one,int two) {
		System.out.println(com.computer(one, two));
	}
	public static void main(String[] args) {
		UserComputer u=new UserComputer();
		u.useCom(new Add(), 2, 1);
		u.useCom(new Sub(), 2, 1);
		u.useCom(new Mul(), 2, 1);
		u.useCom(new Div(), 2, 1);
	}
}

2.按如下要求编写Java程序:

(1)定义接口A,里面包含值为3.14的常量PI和
抽象方法double doubleArea(double radius)。//πr*r

(2)定义接口B,里面包含
抽象方法void setColor(String c)。

(3)定义接口C,该接口继承了接口A和B,
里面包含抽象方法
void volume(double radius,double height)//πrrh

(4)定义圆柱体类Cylinder实现接口C

public interface A {
	double PI=3.14;
	double doubleArea(double radius);
}
public interface B {
	void setColor(String c);
}
public interface C extends A,B{
	double volum(double radius,double height);
}
public class Cylinder implements C{
	String c;
	public double doubleArea(double radius) {
		// TODO Auto-generated method stub
		return A.PI*radius*radius;
	}
	public void setColor(String c) {
		// TODO Auto-generated method stub
		System.out.println(c);
	}
	public double volum(double radius, double height) {
		// TODO Auto-generated method stub
		return A.PI*radius*radius*height;
	}
}

接口jdk8新特性:

1.接口中可以定义普通方法
default void test(){
System.out.println(“test”);
}
static void test2(){
System.out.println(“test2”);
}

2.default修饰的方法由实现类调用
static修饰的方法可以由接口名直接调用
接口不能创建对象

3.实现类的接口和父类定义了同名方法,如何访问
访问父类的方法

4.如果两个接口中都定义了同名方法,如何访问?出现编译错误
子类必须重写同名方法

5.函数式接口:
接口中只有一个抽象方法->lambda表达式

接口和抽象类的区别
抽象类 接口
模板类 不同类型的公共的行为(规范JDBC)
不能多继承 可以多继承
有构造方法 没有构造方法
变量是普通的变量 都是公有静态常量
普通方法 普通方法由 default或者static修饰
抽象方法没有默认访问修饰符 访问修饰符是public


内部类

1.类体内部类

没有static修饰的内部类
outclass.innerclass name = new outclass().new innerclass();

public class Demo1 {
	private int x;
	public static int y;	
	//可以访问外部类的成员
	//不可以定义静态成员,但是可以定义静态常量
	//Demo1.Inner inner = new Demo1().new Inner();
	class Inner{
		final static int b =0;
		int a;
		void test3(){
			x = 0;
			y = 9;
			System.out.println("test3");
		}
	}
	public static void main(String[] args) {
		Demo1.Inner inner = new Demo1().new Inner();
		inner.test3();
	}
}

有static修饰的内部类
outclass.innerclass name = new outclass.innerclass();

 public class Demo2 {
	public int x ;
	public static int y;
	//可以访问外部静态成员
	//可以定义静态和非静态成员
	//Demo2.Inner inner = new Demo2.Inner();
	static class Inner{
		int a=0;
		static int b = 9;
		void f(){
			y = 9;
			System.out.println(y);
		}
	}
public static void main(String[] args) {
	Demo2.Inner inner = new Demo2.Inner();
	inner.f();
}
}

2.方法内的内部类

public class Demo3 {
	int x = 9;
	static int y = 9;
	void f(){
		int a = 9;
		//可以访问外部类的成员
		//不能定义静态成员,但是可以定义静态常量
		//方法内的变量被内部类访问后,变量别表示为常量
		class Inner{
			int b=0; //jdk1.7之后默认常量
			final static int c = 0;
			void f(){
				int r = a+0;
				x = 0;
				y = 9;
				System.out.println("!!!!!");
			}
		}
		new Inner().f();
	}
	public static void main(String[] args) {
		new Demo3().f();
	}
}

3.匿名类

匿名类可以继承父类,也可以实现接口,可以创建对象

 父类类型(接口类型) 变量名 = new  父类类型(接口类型)(){

匿名类的类体;

 }
public class Demo4 {
	//创建子类的对象
	Object obj = new Object(){
		@Override
		public String toString() {
			return "Hello";			
		}
	};
	IDemo demo = new IDemo(){
		@Override
		public void f() {
			System.out.println("接口方法的实现");			
		}		
	};
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(new Demo4().obj.toString());   //hello
		new Demo4().demo.f();    //接口方法的实现
	}



	//方法的参数使用匿名类实现
	public void test(IDemo demo){
		demo.f();
	}	
	public static void main(String[] args) {
		Demo4 demo4 = new Demo4();
		demo4.test(new IDemo(){
			@Override
			public void f() {
				System.out.println("接口方法的实现");			
			}		
		});
	}
}

匿名类练习

interface IA{  void ma(); }
class MyClass {
    public static void method(IA ia){
        System.out.println(“in method” );
        ia.ma();
    }
}
public class TestInnerClass{
    public static void main(String args[]){
    MyClass.method(new IA(){
        public void ma(){
           System.out.println(“ma in anonymous inner class” );                       
        }
    });
    class MyMaClass implements IA{
         public void ma(){
              System.out.println(“ma in local inner class” );
         }
    }
    MyClass.method(new MyMaClass());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值