欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

Java基础-基础,java基础

来源: javaer 分享于  点击 5809 次 点评:175

Java基础-基础,java基础



一.java简介与环境搭建

(1)Java简介

J2ee java 2 platform enterprise edition)企业版

主要针对web应用程序开发

J2se   (java 2 platform standard edition)标准版

是为开发普通桌面和上午应用程序提供的解决方案。

该技术体系是其他两者的基础,可以完成一些桌面应用程序的开发。

比如java版的扫雷。

J2me(java 2 platform micro edition)小型版

是为开发电子消费产品和嵌入式设备提供的解决方案。

该技术体系主要应用于小型电子消费类产品,如手机的应用程序等

Java 5.0版本后,更名为javaEE   javase  javame


(2)Java运行环境搭建

(1)设置相关路径方法


F:\ProgramFiles\Java\jdk1.8.0_05\bin;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\OpenCL SDK\3.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\3.0\bin\x64

在系统环境变量中顶格加入F:\ProgramFiles\Java\jdk1.8.0_05\bin;注意分号用来与后面的隔开。(放在前面先找)而且必须是可执行文件才能这么做。这么做是让系统帮我们去找。

 

可以换一种方式配,因为可能配置地方会变

Java_home=e:\jdk1.6.0_24

两个百分号是动态获取已存在变量的值

红色的表示动态获取jave_home

Path=%home%\bin;C:\ProgramFiles(x86)\NVIDIA Corporation\PhysX\Common;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\ProgramFiles (x86)\Intel\OpenCL SDK\3.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\3.0\bin\x64

在系统变量中,新建变量为java_home,变量值为e:\jdk1.6.0_24就行,如果bin之前的目录改了只要在这改就行




(2)dos命令相关操作

Dos 命令行

Dir:列出当前目录下的文件以及文件夹

Md:创建目录       md 文件名

Rd:删除目录        rd 文件名

Cd :进入指定目录  cd 文件名

Cd..:退回到上一级目录

Cd/:退回到根目录

del:删除文件

exit:退出dos命令行

del *.txt删除当前目录下的所有txt文件

echo haha>1.txt  在当前目录下创建1.txt内容为haha

dos命令删除文件夹里面必须是空的


盘号:   即可进入其他磁盘

2.但是在别人电脑上就需要临时配置

Dos命令只要输set   就可以查看所有环境变量


 

 

 

如果只要查看其中一个环境变量就可以用下面的方式

Set path(这是环境变量名path也是环境变量名

 

 

 

如果要修改

Set path=haha

不过只在当前窗口配置有效关掉无效

 

Set path=D:\jdk1.6.0_24\bin

这样就行了  但是只在当前目录有效!!!!

 

 

但是如果想在之前的path基础上加上新的值

Set path=haha;%path%

%%是动态获取

 

如果不是输CMD打开窗口通过输入start会延续效果,如果是再次通过cmd打开则效果全无


4.编译与执行

Public class democlass demo 的区别在于前者不仅变成公共的,而且必须保证类名跟文件名一样!!!

 

5.想要在其他目录下直接执行java demo

(1)采取临时环境变量的方法

Set classpath=D:\java0217\day01 

执行的时候虚拟机先找class path下有没有demoClass文件

只对class文件有效,因为用的是class文件

 

如果想要清空set classpath=      就行了

通过set classpath  即可查看到当前目录下什么都没有了

在设置了classpath临时环境变量以后

如果其他盘也有demo执行的是设置临时的路径

先找的是classpath 然后找当前目录!!!!

记住

Set classpath=D:\java0217\day01如果在这个目录找不到就不找了

Set classpath=D:\java0217\day01;(注意分号)这个在临时环境变量找不到就会在当前目录下继续找。

一般不建议加   分号

如果要先找一个盘再找一个盘可以这么做

Set classpath=c:\;d:\

这样就可以先找C盘再找D盘,还找不到就报错

Set classpath=.;c:\;d:\

.(这个点就代表当前路径),依次从当前路径,C盘,然后在D


如果是path的话就是反的,现在当前目录下找,然后再找path设置的

(可执行文件(exe)pathclass文件用chasspath

 

二:java语法基础:

 

1,关键字:其实就是某种语言赋予了特殊含义的单词。

保留字:其实就是还没有赋予特殊含义,但是准备日后要使用过的单词。 

2,标示符:其实就是在程序中自定义的名词。比如类名,变量名,函数名。包含 0-9、a-z、$、_ ;

注意:

1),数字不可以开头。

2),不可以使用关键字。

3,常量:是在程序中的不会变化的数据。

4,变量:其实就是内存中的一个存储空间,用于存储常量数据。

作用:方便于运算。因为有些数据不确定。所以确定该数据的名词和存储空间。

特点:变量空间可以重复使用。 

什么时候定义变量?只要是数据不确定的时候,就定义变量。

 

变量空间的开辟需要什么要素呢?

1,这个空间要存储什么数据?数据类型。

2,这个空间叫什么名字啊?变量名称。

3,这个空间的第一次的数据是什么? 变量的初始化值。

 

变量的作用域和生存期:

变量的作用域:

    作用域从变量定义的位置开始,到该变量所在的那对大括号结束;

生命周期:

    变量从定义的位置开始就在内存中活了;

    变量到达它所在的作用域的时候就在内存中消失了;

 

数据类型:

1):基本数据类型:byte、short、int、long、float、double、char、boolean 

2):引用数据类型: 数组、类、接口。

级别从低到高为:byte,char,short(这三个平级)-->int-->float-->long-->double

自动类型转换:从低级别到高级别,系统自动转的;
强制类型转换:什么情况下使用?把一个高级别的数赋给一个别该数的级别低的变量;

 

运算符号:

1)、算术运算符。

+ - * / %   %:任何整数模2不是0就是1,所以只要改变被模数就可以实现开关运算。

+:连接符。

++,--

2)、赋值运算符。

=  += -= *= /= %=

3)、比较运算符。

特点:该运算符的特点是:运算完的结果,要么是true,要么是false。 

4)、逻辑运算符。

&  |  ^  !   &&   ||

逻辑运算符除了 !  外都是用于连接两个boolean类型表达式。

&: 只有两边都为true结果是true。否则就是false。

|:只要两边都为false结果是false,否则就是true

^:异或:和或有点不一样。

 两边结果一样,就为false。

 两边结果不一样,就为true.

& 和 &&区别: & :无论左边结果是什么,右边都参与运算。

  &&:短路与,如果左边为false,那么右边不参数与运算。

| 和|| 区别:|:两边都运算。

||:短路或,如果左边为true,那么右边不参与运算。

5)、位运算符:用于操作二进制位的运算符。

&  |  ^ 

<<  >>   >>>(无符号右移)

练习:对两个变量的数据进行互换。不需要第三方变量。//用的是异或

int a  = 3,b = 5;-->b = 3,a = 5;

a = a + b; a = 8;

b = a - b; b = 3;

a = a - b; a = 5;

a = a ^ b;//

b = a ^ b;//b = a ^ b ^ b = a

a = a ^ b;//a = a ^ b ^ a = b;

练习:高效的算出 2*8 = 2<<3;

//自己加的

打印带双引号的helloworld  即“helloworld”

System.out.println(“"helloworld"”)

这样写是错的,因为第一个双引号代表开始,第二个就代表结束了,这是无效代码

正确的应该是在里面的双引号前反斜杠使他成为普通的双引号

 

System.out.println(“\"helloworld\"”)

赋值运算符

Short s=3;

s=s+2 

s+=2;

s=s+2因为s会被提升为int型,运算后的结果还是int类型。

无法赋值给short 类型

 

S+=2编译通过,因为+=运算符在给s赋值时,自动完成了强转操作

 

 

 

左移即乘以2的移动位数次幂

右移就是除以2的移动的位数次幂

3<<2=12   3*4=12

3<<1=6    3*2=6

3<<3=24   3*8=24

-----------------------------------------------------------------

5,语句。

If  switch  do while   while  for 

这些语句什么时候用?

1)、当判断固定个数的值的时候,可以使用if,也可以使用switch。

但是建议使用switch,效率相对较高。

switch(变量){

 case 值:要执行的语句;break;

 …

 default:要执行的语句;

}

 工作原理:用小括号中的变量的值依次和case后面的值进行对比,和哪个case后面的值相同了

           就执行哪个case后面的语句,如果没有相同的则执行default后面的语句;

 细节:1):break是可以省略的,如果省略了就一直执行到遇到break为止;

   2):switch 后面的小括号中的变量应该是byte,char,short,int四种类型中的一种;

   3):default可以写在switch结构中的任意位置;如果将default语句放在了第一行,则不管expression与case中的value是否匹配,程序会从default开始执行直到第一个break出现。

2)、当判断数据范围,获取判断运算结果boolean类型时,需要使用if。

3)、当某些语句需要执行很多次时,就用循环结构。

while和for可以进行互换。

区别在于:如果需要定义变量控制循环次数。建议使用for。因为for循环完毕,变量在内存中释放。

 

break:作用于switch ,和循环语句,用于跳出,或者称为结束。

break语句单独存在时,下面不要定义其他语句,因为执行不到,编译会失败。当循环嵌套时,break只跳出当前所在循环。要跳出嵌套中的外部循环,只要给循环起名字即可,这个名字称之为标号。

 

continue:只作用于循环结构,继续循环用的。

作用:结束本次循环,继续下次循环。该语句单独存在时,下面不可以定义语句,执行不到。

 

6,函 数:为了提高代码的复用性,可以将其定义成一个单独的功能,该功能的体现就是java中的函数。函数就是体现之一。

java中的函数的定义格式:

修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数1,…){

执行语句;

return 返回值;

}

当函数没有具体的返回值时,返回的返回值类型用void关键字表示。

如果函数的返回值类型是void时,return语句可以省略不写的,系统会帮你自动加上。

return的作用:结束函数。结束功能。

 

如何定义一个函数?

函数其实就是一个功能,定义函数就是实现功能,通过两个明确来完成:

1)、明确该功能的运算完的结果,其实是在明确这个函数的返回值类型。

2)、在实现该功能的过程中是否有未知内容参与了运算,其实就是在明确这个函数的参数列表(参数类型&参数个数)。

函数的作用:

1)、用于定义功能。

2)、用于封装代码提高代码的复用性。

注意:函数中只能调用函数,不能定义函数。

主函数:

1)、保证该类的独立运行。

2)、因为它是程序的入口。

3)、因为它在被jvm调用。

 

函数定义名称是为什么呢?

答:1)、为了对该功能进行标示,方便于调用。

2)、为了通过名称就可以明确函数的功能,为了增加代码的阅读性。

 

重载的定义是:在一个类中,如果出现了两个或者两个以上的同名函数,只要它们的参数的个数,或者参数的类型不同,即可称之为该函数重载了。(与函数返回值无关

如何区分重载:当函数同名时,只看参数列表。和返回值类型没关系

例:

Int add(int x,int y){return x+y;}

Int add(int x,int y,int z){return x+y+z;}

Double add(double x,double y){return x+y;}

 

7,数 组:用于存储同一类型数据的一个容器。好处:可以对该容器中的数据进行编号,从0开始。数组用于封装数据,就是一个具体的实体。

(1)数组的特点

1. 长度是固定的,一旦创建长度就不能改变
2. 元素类型必须是相同类型,不能出现混合类型
3. 数组中的元素类型可以使任意类型,可以是基本数据类型也可以是引用数据类型
4. 数组变量属于引用类型,数组也可以看做对象,数组中的元素相当于该对象的的成员变量,数组本身就是对象

(2)数组的创建方法

数组其实就是对象存在堆内存中(堆内存都是new出来的)
如何在java中表现一个数组呢?两种表现形式。
2)、 静态  元素类型[] 变量名 = {元素1,元素2...};
元素类型[] 变量名 = new 元素类型[]{元素1,元素2...};

1)、动态  元素类型[] 变量名 = new 元素类型[元素的个数];

---------------------------------------------------------


8.排序

这里可以把冒泡排序,选择排序,希尔排序加上。

 

(1)二分查找法。必须有前提:数组中的元素要有序。

(1)原理

二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

 

(2)实例

public static int halfSeach_2(int[] arr,int key){

int min,max,mid;

min = 0;

max = arr.length-1;

mid = (max+min)>>1; //(max+min)/2;

while(arr[mid]!=key){

if(key>arr[mid]){

min = mid + 1;

}

else if(key<arr[mid])

max = mid - 1;

if(max<min)

return -1;

mid = (max+min)>>1;

}

return mid;

}

(2)冒泡排序

(1)原理

相邻元素比较

冒泡排序算法的运作如下:(从后往前)

1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。

2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

3.针对所有的元素重复以上的步骤,除了最后一个。

4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较


(2)实例

(3)总结

冒泡排序在栈内存中换位置比较耗资源,(适于数组元素比较少),堆内存中换位置比较消耗资源,

可以在栈内存中定义两个变量最后再来换(可以看看怎么写!!!)

看看希尔排序,因为他是最快的!!!


注意:

Length的使用

(1).概念

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

(2)实例

这个例子来演示这两个方法和一个属性的用法

public static void main(String[] args) {

String []list=    {"ma","cao","yuan"};

String a="macaoyuan";

System.out.println(list.length);

System.out.println(a.length());

Listarray=new ArrayList();

array.add(a);

System.out.println(array.size());

}

 

打印

3

9

1

---------------------------------------------------

 

 

public static void bubblesort(int [] arr)

{

for(int x=0; x<arr.length-1;x++)

{

// 每一次都把最值放到最后面,所以比较一伦就少比较一个元素,再减一避免角标越界

for(int y=0;y<arr.length-x-1;y++)

{

if(arr[y]<arr[y+1])

{

int temp=arr[y];

arr[y]=arr[y+1];

arr[y+1]=temp;

 

}

 

}

}

 

(3)选择排序

1.原理

//它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部//待排序的数据元素排完。 选择排序是不稳定的排序方法(比如序列[5, 5, 3]第一次就将第一个[5]与[3]交换,//导致第一个5挪动到第二个5后面)

 

/*

选择排序

内循环结束一次,最值出现头角标位置上

 2.实例

public static void selectsort(int [] arr)

{

for(int x=0; x<arr.length-1;x++)

{

for(int y=x+1;y<arr.length;y++)

{

if(arr[x]<arr[y])

{

int temp=arr[x];

arr[x]=arr[y];

arr[y]=temp;

 

}

 

}

 

}

9.内存

java分了5片内存。

1:寄存器。2:本地方法区。3:方法区。4:栈。5:堆。

栈:存储的都是局部变量 ( 函数中定义的变量,函数上的参数,语句中的变量 );

只要数据运算完成所在的区域结束,该数据就会被释放。

用于存储数组和对象,也就是实体。啥是实体啊?就是用于封装多个数据的。

1:每一个实体都有内存首地址值。

2:堆内存中的变量都有默认初始化值。因为数据类型不同,值也不一样。 

3:垃圾回收机制。

也是就是局部变量不会初始化????


三.设计模式

设计模式:解决某一类问题最行之有效的方法
Java中23种设计模式
单例设计模式:解决一个类在内存只存在一个对象


为什么要用单例模式?

1.为了避免其他程序过多建立该类对象。先禁止其他程序建立该类对象。
2.还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象
3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式


怎么实现单例模式?

1.将构造函数私有化
2.在该类中创建一个本类对象
3.提供一个方法可以获取到该对象
class Single
{
	private Single(){}
	private static Single s =new Single();
	public static Single getInstance()   //为了让类直接调用static  
	{
		return s;
	}
}


class singledemo
{
	public static void main(string[] args)
	{
			Single ss = single.getinstance();
			Single s1 = single getinstance(); //和ss指向同一个区域,因为不能自己创建(因为private single()),只能调用之前给的
}


}




(1)Single有没有private的对比

如果把  private Single()中的private却掉
Single s1 = new Single();
Single s2 = new Single();
S1.setnum(30);
System.out.println(s2.getnum());
打印会得到  零  ,因为在堆中创建了两个不同的对象!!!!!


如果继续private Single()
Single s1= Single.getinstance();
Single s2 = Single.getinstance();
S1.setnum(30);
System.out.println(s2.getnum());
打印会得到 30 ,因为没创建新的对象,两个指的都是一个对象!!!!


/*
饿汉式
这个是先初始化对象single类一进内存,就已经创建好了对象
*/
class single
{
private single(){}
private static single s = new single();
public static single getInstance()
{
return s;



}




/*

懒汉式。

Singel类进内存,对象还没有存在,只有在调用getinstance方法时,才建立对象


*/
class single 
{
private static single s = null;
private single(){}
public static single getinstance()
{
if(s ==null)    //1
S= new single();   //2


}


}

问题:

对于懒汉式,如果多线程停留在1到2之间,加入A停在那之间执行别的去了,B也停在那个地方,等会A来了执行了2,然后B来了也会在执行一次2,这样就创建了两个对象,出错了(因为只要创建一个对象)

1.解决方法1!!!

class single 
{
	private static single s = null;
private single(){}
public static synchronized single getinstance()
	{
	if(s ==null)    //1
	S= new single();   //2


}


}
加了synchronized  当A进入时别的就进不了,只有A执行完出去了,其他的任务才能进,但是这样就大大降低了程序的效率

2.解决方法2

class single 
{
	private static single s = null;
	private single(){}
	public static single getinstance()
	{
			if(s ==null)    //1
		{
				synchronized(single.class)  //3
			{
				if(s == null) //4
				S= new single();   //2
			}
		}


	}


}

四.多态


多态:可以理解为事物存在的多种体现形态。
人: 男人  女人
动物:猫,狗
猫 x = new 猫();
动物 x = new 猫();


1.多态的体现

父类的引用(animal a)指向了自己的子类对象( new cat或者 new dog)
换种说法父类的引用也可以接受子类对象


2.多态的前提

必须是类与类之间有关系。要么继承,要么实现通常还有一个前提:存在覆盖。(比如说抓老鼠,只有猫 才有)

3.多态的好处

多态的出现大大的提高程序扩展性(function)

4.多态的弊端

(animal a = new dog )
提高了扩展性,但是只能使用父类的引用访问父类中的成员(此处就是eat())!!!!!

5.多态的应用

6.多态使用的注意事项

//代码1

abstract class animal
{


	abstract void eat();


}




class Cat extends Animal
{
	public void eat()
	{


		System.out.println("吃鱼");


	}




 	public void catchMouse()
	{
 		System.out.println("抓老鼠");


	}


}


class dog extends animal
{
		public void eat()
		{


			System.out.println("吃骨头");


		}


		public void catchMouse()
		{


			System.out.println("看门");


		}
	


}


class Pig extends animal
{
		public void eat()
		{


			System.out.println("饲料");


		}


		public void catchMouse()
		{


			System.out.println("拱地");


		}
	


}


class DuoTaiDemo
{


	public static void main(String[] args)


	{


		//Cat c =new Cat();   //没有体现多态性
 		animal c =new cat();  //跟上面的结果一样,但是这样才能体现多态性
		c.eat();
		function(c);//提高代码复用性,不用XX.eat
		function(new dog);
		function(new pig);


		animal a =new cat();  //类型提升。向上转型					a.eat();
		//如果想要调用猫的得特有方法应该怎么操作。
		//强制将父类的引用,转成子类类型,向下转型
		//我们能转换的是父类的引用指向了自己的子类对象时,该////应用可以被提升,也可以被强制转换
		/*
			强制将父类的引用。转成子类类型,向下转型。(转的是引用)
			Animal a = new Cat();
			Cat c = (Cat)a;
			c.catchMouse();


			//错误
			//千万不能出现下面这样的操作,就是将父类对象转成子类类型
			//我们能转换的是父类引用指向了自己的子类对象时,该应用可以可以被提升,也可以被强制转换
			//多态自始至终都是子类对象在做着变化
			Animal a = new Animal();
			Cat c = (Cat)a;
			c.catchMouse();//错误
		
		*/
		//多态自始至终都是子类对象在做着变化
		Cat  c=(cat)a; //如果不转换类型,直接调用a.catchMouse会报错
		C.catchmouse();


	}
/*这样写就分的太细,可以简化成代码2,参数可以直接写animal c
	public static void function(Cat c)//父类的引用也可以接受子类对象
										//可以直接写 animal c
	{


		c.eat();


	}
	public static void function(dog d)
	{


		d.eat();


	}


	public static void function(pig p)
	{


		p.eat();


	}


// 代码2!!!  

 都是动物   所以参数直接写Animal a

public static void function(animal a)
	{
	
		a.eat();
			
		if(a  instanceof  cat)  //instanceof 用来判断所属判断类型!!!
		{
			Cat c = (cat)a;
			C.catchmouse();
		}
		else
			if(a instanceof Dog)
		{
			Dog c = (Dog)a;
			c.kanjia();
		
		
		}
	
	}
}



毕老师毕姥爷的比喻

毕姥爷    讲工商管理    看书
毕老师的事  讲java       看电影
//找人讲课的时候(编译)找的是毕姥爷,讲课的时候(运行)是毕老师讲课
//毕老师的朋友,来找毕老师看电影,一进门看见伪装成毕姥爷的毕老师(当然认不出),肯定不会找他看电影(报错)
毕姥爷  x = new 毕老师  //毕老师化妆成他的父亲
x.讲课()//讲java
x.看电影();(失败)
毕老师 y = (毕老师)x//毕老师一看是自己的朋友,就卸下伪装,变回毕老师,看电影就行了
y.看电影();(OK)
//从头到尾都是毕老师在变化(子类对象),不能把毕姥爷变成毕老师
*/
class FU
{
Int num =5;
void method1()
{
System.out.println(“fu method_1”);
}
void method2()
{
System.out.println(“fu method_2”);
}




}
class zi extends FU
{
Int num = 8;
void method1()
{
System.out.println(“zi method_1”);
}
void method3()
	{
System.out.println(“zi method_3”);
}




}


class  duotaidemo4
{
Public static void main(void [] args)
{
FU f = new zi();
System.out.println(f.num);
Zi z=new zi();
System.out.println(z.num);


/*
FU f=new zi();
f.method1();
F.method2();  //这里子类没写method2,但是子类继承了父类的方法,子类没有就找父类
//F.method3();  现在伪装成毕姥爷不能用毕老师的方法,除非卸下伪装




在多态中成员函数的特点:

在编译时期:参阅引用型变量(左边)所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败(比如F.method3();)。
在运行时期:参阅对象所属的类(右边)中是否有调用的方法


简单总结就是:成员函数的多态调用时,编译看左边,运行看右边
*/


}


}


结果是
5
8

成员函数的多态调用时,编译看左边,运行看右边

多态中,成员变量的特点:

无论编译和运行,都参考左边(应用型变量所属的类)


在多态中,静态函数的特点

无论编译和运行都参考左边

静态绑定

//静态方法一进内存就绑定在所属类上  (静态绑定)

动态绑定

//非静态方法  里面是this.方法  super.方法,哪个对象调用就是哪个,f指向子类对象
//(动态绑定)

五.内部类

内部类定义:

将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)。
访问特点:
内部类可以直接访问外部类中的成员,包括私有成员。
而外部类要访问内部类中的成员必须要建立内部类的对象。
类可以私有但是只在外部类中作为成员时

内部类的访问规则:

1.内部类可以直接访问外部类中的成员,包括私有。如果在外面就必须创建outer类对象,才能访问其内部的成员及函数(私有成员只在内部可以访问,或者用一个公有函数做接口)。
之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式  外部类名.this


2.外部类要访问内部,必须建立内部类对象。


内部类访问格式:

1.当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中,可以直接建立内部类对象。
格式 
外部类名.内部类名 变量名 = 外部类对象。内部类对象;
outer.Inner in = new outer.new inner();
2.当内部类在成员位置上,就可以被成员修饰符所修饰。
3.比如,private:将内部类在外部类进行封装。
static:内部类就具备static的特性。
当内部类被static修饰后,只能直接访问外部类中的stacic成员。出现了访问局限

在外部其他类中,如何直接访问static内部类的非静态成员呢?

class outer
{
	private static int x=3;
	static class inner//静态内部类
	{
		static void function()
		{
			System.out.println(“inner:”+x);
		}
	}


}
new outer.inner().function//因为function是非静态的,所以要用对象来调用

在外部其他类中,如何直接访问static内部类的静态成员呢?

Outer.inner.function();//因为x是静态的,所以不用对象就可以调用


注意:当内部类定义了静态成员,该内部类必须是static.
class outer
{
private static int x=3;
class inner//静态内部类
{
static void function()
{
System.out.println(“inner:”+x);
}
}


}
这种会报错   需要改为static class inner
注意:

当外部类中的静态方法访问内部类时,内部类也必须是static的

class inner2//需要修改为static class inner2
{
	void show()
	{
	System.out.println(“inner2 show”);
	}
}


public static void method()
{
	n

ew inner2().show();
}
这种的会报错,改为 static class inner2就行了,因为public static void method()
一开始加载,但是inner类不是静态的,需要对象,所以不行(那如果外部类是静态的呢,然后调用?????)

内部类定义在局部时,可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问他所在的局部中的变量,只能访问被final修饰的局部变量。

class outer
{
	int  x=3;
	void method()
	{
		class inner   //这里写在局部不是成员位置,这里就不能被静态修饰因为他不是成员
		{	int  y = 4;
			void function()//也不能定义为静态,因为内部类中如果有静态成员,那么该类也是静态
			{
			System.out.println(y);

			}
			New inner().function();

		}
	}
}
这样会报错,需要把 int y = 4;改为final int y = 4

匿名内部类:

1.匿名内部类其实就是内部类的简写格式。
2.定义匿名内部类的前提:
内部类必须继承一个类或者实现接口
3.匿名内部类的格式:new 父亲或者接口(){定义子类的内容}
4.其实匿名内部类就是一个匿名子类对象,而且这个对象有点胖。可以理解为带内容的对象

1.正常写法


abstract class absdemo
{
	abstract void show();
}


class  outer
{
	int x =3;
	class inner externds absdemo
	{
		void show()
		{
			System.out.println(“show:”+x);
		}

	}

	public void function()
	{
		new inner().show();
	}

}


	class innerclassdemo4
	{
	public static void main(string[] args)
	{
		new outer().function();
	}

}

2.匿名写法

class  outer
{
	int x =3;

	public void function()
	{
			new absdemo()     //表示absdemo的子类//因为absdemo是抽象类不能用new除非把它实现了(这里用大括号实现了!!!!)
		{
				void show()
			{
				System.out.println(“x=”+x);
			}
		}.show();//调用show                  //表示absdemo的子类

	}

}


class innerclassdemo4
{
	public static void main(string[] args)
	{
		new outer().function();
	}

}



new absdemo()     //可以写成 absdemo d = new absdemo() 其实这就等于absdemo d = new inner();
{
	void show()
	{
		System.out.println(“x=”+x);
	}
}.show()//调用show  
</pre><pre name="code" class="java">可以写成d.show();

练习


注意:匿名内部类中定义的方法最好不要超过3个

interface inter
{
void method();
}
class test
{
//第一种
	Static class inner implements inter
	{
		public void method()
		{
			System.out.println(“method run”);
		}

	}

	Static inter function()
	{
		return new inner()

	}


//第二种
	Static inter function()
	{
			return new inter()
		{
			public void inter()
			{
				System.out.println(“method run”);
			}
		};

	}


}

class innerclasstest
{
	public static void main(string[] args)
	{
		Test.function().method();
	}

}


什么时候使用


当描述事物时,事物内部还有事物,该事物用内部类来描述。
因为内部事务在使用外部事物的内容。
身体——心脏(还有其他器官)

class outer
{
	private int x=3;
	class inner
	{
		Int x=4;//xc_2
		void function()
		{
		Int x=6;//xc_1
		System.out.println(“inner”+x);  //如果	xc_1和xc_2都有就6,都没有就是3,省略outer.this(如果把xc_1和xc_2逐个去掉会怎么样???!!!)
		System.out.println(“inner”+this.x);  //如果	xc_1和xc_2都有4
		System.out.println(“inner”+outer.this.x);//如果	xc_1和xc_2都有3


		}
	}


void method()
{
	//要标注内部类的所属//但是很少很少用
	outer.Inner in = new outer.new inner();
	In.function();
}






}


class innerclassdemo
{
	public static void main(String[] args)
	{
		Outer out = new outer();
		Out.method();
	}


}
分析Test.function().这个运行的结果肯定是一个对象
还有因为是test.所以成员肯定是静态的(因为是类test调用的)
只能是接口inter的子类才能调用method  所以static inter


Test.function().method();
可以拆分为
inter in = test.function();
In.method();
Show(new inter()
{
	public void method()
	{
		System.out.println(“method show run”);
	}
);


public static void show(inter in)
{
	In.method();
}


小面试题
class innertest
{
	public static void main(string[] args)
	{
		new object()
		{
			public void function()
			{

			}

		}.function();
	}
}
如果改为
class innertest
{
	public static void main(string[] args)
	{
		Object o=new object()
		{
			public void function()
			{

			}

		}.function();

		O.function();//会报错,因为父类中没有function,现在有点混!!!!搞清毕姥爷的关系,搞清了
	}
}




相关文章

    暂无相关文章
相关栏目:

用户点评