Java基础三个排序详解_继承粗解语法关键字分析

集合存放数据的容器,存放的数据可以是基本类型也可以是引用类型,数据类型必须一致,存放数据的空间是连续的即地址连续,长度固定
声明数组变量
首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:

dataType[] arrayRefVar; // 首选的方法 
dataType arrayRefVar[]; // 效果相同,但不是首选方法

注意: 建议使用 dataType[] arrayRefVar 的声明风格声明数组变量。
dataType arrayRefVar[] 风格是来自 C/C++ 语言 ,在Java中采用是为了让 C/C++ 程序员能够快速理解java语言。
创建数组
Java语言使用new操作符来创建数组,语法如下:
arrayRefVar = new dataType[arraySize];
上面的语法语句做了两件事:
一、使用 dataType[arraySize] 创建了一个数组。
二、把新创建的数组的引用赋值给变量 arrayRefVar。
数组变量的声明,和创建数组可以用一条语句完成,如下所示:
dataType[] arrayRefVar = new dataType[arraySize];
另外,你还可以使用如下的方式创建数组。
dataType[] arrayRefVar = {value0, value1, …, valuek};
数组的元素是通过索引访问的。数组索引从 0 开始,所以索引值从 0 到 arrayRefVar.length-1。

例一:

public class ArrayDf{
	public static void main(String[] args){
		String[] stringArray; 
//主方法栈帧中创建一个String[]类型变量,存放一个String[]类型的变量,里面包含若干元素,引用类型
		//String[]是一种类型,不能有下标
		//数组变量存储的位置看定义的位置,比如static——静态数据区
		stringArray = new String[10]; 
//创建对象在堆区,开辟10个String[]类型的空间相当于创建了10个连续的变量,初值一样
       stringArray[1]="two";  
//把two赋给stringArray[]所指数组对象的第二个元素
//数组名对应数组元素空间地址,数组对象每一个元素的空间
//元素名和变量名类似,寻址方式不同,导致叫法不同
//变量——直接寻址
//元素——间接寻址
//元素名:元素空间首地址+下标
//有确切的初值null
//一个new String一次创建两个对象,分别储存在堆中和方法区的常量池
//元素个数已经定义,是final不可分割,不可改变的
		System.out.println("元素默认初始化值是:"+stringArray[2]); 
//输出String[]类型
	   System.out.println("元素默认初始化值是:"+stringArray);
	}	
}

例二:

public class StaticInitArray{
	public static void main(String[] args){
	     int[]a = {1,3,5,7,9,11};//这种初始化只能在声明时使用
主方法栈帧中开辟空间,创建变量a,int[]类型,不会默认初始化
在类中定义的实例变量(堆)和静态全局变量(方法区静态数据区)会默认初始化,在栈桢中不会默认初始化
    	 	//int[] a;
		    //a= {1,3,5,7,9,11}; 错误这属于赋值不是初始化
			//初始化有默认初始化,显式初始化			
			//显示初始化是在定义变量的时候
			//赋值可以多次,初始化只能有一次
          int[]k=new int[0];
		 //System.out.println(k[0]);
		  //int[]m=new int[-10];
			int[]num;
			num=new int[]{1, 2, 3, 4, 5};
		既可以初始化,也可以赋值,比较灵活
		int[]b = new int[3]; //指定元素个数3,默认为0
		b=num;
		b原来所指的数组对象地址丢失,游离,内存泄露		
//b,num都是首元素地址
		a,b,num类型相同,可以相互赋值
		b[2]=100;
		for (int i = 0;i<b.length;i++){
			System.out.println(num[i]);
		}		
	    System.out.println("--------------------");
		for (int i:b){ //拿出数组元素赋给i
			System.out.println(i);
		}
	集合可以存放不同类型对象的地址,数组也可以,但必须是object[]类型
	}	
}

多维数组
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组,例如:

String str[][] = new String[3][4];

多维数组的动态初始化(以二维数组为例)
1. 直接为每一维分配空间,格式如下:

type[][] typeName = new type[typeLength1][typeLength2];

type 可以为基本数据类型和复合数据类型,arraylength1 和 arraylength2 必须为正整数,arraylength1 为行数,arraylength2 为列数。
例如:

int a[][] = new int[2][3];

解析:
二维数组 a 可以看成一个两行三列的数组。
2. 从最高维开始,分别为每一维分配空间,例如:

String s[][] = new String[2][]; 
s[0] = new String[2]; 
s[1] = new String[3]; 
s[0][0] = new String("Good"); 
s[0][1] = new String("Luck"); 
s[1][0] = new String("to"); 
s[1][1] = new String("you"); 
s[1][2] = new String("!");

解析:
s[0]=new String[2] 和 s[1]=new String[3] 是为最高维分配引用空间,也就是为最高维限制其能保存数据的最长的长度,然后再为其每个数组元素单独分配空间 s0=new String(“Good”) 等操作。
多维数组的引用(以二维数组为例)
对二维数组中的每个元素,引用方式为 arrayName[index1][index2],例如:

num[1][0];

Arrays 类
java.util.Arrays 类能方便地操作数组,它提供的所有方法都是静态的。
具有以下功能:
• 给数组赋值:通过 fill 方法。
• 对数组排序:通过 sort 方法,按升序。
• 比较数组:通过 equals 方法比较数组中元素值是否相等。
• 查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作。
具体说明请查看下表:
序号 方法和说明

1	public static int binarySearch(Object[] a, Object key)

用二分查找算法在给定数组中搜索给定值的对象(Byte,Int,double等)。数组在调用前必须排序好的。如果查找值包含在数组中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。

2	public static boolean equals(long[] a, long[] a2)

如果两个指定的 long 型数组彼此相等,则返回 true。如果两个数组包含相同数量的元素,并且两个数组中的所有相应元素对都是相等的,则认为这两个数组是相等的。换句话说,如果两个数组以相同顺序包含相同的元素,则两个数组是相等的。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。

3	public static void fill(int[] a, int val)

将指定的 int 值分配给指定 int 型数组指定范围中的每个元素。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。

4	public static void sort(Object[] a)

对指定对象数组根据其元素的自然顺序进行升序排列。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。

length属性,length()方法和size()的方法的区别
1.length属性是针对Java中的数组来说的,要求数组的长度可以用其length属性;
2.length()方法是针对字符串来说的,要求一个字符串的长度就要用到它的length()方法;
3.java中的size()方法是针对泛型集合说的,如果想看这个泛型有多少个元素,就调用此方法来查看!

public static void main(String[] args) {
    String []list={"ma","cao","yuan"};
    String a="macaoyuan";
    System.out.println(list.length);
    System.out.println(a.length());
    List array=new ArrayList();
    array.add(a);
    System.out.println(array.size());
}

冒泡法排序的基本思想:
从前向后(或从后向前)依次比较相邻两个元素的大小,如果逆序(与题意要求的顺序相反)就进行交换,使最小(最大)的元素上浮(下沉)到本次排序的最前面(最后面),从而完成一趟(pass)排序。下一趟排序时,已经有序的元素不再参与。这样的话,n个元素需要进行n-1趟排序
冒泡排序的关键点:
(1)采用双层循环:时间复杂度为O(n的平方)
外层循环表示的是排序的趟数,n个数字需要n-1趟,因此,外层循环的次数是n-1次;
内层循环表示的是每一趟排序的数字。根据冒泡排序的思想,第i趟排序后,就会有i个数属于有序的元素,它们不参与第i+1趟的排序。因此,用一个循环来控制,只是不同的方式的写法不一样,望学者理解掌握。
(2)相邻两个数只要属于逆序,就实行交换。正序就不交换,因此,是稳定排序;也就是说,即使序列中出现相同的两个数字,它们不会实施交换,相同数字的相对顺序不会发生变化!

选择排序的基本思想:
找到当前数字序列中最大(最小)的数,记录其所在位置,将其和最前面(最后面)的数进行交换,使最小(最大)的元素上浮(下沉)到本次排序的最前面(最后面),从而完成一趟(pass)排序。下一趟排序时,已经有序的元素不再参与。这样的话,n个元素需要进行n-1趟排序
选择排序的关键点:
(1)采用双层循环:时间复杂度也是O(n的平方)
外层循环表示的是排序的趟数,n个数字需要n-1趟,因此,外层循环的次数是n-1次;同时也代表数的位置。
内层循环表示的是每一趟排序的数字。根据选择排序的思想,第i趟排序时,最前面的位置就是i,用一个循环来不断更新。
(2)找到最值数的位置,将该位置的数和当前序列最前面(最后面)位置的数进行交换;。(稳定排序)

插入排序的基本思想是:
将数组的第一个数认为是有序数组,从后往前(从前往后)扫描该有序数组,把数组中其余n-1个数,根据数值的大小,插入到有序数组中,直至数组中的所有数有序排列为止。这样的话,n个元素需要进行n-1趟排序
插入排序的关键点:
 采用双层循环:时间复杂度也是O(n的平方)
(1)外层循环表示的是排序的趟数,n个数字需要n-1趟,因此,外层循环 的次数是n-1次;同时也代表数的位置。
(2)内层循环表示的是每一趟排序的数字。根据插入排序的思想,第i趟排 序时,有序数组中的数字就有i个,就需要进行i次比较,因此循环i次。注 意采用的是从后往前进行比较。
 从后往前扫描的时候,如果必须插入的数大于有序数组中当前位置的数,则有序数组中的数和它之后的数均往后移一个位置,否则,把插入的数插入到有序数组中。(稳定排序)

继承类型
需要注意的是 Java 不支持多继承,但支持多重继承。

在这里插入图片描述

继承的特性

  1. 子类拥有父类非 private 的属性、方法。
  2. 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
  3. 子类可以用自己的方式实现父类的方法。

Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如A类继承B类,B类继承C类,所以按照关系就是C类是B类的父类,B类是A类的父类,这是Java继承区别于C++继承的一个特性。提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。

继承关键字
继承可以使用extends和implements这两个关键字来实现继承,而且所有的类都是继承于java.lang.Object,当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。
extends关键字
在Java中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以extends只能继承一个类。
implements关键字
使用implements关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。
super 与 this 关键字
**super关键字:**我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
**this关键字:**指向自己的引用。
final关键字 final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写:

声明类:
final class 类名 {//类体}
声明方法:

修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}

**注:**实例变量也可以被定义为 final,被定义为 final 的变量不能被修改。被声明为 final 类的方法自动地声明为 final,但是实例变量并不是 final

构造器
子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。
如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。

代码分析
只创建了一个子类对象,父类对象没有创建
不会创建父类对象,但是会为父类的私有属性在堆中开辟空间,四个字节,会默认初始化为0
但这个空间不属于父类对象,也不属于子类对象,而是和定义这个属性的父类做动态绑定

 class Animal{   
	private int weight;		
	Boolean sex; //可以被继承
	//父类构造方法
	public Animal(){
		System.out.println("Animal(): "+this);
		this.weight=20;
//根据this.weight,拿到this地址优先在子类中找weight属性,没有就会到构造方法动态绑定的Animal类动态绑定的属性weight,进行初始化设值。
        this.sex=true;
//调用父类构造方法(也和父类进行的动态绑定),父类的私有属性只能用父类的构造方法初始化,this.sex传过去的对象地址是子类对象Dog的地址
//先回在子类中寻找sex属性,找到了设置为true
	   //this.age=10; 
//父类的方法里看不到子类新增的属性和方法
//只能看的子类继承的或者继承和重写的属性和方法
		}	
	public int getWeight(){ //可被子类继承
		return this.weight;
	}	
	public void setWeight(int w){  //可被子类继承
		this.weight=w;
	    this.sex=false;
		//this.age=10;
		//父类看不到子类新增的属性,不能给子类属性进行初始化   
	}
}
 class Dog extends Animal{	  	 
	  int age; //子类新增属性,父类看不到
	public Dog(){  //子类构造方法与子类绑定
		System.out.println("Dog(): "+this);
		this.age=10; //调用子类的构造方法为子类对象的属性初始化
	    this.sex=false;//上转型
//虽然是父类属性,但是被子类继承,且传入的是子类对象的地址,优先在子类中寻找,这里可以为sex进行初始化false
	  //this.weight=20;  
//子类构造方法不能给父类私有属性初始化
//1、weight是父类的私有属性,子类没有继承
//2、在子类对象寻找weight,子类的构造方法和子类绑定,子类没有绑定weight
	}

构造方法执行结束后,对象也就创建结束了

	/**子类新增方法*/
	public void Bark(){   //方法空间
		//this.weight=20;
		this.sex=false;
		System.out.println("Wang~~Wang~~~");	
	}
}

//测试类

public class MyDog{ //加载到方法区的类代码区
	private static Animal myAnimal;  //静态绑定,加载Animal字节码文件
	//方法区的静态数据区创建Animal类的静态变量,默认初始化null
	public static void main(String args[]){ 
		myAnimal=new Dog(); //对象的上转型
//Dog对象父类Animal类的变量,父类不知道子类有新增的属性和方法
//有在方法区的静态数据区
	    myAnimal.setWeight(50);
///调用myAnimal所指对象的setWeight方法,现在子类中寻址没有,再到绑定的Animal类中绑定的setWeight方法
		System.out.println("My Dog's Weight is"+myAnimal.getWeight());
  	    //myAnimal.weight=100;
	    // myAnimal.Bark();
	    //Dog dog=new Dog();
	    //dog.Bark();
	}
}

总结:
创建子类对象时
1、先为父类中被子类继承的sex属性开辟空间,默认初始化false
2、再为子类新增的属性age开辟空间,4个字节,初始化为0
3、为父类定义的被子类继承的方法getWeight(),setWeight(int)开辟空间
4、为子类新增的方法Bark()开辟空间
此使就有了一个dog类型的this指针
 只要属性和方法在父类中定义,即使能被子类继承或者不被继承,都要和父类做动态绑定,方法getWeight(),setWeight(int),属性sex,weight都和父类做了动态绑定

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值