尚硅谷Java学习笔记-基础部分-6

前言
记录没有条理性,记一些自己没怎么用过,但是比较重要的内容。所以不是那么全面。
因为自己有一些java基础,为秋招准备的。大家看看就好,有错误的地方欢迎指正。、

本节内容:面向对象-下,关键字static,单例模式,final,abstract,interface,代码块,内部类。

一、关键字static

静态的。
可以用来修饰属性,方法,代码块和内部类

1、修饰属性

希望无论产生多少对象,某些特定的数据在内存空间只有一份
两个不同对象有各自不同的属性,比如C1对象中的radius和C2对象中的radius属性互无关系,存在不同的空间。而有些属性在对象中共享,成为类属性,同类方法,不用创建对象就可以调用。

  • 静态属性:也叫类变量。多个对象共享,当某一个对象修改之时,其他对象看到的是修改过的静态属性。
  • 非静态属性:也叫实例变量。每个对象都有各自的,来自于类的非静态属性。你改你的我改我的互不影响。

特性

  • 随着类的加载而加载,先于对象存在。
  • 为所有对象共享,可不创建对象直接用类调用。
  • 类可以调类变量,不能调实例变量;对象可以调类变量,也可以调实例变量。

内存解析
在这里插入图片描述

2、修饰方法

凡是静态的,都随着类的加载而加载,可以通过“类.静态方法”调用。

  • 静态方法中(即类中),只能调用静态的方法和属性,生命周期一致;静态只能调静态
  • 非静态方法中(即对象中),既可以调用非静态(对象)的方法和属性,也可以调用静态的方法和属性。
3、注意点

在静态的方法中,不能使用this和super(代表的是本类和父类),用生命周期来理解,静态方法不能被重写。

4、使用场合

静态属性:可以被多个对象共享的,不会随对象不同而不同的。或者,常量。
静态方法:操作静态属性的方法。或者,工具类中的方法:Math.sqrt,Arrays.sort…,Collections,直接用类名调用工具。

5、举例
package com.atguigu.java1;
//static关键字的应用
public class CircleTest {
	public static void main(String[] args) {
		
		Circle c1 = new Circle(); //根据下面的构造器,这里自动赋值了id
		
		Circle c2 = new Circle();
		
		Circle c3 = new Circle(3.4);
		System.out.println("c1的id:" + c1.getId() );
		System.out.println("c2的id:" + c2.getId() );
		System.out.println("c3的id:" + c3.getId() );
		
		System.out.println("创建的圆的个数为:" + Circle.getTotal()); //类.静态变量
		
	}
}

class Circle{
	
	private double radius;  //不同圆半径不同,所以不用static
	private int id; //圆的编号,每个人不同,但是相互之间有++关系,所以有静态的init来负责id赋值
	
	public Circle(){ //构造器一
		id = init++; //init是多个对象共享,所以是static,值为1001赋给id,再++
		total++;  //记录对象-圆的个数
	}
	
	public Circle(double radius){  //构造器二
		this();
//		id = init++;
//		total++;
		this.radius = radius;
		
	}
	
	private static int total;//记录创建的圆的个数,类自己管理就好,不用给到对象。
	private static int init = 1001;//static声明的属性被所有对象所共享,相当于总的管理处
	
	public double findArea(){return 3.14 * radius * radius;}
	public double getRadius() {return radius;}
	public void setRadius(double radius) {this.radius = radius;}
	public int getId() {return id;}
	
	public static int getTotal() { //total是静态变量,所以该方法也是static
		return total;
	}

}

二、设计模式

1、概念

大量实践中总结和理论化之后的优选的代码结构,编程风格,思考方式。
单例模式:采用方法让整个软件系统中,某个类只存在一个对象实例,且该类只提供一个取得其对象实例的方法。
具体操作:类的构造器权限为private,故只能在类的内部new对象。所以类的外部只能调用类的静态方法来返回类内部创建的这个对象,所以
翻译成人话:即在类外,不能用new某个对象来使用其属性了,只能“类.方法”或者“类.属性”使用其方法。所以,这里的方法必须是静态的,才能“类.方法”,所以该方法中的变量也必须是静态的。

2、实现

饿汉式 vs 懒汉式

package com.atguigu.java2;

public class SingletonTest1 {
	public static void main(String[] args) {
//		Bank bank1 = new Bank();  这个时候就没办法new了,因为其构造器为private,现在在类外
//		Bank bank2 = new Bank();

		//饿汉式
		Bank bank1 = Bank.getInstance(); //只能通过bank类中的静态方法来新建对象
		Bank bank2 = Bank.getInstance();
		System.out.println(bank1 == bank2); //返回true,因为static是共享空间,地址一样(==比较的是地址)
		
		//懒汉式
		Order order1 = Order.getInstance();
		Order order2 = Order.getInstance();
		System.out.println(order1 == order2);
	}
}

//饿汉式
class Bank{
	
	//1.私有化类的构造器,构造器不加static
	private Bank(){	
	}
	
	//2.内部创建类的对象
	//4.要求此对象也必须声明为静态的,这里注意前面的private static
	private static Bank instance = new Bank();  //上来就new好,饿汉,上来就把事情做完
	//Bank instance = new Bank();
	
	//3.提供公共的静态的方法,返回类的对象,类外调用此方法
	public static Bank getInstance(){
		return instance;
	}
}

//懒汉式
class Order{

	//1.私有化类的构造器
	private Order(){		
	}
	
	//2.声明当前类对象,没有初始化
	//4.此对象也必须声明为static的
	private static Order instance = null; //饿汉懒汉以此为区分,这里先不创建,后面需要的再创建
	
	//3.声明public、static的返回当前类对象的方法
	public static Order getInstance(){		
		if(instance == null){ //啥时候用啥时候造		
			instance = new Order();			
		}
		return instance;
	}	
}

饿汉式:坏:对象加载时间(对象在内存中存在的时间)过长;好:但是线程安全。
懒汉式:好:推迟对象的创建,要用了再造,节省内存空间;坏:但是线程不安全,俩个人同时抢到一张票。到多线程内容时再修改。

3、使用场景
  • 网站的计数器,应用程序的日志应用
  • 数据库连接池:使用数据库首先需要连接,而这么多连接先连接好,都放在连接池中,这个池子就是单例模式,只有一个
  • application进程,任务管理器等

三、main的使用

  • 程序的入口,是一个普通的静态方法。
    之前的main中调用类中的属性时,需要先新建对象才能调用其属性,因为main是static的,所以只能调用static的属性,所以只需要在之前的属性前加上static。

  • 可以作为与控制台交互的方式。 之前:使用Scanner,现在:在eclipse中右键-run as跑一下,再run as-run configuration,找到该类,选择arguments,填入参数,即为输入args到main中。
    在这里插入图片描述
    其中,只有数值型的才能转换为int型。

如何将控制台获取的数据传给形参:String[] args?比如运行时:java 类名 “Tom” “Jerry” “123” “true”

sysout(args[0]);//"Tom"
sysout(args[3]);//"true"  -->Boolean.parseBoolean(args[3]);
sysout(args[4]);//报异常

四、代码块

作用:初始化类和对象。要么不加关键词,要加就只有static。
分类:static静态和非静态的。
初始化的顺序

  • 默认初始化(系统给的)
  • 显式初始化(类中定义属性时int Id = 3)/ 在代码块中赋值
  • 构造器初始化
  • 对象.属性或者对象.方法
static{...},静态
{...},非静态
1、静态代码块
  • 作用:初始化的信息,内部可以有输出。随着类的加载并且执行里面的代码,而且只执行一次,跟着类而非对象走
  • 如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行。静态代码块的执行要优先于非静态代码块的执行。一般开发中不会写很多的代码块,会合到一起。
  • 静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构即静态只能调静态
2、非静态代码块
  • 作用:可以在创建对象时,对对象的属性等进行初始化。内部可以有输出语句。随着对象的创建而执行,每创建一个对象,就执行一次非静态代码块
  • 如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
  • 非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法。(对象可以调用非静态和静态,类无法调非静态,因为只有具体的对象创建出来,才能调用个性化的非静态)
3、 实际应用
//常量池的应用datasource
public class JDBCUtils{
	private static DataSource dataSource = null; //常量池类,先是定义为null,需要的时候再创建对象,懒汉式
	static{
		...
		... //准备创建datasource对象所需要的资源
		dataSource = 。。。。 //创建对象了
		//因为创建这个对象需要做诸多准备工作,这些工作不能作为属性直接放在前面private的前面,所以放在了代码块中,准备好了再创建。
		//又因为是静态的代码块,所以只造一次。不管新建了多少对象,只跟着类走。常量池值新建了一次。并且只调用静态的属性
		//属性不可以调方法,代码块中可以
	}
}
class A{ //类
	
	int a; 
	a += 1; 或 a = 1;//错误,类中的属性不能这样赋值
	
	int a = 1; //对
	
	int b(){ //方法
	}
}

涉及到继承中的代码块,顺序:由父及子,静态现行。静态 > 非静态 > 构造器。

五、关键词final

用于修饰:类,方法,变量

1、final修饰类

此类不能被其他类继承,比如String类,System类,StringBuffer类

2、final修饰方法

此方法不能被重写,比如Object类中的getClass();

final class FinalA{
}
class B extends FinalA{ //报错,final类无法继承
}

class AA{
	public final void show(){
	}
}
class BB extends AA{
	public void show(){ //报错,final方法不可以被重写
	}
}
3、final修饰变量:常量。
  • 修饰属性:可以考虑赋值的位置,显式初始化,代码块中显式初始化,构造器中初始化
    final int WIDTH = 0;
    final int LEFT;
    final int RIGHT;
    {
    LEFT = 1;
    }
    public FinalTest(){
    	RIGHT = 2;
    }
    
  • 修饰局部变量(即方法中的):final修饰形参时,表明此形参是个常量,且只能在方法体中使用,且不能重新赋值。
    public void show(){
    final int NUM = 10;//常量
    //	NUM += 20;
    }
    
    public void show(final int num){ 
    //	num = 20;//编译不通过。在传入形参的时候已经赋值了,不能重新赋值
    	System.out.println(num);
    }
    
  • static final修饰属性:全局常量

六、关键字abstract

可以用来修饰类,方法

1、abstract修饰类:抽象类
  • 此类不可实例化;一定有构造器,供子类在实例化时调用,开发中会提供抽象类的子类。
  • 抽象只是不能实例化,是可以被继承的。
2、abstract修饰方法:抽象方法
  • 抽象方法只有方法的声明,没有方法体;
  • 包含抽象方法的类,一定是个抽象类。反之,抽象类中可以没有抽象方法。
  • 子类重写了父类的所有的抽象方法后,此子类方可实例化。若没有重写父类的全部抽象方法,说明此子类依然是个抽象类,需要前面加上abstract。
public class AbstractTest {
	public static void main(String[] args) {
		
		//一旦Person类抽象了,就不可实例化
//		Person p1 = new Person();
//		p1.eat();

		Student s1 = new Student();  //student将所有的抽象方法重写了,所以可以实例化了
		s1.eat();
		s1.breath();
		
	}
}

abstract class Creature{ //抽象类
	public abstract void breath();  //抽象方法breath
}

abstract class Person extends Creature{  //有抽象方法eat,故依然是抽象类
	String name;
	int age;
	
	public Person(){
		
	}
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	
	//不是抽象方法:
//	public void eat(){
//		
//	}
	//抽象方法
	public abstract void eat();
	
	public void walk(){
		System.out.println("人走路");
	}
	
	
}


class Student extends Person{
	
	public Student(String name,int age){
		super(name,age);
	}
	public Student(){
	}
	
	public void eat(){  //重写直接父类中的抽象方法
		System.out.println("学生多吃有营养的食物");
	}

	@Override
	public void breath() {  //重写间接父类中华的抽象方法
		System.out.println("学生应该呼吸新鲜的没有雾霾的空气");
	}
	//如此,才可以实例化
}
3、注意点
  • 不能用abstract修饰:属性,构造器。因为abstract核心就是不给值,所以属性代码块不能。
  • 不能用abstract修饰:私有方法(私有方法本来就不能继承给子类),静态方法(static在内共享区域),final方法final(不能重写)
4、模板方法设计模式

功能内部一部分实现是确定的,一部分是不确定的。这时可以把不确定的部分暴露出去,让子类

七、接口interface

1、定义
  • 从几个类中抽取出一些共同的行为特征,他们之间没有is a关系,但是有相同的行为特征。继承:子类 is a 父类,即是不是接口能不能
  • 接口的本质是契约,标准,规范。接口与类是并列的两个结构。
  • 接口是抽象方法和常量值定义的集合。
2、特点
  • 所有成员变量都是public static final修饰,全局常量
  • 所有抽象方法都是public abstract修饰的,抽象方法
  • 接口中没有构造器,不能实例化
3、使用
  • 接口通过让类去实现implements的方式来使用。
    如果这个类覆盖了接口中的所有抽象方法,那么这个类可以实例化
    如果实现类没有覆盖接口中的所有抽象方法,那么这个类仍然为抽象类,无法实例化。
  • java类可以实现多个接口,弥补了java单继承性的局限性。
    class AA extends BB implements CC,DD,EE
  • 接口和接口之间可以继承,而且可以多继承。
    interface CC extends AA,BB
public class InterfaceTest {
	public static void main(String[] args) {
		System.out.println(Flyable.MAX_SPEED);
		System.out.println(Flyable.MIN_SPEED);
//		Flyable.MIN_SPEED = 2;
		
		Plane plane = new Plane();
		plane.fly();
	}
}


interface Flyable{ //接口:能不能
	
	//全局常量
	public static final int MAX_SPEED = 7900; //第一宇宙速度
	int MIN_SPEED = 1; //省略了public static final
	
	//抽象方法
	public abstract void fly();
	//省略了public abstract
	void stop();
	
	
	//Interfaces cannot have constructors 接口不能有构造器
//	public Flyable(){
//		
//	}
}

interface Attackable{
	
	void attack();
	
}

class Plane implements Flyable{ //接口flyable的两个方法都被覆盖了,所以Plane类可以实例化

	@Override
	public void fly() {
		System.out.println("通过引擎起飞");
	}

	@Override
	public void stop() {
		System.out.println("驾驶员减速停止");
	}
	
}

abstract class Kite implements Flyable{  //没有覆盖flyable的所有方法,所以仍然是抽象类abstract

	@Override
	public void fly() {
		
	}
	
}

class Bullet extends Object implements Flyable,Attackable,CC{ //重写了是三个接口的所有方法,所以Bullet可以实例化造对象

	@Override
	public void attack() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void stop() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void method1() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void method2() {
		// TODO Auto-generated method stub
		
	}
	
}
//************************************

interface AA{
	void method1();
}
interface BB{
	
	void method2();
}

interface CC extends AA,BB{  //接口继承接口
	
}

关于接口的多态性

class Computer{
	
	public void transferData(USB usb){//USB usb = new Flash();
		usb.start();
		
		System.out.println("具体传输数据的细节");
		
		usb.stop();
	}
	
	
}

interface USB{
	//常量:定义了长、宽、最大最小的传输速度等
	
	void start();
	
	void stop();
	
}

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("打印机结束工作");
	}
	
}

体会:

  • 1.接口使用上也满足多态性
  • 2.接口,实际上就是定义了一种规范
  • 3.开发中,体会面向接口编程!比如数据库,在应用程序中调用的接口都是JDBC定义的接口,不会出现具体某个数据库厂商的API。
4、面向接口编程
  • Java8中关于接口的新规范
    • 知识点1:接口中定义的静态方法,只能通过接口来调用。
    • 知识点2:通过实现类的对象,可以调用接口中的默认方法。如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写以后的方法
    • 知识点3:如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,那么子类在没重写此方法的情况下,默认调用的是父类中的同名同参数的方法。–>类优先原则
    • 知识点4:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,那么在实现类没重写此方法的情况下,报错。–>接口冲突。这就需要我们必须在实现类中重写此方法
    • 知识点5:如何在子类(或实现类)的方法中调用父类、接口中被重写的方法
public void myMethod(){
	method3();//调用自己定义的重写的方法
	super.method3();//调用的是父类中声明的
	//调用接口中的默认方法
	CompareA.super.method3();
	CompareB.super.method3();
	}
  • 面试题:
    抽象类和接口的异同?
    相同点:不能实例化;都可以包含抽象方法的。
    不同点
    1)把抽象类和接口(java7,java8,java9)的定义、内部结构解释说明
    2)类:单继承性 接口:多继承
    类与接口:多实现

八、代理模式

为其他对象提供一种代理以控制对这个对象的访问。

interface NetWork{
	
	public void browse(); //浏览
	
}

//被代理类
class Server implements NetWork{

	@Override
	public void browse() {
		System.out.println("真实的服务器访问网络");
	}

}
//代理类
class ProxyServer implements NetWork{
	
	private NetWork work;
	
	public ProxyServer(NetWork work){
		this.work = work;
	}
	

	public void check(){
		System.out.println("联网之前的检查工作");
	}
	
	@Override
	public void browse() {
		check();
		
		work.browse();
		
	}
	
}

在这里插入图片描述

九、工厂模式

  • 解决的问题
    实现了创建者与调用者的分离,即将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。

  • 具体模式

    • 简单工厂模式:用来生产同一等级结构中的任意产品。(对于增加新的产品,需要修改已有代码)
    • 工厂方法模式:用来生产同一等级结构中的固定产品。(支持增加任意产品)
    • 抽象工厂模式:用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)

十、内部类(基本不用)

内部类:类的第五个成员

  • 定义:Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类.
  • 内部类的分类:
    成员内部类(静态、非静态 ) vs 局部内部类(方法内、代码块内、构造器内)
  • 成员内部类的理解:

一方面,作为外部类的成员:

  • 调用外部类的结构
  • 可以被static修饰
  • 可以被4种不同的权限修饰

另一方面,作为一个类:

  • 类内可以定义属性、方法、构造器等
  • 可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承
  • 可以被abstract修饰、

成员内部类:

  • 如何创建成员内部类的对象?(静态的,非静态的)
//创建静态的Dog内部类的实例(静态的成员内部类):
Person.Dog dog = new Person.Dog();

//创建非静态的Bird内部类的实例(非静态的成员内部类):
//Person.Bird bird = new Person.Bird();//错误的
Person p = new Person();
Person.Bird bird = p.new Bird();
  • 如何在成员内部类中调用外部类的结构?
class Person{
	String name = "小明";
public void eat(){
}
//非静态成员内部类
	class Bird{
		String name = "杜鹃";
		public void display(String name){
			System.out.println(name);//方法的形参
			System.out.println(this.name);//内部类的属性
			System.out.println(Person.this.name);//外部类的属性
		//Person.this.eat();
		}
	}
}
  • 局部内部类的使用:
//返回一个实现了Comparable接口的类的对象
	public Comparable getComparable(){
		
		//创建一个实现了Comparable接口的类:局部内部类
		//方式一:
//		class MyComparable implements Comparable{
//
//			@Override
//			public int compareTo(Object o) {
//				return 0;
//			}
//			
//		}
//		
//		return new MyComparable();
		
		//方式二:
		return new Comparable(){

			@Override
			public int compareTo(Object o) {
				return 0;
			}
			
		};
		
	}
  • 注意点:
    在局部内部类的方法中(比如:show如果调用局部内部类所声明的方法(比如:method)中的局部变量(比如:num)的话,要求此局部变量声明为final的。
    jdk 7及之前版本:要求此局部变量显式的声明为final的
    jdk 8及之后的版本:可以省略final的声明
  • 总结:
    成员内部类和局部内部类,在编译以后,都会生成字节码文件。
    格式:成员内部类:外部类 $ 内部类名.class;局部内部类:外部类 $ 数字内部类名.class

面向对象终于更完了,呼~。一周忙着回家,做项目,没有之前更新的快了。虽然但是感觉自己写过的又忘记了,害。

不经一番寒彻骨,怎得梅花扑鼻香

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值