Java基础-基础,java基础
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 demo与class demo 的区别在于前者不仅变成公共的,而且必须保证类名跟文件名一样!!!
5.想要在其他目录下直接执行java demo
(1)采取临时环境变量的方法
Set classpath=D:\java0217\day01
执行的时候虚拟机先找class path下有没有demo。Class文件
只对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)用path,class文件用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 apublic 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,现在有点混!!!!搞清毕姥爷的关系,搞清了
}
}
相关文章
- 暂无相关文章
用户点评