• JavaSE 第二次学习随笔(二)


    循环结构中的多层嵌套跳出

    targeta:
    for(int i = 0; i < 100; i++){
    	for (int j = 0; j < 100; j++) {
    		if(i + j == 100){
    //			break targeta;
    			continue targeta;
    		}
    	}
    }
    

      

    数组

    * 一维数组里边存的是值(直接数据) 二维数组里边存的是一维数组的地址
    * 二维数组和一维数组一样都是数据类型 二维数组类型的构成: 数据类型 + [] + [] 创建格式 type [][] name = new
    * type[count][count_1]; count 是表示一维数组个数 count_1
    * 是二维数组对一维数组的长度的建议值(可以不写的啦)!!!!如果有一维数组长度和它不一样长那么其不会生效

    int[] a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    int[] b = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4 };
    
    int[][] c = new int[2][];
    c[0] = a;
    c[1] = b;
    
    for (int i = 0; i < c.length; i++) {
    	int[] js = c[i];
    	for (int j = 0; j < js.length; j++) {
    		int num = js[j];
    		System.out.print(num);
    	}
    	System.out.println();
    }
    

      

    增强for循环 : foreach 开始循环后从数组中取出第一个元素放入:前边的 变量中 使用其对 : 后边的 数组进行迭代

    for (int[] is : c) {
    	for (int i : is) {
    		System.out.print(i);
    	}
    	System.out.println();
    }
    

      

    学会了循环 就可以学习排序啦~ 排序完就可以使用二分查找了呢

            // 冒泡排序
    	public static int[] bubbleSort(int[] arr) {
    		int sum = 0;
    		for (int i = 0; i < arr.length - 1; i++)
    			for (int j = 0; j < arr.length - i - 1; j++)
    				if (arr[j] > arr[j+1]) {
    					arr[j+1] ^= arr[j];
    					arr[j] ^= arr[j+1];
    					arr[j+1] ^= arr[j];
    					sum++;
    				}
    		System.out.println(sum);
    		return arr;
    	}
         //选择排序
    	public static int[] selectSort(int[] arr) {
    		int sum = 0;
    		for (int i = 0; i < arr.length - 1; i++)
    			for (int j = arr.length - 1; j > i; j--)
    				if (arr[i] > arr[j]) {
    					arr[i] ^= arr[j];
    					arr[j] ^= arr[i];
    					arr[i] ^= arr[j];
    					sum++;
    				}
    		System.out.println(sum);
    		return arr;
    	}
    
    	
    	public static int[] binaryFind(int[] arr, int num) {
    		int startIndex = 0;
    		int endIndex = arr.length;
    		int middleIndex = 0;
    		int index = -1;
    		while (endIndex - startIndex >= 0) {
    			middleIndex = (endIndex + startIndex) >> 1;
    			int sBound = middleIndex - 1 > 0 ? middleIndex - 1 : 0;
    			if (num >= arr[sBound] && num <= arr[middleIndex]) {
    				index = sBound;
    				break;
    			} else if (num > arr[middleIndex]) {
    				startIndex = middleIndex + 1;
    			} else if (num < arr[middleIndex]) {
    				endIndex = middleIndex - 1;
    			}
    		}
    		int arr1[] = new int[arr.length + 1];
    		int j = 0;
    		for (int i = 0; i < arr.length; i++) {
    			arr1[j++] = arr[i];
    			if (i == index)
    				arr1[j++] = num;
    		}
    		Arrays.toString(arr1);
    		return arr1;
    	}
    

      

    接下来就要开始面向对象了, (牢骚 : 我还有对象, 可惜她不在我身边, 有些想她了, 虽然有好友在身边还是有点空落落的)

    * 面向对象初识
    * 开发的过程:不断的创建对象, 使用对象, 指挥对象做事情.设计类就是在管理和维护对象之间的关系
    * 面向过程强调的是功能行为,注重解决问题的步骤
    * 面向对象封装功能道对象里, 强调了具备功能的对象,关注的是解决问题需要哪些对象
    * 面向对象更加符合人类的思维方式, 使得程序员从执行者变为指挥者
    * 面向对象比面向过程更加高级
    * 面向对象和面向过程都是一种编程思想
    * 面向对象基于面向过程

    * 对于类, 拥有相似功能和特性的事物可以抽象成一个类
    * 对于类的对象的方法调用后系统直接释放它
    * 对于类的对象使用完后,系统会调用gc之后释放他

    * 成员变量的特点
    * 创建对象的时候被赋予默认值
    * 可以在类中定义对象的时候直接赋值
    * 可以在没有被static修饰的方法中直接使用

    * 成员变量和局部变量的比较
    * 作用域 成员变量的作用域是类的对象, 局部变量的作用域是方法
    * 默认值 成员变量有默认值, 局部变量没有默认值必须先初始化才能使用
    * 释放机制 成员变量和类保持一致 局部变量使用完立即释放(局部变量和方法的生命周期是一样的ma ?)
    * 存放机制 成员变量放在堆区中的对象中 局部变量放在栈区中的方法中
    *
    *
    * 成员变量分成静态的和非静态的 (static)
    * static : 静态成员和方法
    * 非 static : 非静态成员和方法
    * 静态的成员变量和放方法可以用引用调用也可以用类名调用
    * 非静态的成员变量和方法只能用引用调用

    事实上构造方法也是个static方法

    * 调用构造方法的构成: 类名+()
    * 作用: 对对象的属性进行初始化, 在没有自定义构造方法时, 能调用系统默认的无参构造方法
    *
    * 自定义类的构造方法:
    * 无参 + 有参
    *
    * 基本构成 : 修饰词 方法名 参数列表 方法体
    * 无返回值, 和类名相同
    *
    * 一旦自定义类的构造方法 系统就不会再有默认构造方法
    * 构造方法的内部会自动的进行属性的初始化
    * 多个构造方法之间是重载的关系
    *
    * 无参构造方法会将成员变量初始化成null或者0或者false等
    * 有参构造方法会将成员变量进行初始化并赋值, 赋值成通过参数传入的值
    * 有参方法中当方法形参和成员变量名字一致时, 方法内部是别的时形参 依据的时就近原则,
    * 就近原则时说从内存的角度考虑的就近原则
    *
    * 对于类: this是一种引用类型, 是一种引用数据类型, 代表的是当前的对象, 保存的是当前对象的地址
    * 在类内需要拿到当前类的引用的时候使用this.
    *
    * this 的作用 :
    * 区分成员变量和局部变量
    * 在构造方法中调用其他的重载的构造方法, 提高代码的复用性, 简化代码
    *
    * 通过this调用其他方法的时候必须放在当前方法的第一行
    * 不能相互调用会造成死循环
    * this() 作为方法只适用于构造


    Java中程序的 .java 程序的基本运行过程 (https://blog.csdn.net/Marvel__Dead/article/details/69220153?locationNum=5&fps=1)
    >> javac example.java >> java example.class >> jvm 调用ClassLoader 将example.class 加载到方法区, 当类被执行的时候 以main 方法作为入口
    进入execute 子系统 >> 任何方法在被线程调用时都会在栈区开辟新的内存空间 所以在多线程环境下方法的执行是互不干扰的, 但是成员变量是存储在堆区
    所以他们之间会互相干扰; >> 当在方法中有新建的对象时, 通过ClassforName(xxx.xxx.xxx).newInstance();创建类的过程是查看方法区是否有相应的.class 文件,
    如果有就用 newInstance创建对象, 没有就通过类的全路径加载 .class 然后再创建对象(new 出来的对象在堆中);

    对于类里边的静态成员变量和静态成员方法, 其存储在方法区, 静态成员变量存在于方法区的静态域中, 静态方法则存在于类的 .class 二进制信息中(.class 
    中的二进制信息和方法区中的不一样, 读取.class 文件按照jvm需要的格式存储在方法区, 这种格式包括数据结构方面), 静态成员变量和静态方法使用时不用创建对象, 
    类加载初始化后就可以使用, 并且线程是共享的

    在方法中声明的变量,即该变量是局部变量,每当程序调用方法时,系统都会为该方法建立一个方法栈,其所在方法中声明的变量就放在方法栈中,当方法结束系统会释放方法栈 ,其对应在该方法中声明的变量随着栈的销毁而结束,这就局部变量只能在方法中有效的原因

    * 静态代码块: 随着类的加载而加载, 在整个程序的过程中只执行一次,执行顺序优先级最高(高于main)
    * 构造代码块: 随着类对象的加载而记载每次创建对象都会执行一次
    * 静态代码块: 做类的初始化工作
    * 构造代码块: 做对象的初始化工作

    final:
    1,修饰类,变量(成员变量,静态变量,局部变量),函数。
    2,修饰的类不可以被继承。
    3,修饰的函数不可以被重写。
    4,修饰的变量是一个常量,只能赋值一次。
    5,使用final修饰符不仅会保持对象的引用不会改变,而且还会保护这个对象在回调方法中的生命周期,所以这才是final修饰变量和final修饰参数的根本意义
    final修饰的变量只能被赋值一次;由于赋值方式机制的不同因此分为两种情况:
    成员变量:由于分配内存后系统自动赋初值,这样使得此变量失去意义,因此在定义成员变量时需要赋值,或者在代码块,构造器中对其赋值
    局部变量:没有赋值,系统并不为它分配,栈内存,所以可以定义时可以赋值也可以不赋值,但是,形参作为局部变量,系统当将形参传递时已经赋值了所以,形参不能再
    次改变.
    宏变量:一个变量被final修饰且是编译时确定的。那么这个变量可称为宏变量。宏变量可以将引用指向常量池。
    (https://blog.csdn.net/gcw1024/article/details/51026840/ )  常量池

    程序中出现的不希望出现的数据为脏数据
    出现原因直接给变量赋值
    解决方案: 将成员变量变为private变量通过方法间接访问他;

    封装: (根据属性的封装来说明) 把成员变量的访问进行私有化, 通过一个公共的方法对其进行访问.好处: 提高了访问的安全性代码的可复用性易读性
    在方法内部先过滤再赋值

    继承
    *特殊类的对象拥有一般类的全部属性与行为,称为特殊类对一般类的继承。一个类可以是多个一般类的特殊类,也可以从多个一般类中继承属性与行为,但在java语言中,不允
    *许一个类从多个一般类中继承属性与行为,即在java语言中,只支持单继承。
      *在软件开发中,通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。因此,类的继承性使
    *所建立的软件具有开放性开放性、可扩充性,这是信息组织与分类的行之有效的方法,通过类的继承关系,使公共的特性能够共享,简化了对象、类的创建工作量,增加了代码
    *的可重用性。
    *重写
    *构造方法中默认自动调用super();
    * 在继承中使用构造方法
    *
    * *
    * 1.当一个子类中只有一个带参数的构造方法,只能使用带参数的,不能使用无参的.如果想使用,必须手动建立无参的构造方法
    * 2.当父类中只有带参数的构造方法,子类的构造方法中就必须在第一行手动调用父类带参数的构造方法(super(参数))
    * 3.当我们创建构造方法的时候,如果自己不写super(),系统会自动调用
    * 原因:父类中也有属性要进行初始化,而对象的属性必须由自己的构造方法进行初始化,所以必须调用super(),所以每个构造方法中都默认有一个super()
    *
    * 为什么要将super放在方法的第一行?
    * 答:在子类的构造方法中有可能用到父类的属性,而属性在使用之前必须先进行初始化,否则无法使用.
    *
    * 总之:在继承体系中,作为父类最好的办法就是将无参构造方法和有参构造方法都写了.
    * 重写:当子类有与父类同名(方法名,参数等完全相同)的方法,我们称为重写.
    * 注意点:相当于子类的同名方法将父类的覆盖了,不会再去调用父类的方法.
    *
    * 作用:在不改变父类方法名字的前提下,在父类原有方法的功能基础上,实现一些自己的功能.实现了对原有功能的扩充.
    *
    * this:是一种引用数据类型,代表当前的对象.保存的是当前对象的地址
    * super:不是一种引用数据类型.可以通过super调用父类的成员
    *
    * 注意事项:
    * 1.私有方法不能被重写
    * 2.子类的同名方法的权限大于等于父类的同名方法
    * 3.静态的方法只能覆盖静态的方法

    * 接口 interface
    * interface 接口的名字{
    * 成员变量默认 public final static
    * 成员方法默认 public abstract
    * 一般接口中不写成员变量, 只写方法和规则 又将接口称为方法列表
    * 需要子类实现方法
    * 继承 extends
    * 实现 implements
    *
    * 接口本身时抽象的
    *
    * 接口和继承同时存在
    * 接口自身可以多继承
    * 接口可以被多实现
    * 抽象类也一样可以impl接口
    *
    *
    * 父类中放入主要功能
    * 接口中放的是额外功能是类的补充 对类的方法行为的规定
    * 接口不能被实例化 它默认是抽象的
    * 接口与接口之间可以有继承的关系
    *
    * 一个类的接口中出现了相同的方法,子类实现时不会混淆,接口中的方法都是抽象的,只能通过子类具体实现, 该功能的实现只有子类中的一份;
    *
    *
    * 接口的作用: 将Java从单继承间接的实现多继承,扩充了原来的功能, 我们可以认为接口是类的补充.
    * jdk 1.7开始, 接口中可以有static或default 方法的实现

    * 多态下的向上转型和向下转型(向父类转型, 和向子类转型)
    *
    * 向上转型:子类对象->父类对象 安全
    * 向下转型:父类对象->子类对象 不安全
    * 向上转型: 相当于自动类型转换, 由低类型到高类型, 由子类型到父类型
    * >> 将子类类型引用(此引用指向的子类对象)转换成父类类型
    * 向下转型: 相当于强制类型转换, 由高类型到低类型
    * >> 将父类引用(此引用指向子类对象)转换成子类类型
    * Object str = new String();
    * ((String)str).toCharArray();

    * /---Object Height
    * | |
    * | |
    * -> Anmial |
    * | |
    * | |
    * ----> Dog, Cat Low
    * 类型Tree
    * //前段时间写错了
    * 一句话解释下边的错误:
    * Object obj = new Object();
    * (String)obj;
    * 这不是多态 也不存在向下转型
    *
    *
    * sysout(a instanceof B); a是B或B的子类对象 就是true 否则就是false (也就是说a类型必须大于等于b)
    * 此关键字 a的引用类型 和 B 要有继承关系(前后位置没问题) 如果没有关系立刻报错

    *
    * class Son extends Person{...}
    * Person s = new Son();
    *
    * 在多态下成员的使用方法: 其会根据引用类型调用方法除非强制类型转换
    * 成员变量: 编译时能不能访问看父类, 运行时也看父类
    * 成员方法: 编译时看父类, 运行时看子类
    * 静态方法: 编译运行都看父类-->静态方法从属于类啊 所以它和子类没关系吧(直接用类名调用的哇)
    *
    * 总结: 多态情况下 只有 >>普通成员方法<< 最特殊 编译的时候由于Java 仅仅是准动态语言所以在此时编译阶段对象还没装入内存, 因此
    * 方法能不能调用要看其引用类型中有没有这个方法
    * 运行时: 对象已经装入内存我们实际操作的已经是该对象了(子类类型)
    *
    *
    * ( https://www.zhihu.com/question/19883873)
    * 为什么Java没有做成动态语言(准动态语言)?
    * 静态类型有利于工具做静态分析,有利于性能优化,有利于代码可读性
    * 越是复杂的项目,使用静态语言可以利用编译器更早的发现和避免问题。
    * 这并不是说动态语言并不能用于大型项目,但是在超过一定规模之后, 动态语言轻便灵活的优势就会被重构时的overhead给抵消掉。
    * 另一个原因是性能上的。同理,也不是动态语言写不出高效的代码,而是你花在优化上的时间会更多,
    * 而团队人多了水平难免参差不齐,不如静态语言稳妥。

    内部类
    当 类C 同时需要实现A的功能 和B的功能时 可以建一个内部类 AA 对 A继承 BB对B继承 从而间接实现多继承
    局部内部类
    定义 : 在一个类的方法中的类
    作用 : 可以将功能在类中私有化, 整理代码, 提高复用性
    意义 : 对于被封装的方法, 相当于将他的一部分功能面向对象了
    了解 :
    例子 : 对于类中的方法a() 和 b() 和c() 想要对 b() 屏蔽 c() 方法[即b()无法调用c()]
    只允许a()运行c(), 此时 将 c() 封装到 a() 中的局部内部类中

    class Test{
    	void a(){
    		class C{
    			void c(){}
    		}
    	}
    	void b(){
    	}
    }
    

      


    TIP:
    A:可以直接访问外部类的成员
    B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能。
    局部内部类访问局部变量的注意事项
    A:局部内部类访问局部变量必须用final修饰(1.7 之前)
    B:为什么呢?
    因为局部变量会随着方法的调用而调用,随着调用完毕而消失。
    而堆内存的内容并不会立即消失。所以,我们加final修饰
    加入final修饰后,这个这变量就成了常量。既然是常量。你消失了。
    我在内存中存储的是数据20,所以,我还是有数据在使用。

  • 相关阅读:
    [转载] $CF652B$ 题解
    [转载] $Luogu$ $P4951$ 题解
    luoguP3723 HNOI2017 礼物
    动态dp学习笔记
    noip级别模板小复习
    noip2017简要题解。
    noip考前抱佛脚 数论小总结
    HDU 6071 Lazy Running
    POI2012 ODL-Distance
    [NOI2002]荒岛野人
  • 原文地址:https://www.cnblogs.com/chinashenkai/p/9429693.html
Copyright © 2020-2023  润新知