Java基础---基础加强---增强for循环、自动拆装箱及享元、枚举的作用、实现带有构造方法、透彻分析反射的基础_Class类、成员变量的反射、数组参数的成员方法进行反射、数组的反射应用
在perference 加content Assist 可以设置快捷键
透视图与视图
透视图:Debug和java主窗口
视图:每一个小窗口就是视图
高版本的java可运行低版本的java版本
常见的错误:classversionError
一般都是文件编译与系统默认的编译器版本不同导致的。
在配置文件里把java compiler变了,整个工作间都会跟着改变
如何自己配置模板:
在preferences中有一个Editor。下面有一个Template,里面可以设置
提示:
如果在导入工程的时候,发现在jdk版本不一样,我们可以在Build Path下找到java Build path 有一个Libraries删除原来的jRE库,重新导入新的jRE,很多的jar文件在一起就称之为库,jre相当于打包的过程
静态方法的导入java.lang.*;
jdk1.5的新特性
1.可变参数
一个方法接受的参数的个数不固定,例如:System.out.println(add(1,2,5);
System.out.println(add(1,2,3,5);
可变参数的特点:
只能出现在参数列表的最后。
位于变量类型和变量名之间。前后有无空格都可以。
调用可变参数的方法时,编译器为该可变参数隐含创建一个数组。在方法中以数组的形式访识破可变参数
overload override:
深入理解。
public class StaticImport {
public static void main(String []args){
//int x=1;
//x++;
System.out.println(add(2,3));
System.out.println(add(2,3,4));
//System.out.println(Math.max(3,6));
}
public static int add(int x,int ...args){
int sum=x;
for(int i=0;i<args.length;i++){
sum+=args[i];
}
return sum;
}
}
增强for循环
语法(类型 变量名:集合变量名)
注意事项:
跌代变量必须在()中定义。
集合变量可以是数组或实现了Iterable接口的集合类。
2.基本数据类型的自动拆箱与装箱及享元设计模式。
自动装箱
Integer num1=12;
自动拆箱
System.out.println(num1+12);
i{char,x,y},为了共用。里面的参数
享元设计模式:
如果很多很小的东西,它们具有相同的属性,我们就可以把它变成一个相同的对象。这些称之为内部状态。那些不同的属性作为方法的参数传入,称之为外部状态
3.枚举
枚举就是要让某个类型的变量取值只能为若干个固定值中的一个,否则,编译器就会报错,枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标。
用普通类如何实现枚举功能,定义一个Weekday的类来模拟枚举功能 。
私有的构造方法。
每个元素分别用一个公有的静态成员表量表示
可以用若干个公有方法或抽象方法,例如,要提供nextday方法必须是抽像的
public abstract class WeekDay1 {
private WeekDay1(){
}
public final static WeekDay1 Sun=new WeekDay1(){
@Override
public WeekDay1 nextDay() {
// TODO Auto-generated method stub
return Mon;
}
};
public final static WeekDay1 Mon=new WeekDay1(){
@Override
public WeekDay1 nextDay() {
// TODO Auto-generated method stub
return Sun;
}
};
public abstract WeekDay1 nextDay();
// public WeekDay nextDay(){
// if(this==Sun){
// return Mon;
// }else{
// return Sun;
// }
// }
public String toString(){
return this==Sun?"Sun":"Mon";
}
}
为了更多的理解枚举,采用抽象方法定义next.day就将大量的if.else语句转移成了一个个独立的类。
如果想在一个类中完成各个枚举和测试调用类,那么就可以将枚举类定义成调用类的内部类。
内部类可以有4个访问修饰符。
一般的成员方法就是2个。public private,内部类与成员方法是平级的
package day01;
import java.sql.Date;
public class EnumTest {
public static void main(String[] args) {
WeekDay1 weekDay=WeekDay1.Mon;//赋值给引用变量
System.out.println(weekDay.nextDay());
WeekDay weekDay2=WeekDay.Fri;
System.out.println(weekDay2);
System.out.println(weekDay2.name());
System.out.println(weekDay2.ordinal());
//把静态的串变成枚举方法
System.out.println(weekDay2.valueOf("Sun"));
new Date(300){
//调用父类的构造方法,调用有参的构造
};
}
public enum WeekDay{
Sun,Mon,Tue,Fri;//相当于里面的类。如果我们写成Sun(1),可会调用第二个方法
//定义带有参数的构造方法
private WeekDay(){
System.out.println("first");
}
private WeekDay(int day ){
System.out.println("second");
}
}
//带有抽象方法的枚举类
public enum TrafficLamp{
Red(30){//red是一个元素,它是由trafficLamp子类来实现的
public TrafficLamp nextLamp(){
return Green;
}
},
Green(45){
public TrafficLamp nextLamp(){
return Yellow;
}
},
Yellow(5){
public TrafficLamp nextLamp(){
return Green;
}
};
public abstract TrafficLamp nextLamp();
private int time;
private TrafficLamp(int time){
this.time=time;
}
}
}
抽象类的返回值还是自己
枚举就相当于一个类,其中也可以定义构造方法,成员变量,普通方法和抽象方法。
枚举元素必须位于枚举体中的最开始部分,枚举元素列表的后面要有分号与其他成员分隔,把枚举中的成员或变是等放在枚举元素的前面,编译器报告错误
带枚造方法的枚举
1.构造方法必须定义成私有的
2.如果有多个构造方法,该如何选择哪个构造方法?
3.枚举元素MON和MON()的效果一样,都是调用默认的构造方法。
带方法的枚举
1.定义枚举TrafficLamp
2.实现普通next的方法
3.实现抽象的next方法,每个元素分别是由枚举的子类来生成的实例对象,这些子类采用类似的内部类的方式进行定义
4.增加上不表示时间的构造方法
枚举只有一个成员时,就可以作为一种单例的实现方式。
反射
Person p1=new Person();
Class代表内存里央的字节码,不能实例化对象。
p1.getClass()也是代表person那个字节码
Class cls1=Data.class//字节码1;Data.class代表Data的那个字节码
Class cls2=Person class//字节码2;
Person class代表Person的那个字节码
每一份字节码就是一份Class的实例对象
还有一种是Class.forName("java.lang.String"),在写源程序的时候,可以把括号里面的变成变量,字符串变量,程序启动,从配置文件里装载进来。类的名字,在写的时候可以不知道,在运行的时候,临时送进来
这个forName的作用是:
1.返回刚刚加载进来的字节码
返回的方式有两种,第一种是说这份字节码曾经被加载过,已经在JVM里面了,直接返回。第二种是JVM还没有这个字节码,则用类加载器去加载,把加载进来的字节码缓存在JVM中,以后要得到这份字节码,就不用加载了
有9个预定义的class对象,8个基本类型加一个void
记得加了void,如Class cls1=void.class;
反射比较占用时间,它是先把构造方法存起来,如果有人要用了,再把它拿出来。这过程中就消耗了时间。
如何你在一个配置文件里,配置了好多东西,我们可以通过反射来修改。这个功能相当有用
面向对象就是把变量搞成私有的,如果谁要调用这个对象,那么方法就应该在谁身上
package day01;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
public class ReflectTest {
public static void main(String[] args)throws Exception {
String str1="abc";
Class cls1=str1.getClass();
Class cls2=String.class;
Class cls3=Class.forName("java.lang.String");
System.out.println(cls1==cls2);
System.out.println(cls2==cls3);
//JVM中只存在一份字节码。供不同的对象调用
//String不是基本类型的字节码,它是一个类
System.out.println(cls1.isPrimitive());//isprim表示一个原始类型
System.out.println(int.class.isPrimitive());
System.out.println(int.class==Integer.class);
System.out.println(int.class==Integer.TYPE);//表示包装类型的那个基本类型的字节码,所以为True
System.out.println(int[].class.isPrimitive());//返回false,因为数组也是一个实例对象,用的方法是Class.isArray();
//new String(new StringBuffer("abc"));
Constructor constructor1=String.class.getConstructor(StringBuffer.class);//第一个StringBuffered表示选择哪个构造方法
String str2=(String)constructor1.newInstance(new StringBuffer("abc"));//每调用一次相当于New了一次对象。第二个StringBuffered表示用这个StringBuffered传哪个对象进去。
//在编译的时候,只知道constructor1是构造方法,而不知道是哪个类下的构造方法,编译器只看变量的类型,而不看执行
System.out.println(str2.charAt(2));
//得到方法的时候需要类型,在调用方法的时候,还是要类型
ReflectPoint pt1=new ReflectPoint(3, 5);
Field fieldY=pt1.getClass().getDeclaredField("y");
//FieldY的值是多少?5,错,没有对应到对象身上,Field
//不代表一个具体的值,只代表一个变量,而且是字节码里面的一个变量
//它是指向哪个类身上的值
fieldY.setAccessible(true);//这里用到的是暴力反射。
System.out.println(fieldY.get(pt1));
changeStringValue(pt1);
System.out.println(pt1);
//直接调用,str1.charAt(1);
Method methodCharAt=String.class.getMethod("charAt", int.class);
//得到字节码里面的方法,再用方法去作用某个对象
System.out.println(methodCharAt.invoke(str1, 2));//args表示传几个参数。str1这个字符串身上调用charAt
//invoke是方法对象身上的方法
System.out.println(methodCharAt.invoke(str1, new Object[]{2}));//2表示一个object
//这是jdk1.4里面的方法
String startingClassName=args[0];
Method mainMethod=Class.forName(startingClassName).getMethod("main", String[].class);
//mainMethod.invoke(null,new Object[]{new String[]{"111","222","333"}});//把三个参数包到一起传送进去
mainMethod.invoke(null,(Object)new String[]{"111","222","333"});
//每个数组的父类都是object
int [] a1=new int[3];
int [] a2=new int[4];
int [][] a3=new int [2][3];
String [] a4=new String []{"a","b","c"};
System.out.println(a1.getClass()==a2.getClass());
//System.out.println(a1.getClass()==a4.getClass());
//System.out.println(a1.getClass()==a3.getClass());
Object aObj1=a1;
Object aObj2=a4;
//Object[] aObj3=a1;//int不是object,基本类型不是Object,基本类型的一维数组不能转成object数组
Object[] aObj4=a3;//二维是object
Object[] aObj5=a4;//String是object
System.out.println(Arrays.asList(a1));
System.out.println(Arrays.asList(a4));//只接受String类型,因为它是object数组
printObject(a4);
printObject("xyz");
}
private static void printObject(Object obj){
Class clazz=obj.getClass();
if(clazz.isArray()){
int len=Array.getLength(obj);
for(int i=0;i<len;i++){
System.out.println(Array.get(obj, i));
}
}else{
System.out.println(obj);
}
}
private static void changeStringValue(Object obj) throws Exception{
Field [] fields=obj.getClass().getFields();//得到所有的字段
for(Field field:fields){
//if(field.getType().equals(String.class)){
//对字节码的比较应该拿==相比
if(field.getType()==(String.class)){//这里应该用==,因为是同一份字节码
String oldValue=(String) field.get(obj);
String newValue=oldValue.replace('b', 'a');
field.set(obj, newValue);
}
//这个field代表字段
}
}
}
class TestArguments {
public static void main(String[] args) {
for(String arg:args){
System.out.println(arg);
}
}
}
ReflectPoint.java
package day01;
public class ReflectPoint {
private int x;
public String str1="ball";
public String str2="basketball";
public String str3="haha";
public int y;
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ReflectPoint other = (ReflectPoint) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
@Override
public String toString(){
return str1+":"+str2+":"+str3;
}
}
例子:
通过反射来调来main方法
数组的反射
int [] a=new int[3];
object[] a=new object[]("a",1)
a[0].getClass().getName();//只能得到它的元素的类型,不能得到a是什么类型
反射的综合应用。
ArrayList 是有顺序的数据。每放一次就引用一个变量。不是排序,而是位置顺序。
HashSet
先判断里面有没有这个对象,如果发现有的话,就不放。如果实在要放,就把原来的数据给删除掉。然后插入进去。
HashCode方法与HashSet类
如果想查找一个集合是否包含某个对象,大概的程序怎样写呢?你通常是逐一取出每个元素与要查找的对象的进行比较,当发现某个元素与要查找的对象进行equals方法比较的结果相等时,则停止继续查找并返回肯定的信息,否则,则返回否定的信息。如果一个集合中有很多元素,譬如有10000个元素,并且没有包含要查找的对象时,则意味着你的程序需要从该 集合中取出一个元素进行逐一比较才能得到结论。有人发明了哈希算法来提高从集合中查找元素的效率,这种方式将集合分成若干个区存储。每个对象可以计算出一个哈希码。可以将哈希码分组。每组分别对应某个存诸区域,根据一个对象的哈希码就可以确定该对象应该存储在哪个区域
hashcode的作用:
对象要有作用,必须在hash算法类的集合中,hashcode的值才有价值。两个相同的对象被存到了不同的Hashset内存里,当要再找这个对象时,只能在本区域里进行查找。如果对象不存到hashset集合里,那么也没有必要用到hashcode方法。
提示:
通常来说,一个类的两个实例对象用equals()方法比较的结果相等时,它们的哈希码也必须相等,但反之则不成立,即equals方法比较结果不相等的对象可以有相同的哈希码。
或者说哈希码相同的两个对象的equals方法比较的结果可以不等,例如,字符串“BB” 和“Aa"的equals方法比较结果肯定不相等,但它们的hashcode方法返回值相等。
2.当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段,否则,对象修改后哈希值最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在Container方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从Hashset集合中单独删除当前对象,从而造成内存泄露。
package day01;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Properties;
public class ReflectTest2 {
public static void main(String[] args) throws Exception{
InputStream ips=new FileInputStream("config.properties");//这里用到的是相对路径
//现在的内容是ArrayList.所以结果是4,
//如果把properties中的内容改为Hashcode,结果就变为2
//这里就用到了反射技术开发框架的原理
Properties props=new Properties();
props.load(ips);
ips.close();//告诉操作系统把这个流关闭
String className=props.getProperty("className");
Collection collections=(Collection) Class.forName(className).newInstance();
//调用不带参数的构造方法
//Collection collections=new HashSet();
ReflectPoint pt1=new ReflectPoint (3,3);
ReflectPoint pt2=new ReflectPoint (5,5);
ReflectPoint pt3=new ReflectPoint (3,3);
collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
//pt1.y=7;//这个集合与hashcode没有关系
//collections.remove(pt1);
System.out.println(collections.size());
}
}
反射的作用--->实现框架功能
newStance(),调用不参数的构造方法
Java基础---基础加强---增强for循环、自动拆装箱及享元、枚举的作用、实现带有构造方法、透彻分析反射的基础_Class类、成员变量的反射、数组参数的成员方法进行反射、数组的反射应用的更多相关文章
- 黑马程序员_Java基本数据的自动拆装箱及享元设计模式视频学习笔记
------- android培训.java培训.期待与您交流! ---------- 装箱:把基本数据类型装成java类(被托管?). 拆箱:把java类拆成基本数据类型(取消托管? ...
- 可见参数和增强for以及自动拆装箱
可变参数:定义方法的时候不知道该定义多少个参数格式: 修饰符 返回值类型 方法名(数据类型… 变量名){ } 注意: 这里的变量其实是一个数组如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定 ...
- java高新技术-基本数据类型拆装箱及享元设计模式
享元设计模式 public static void main(String[] args) { Integer iObj = 3; //自动装箱 System.out.println(iObj + 1 ...
- JAVA进阶之旅(一)——增强for循环,基本数据类型的自动拆箱与装箱,享元设计模式,枚举的概述,枚举的应用,枚举的构造方法,枚举的抽象方法
JAVA进阶之旅(一)--增强for循环,基本数据类型的自动拆箱与装箱,享元设计模式,枚举的概述,枚举的应用,枚举的构造方法,枚举的抽象方法 学完我们的java之旅,其实收获还是很多的,但是依然还有很 ...
- Java基础进阶:APi使用,Math,Arrarys,Objects工具类,自动拆装箱,字符串与基本数据类型互转,递归算法源码,冒泡排序源码实现,快排实现源码,附重难点,代码实现源码,课堂笔记,课后扩展及答案
要点摘要 Math: 类中么有构造方法,内部方法是静态的,可以直接类名.方式调用 常用: Math.abs(int a):返回参数绝对值 Math.ceil(double a):返回大于或等于参数的最 ...
- Java枚举、静态导入、自动拆装箱、增强for循环、可变参数
一.枚举简介 1.什么是枚举? 需要在一定范围内取值,这个值只能是这个范围内中的任意一个 现实场景:交通信号灯,有三种颜色,但是每次只能亮三种颜色里面的任意一个 2.使用一个关键字 enum enum ...
- Java基础(二) 基本类型数据类型、包装类及自动拆装箱
我们知道基本数据类型包括byte, short, int, long, float, double, char, boolean,对应的包装类分别是Byte, Short, Integer, Long ...
- 黑马程序员_Java基础:JDK1.5后的新特性:自动拆装箱,以及注意事项
------- android培训.java培训.期待与您交流! ---------- 首先来看一段代码: Integer x = new Integer(4); Integer y = 4; 在JD ...
- javaweb学习总结二(静态导入、自动拆装箱、增强for与可变参数)
一:静态导入语法:import static 导入类.成员变量|成员方法那么在代码中可以直接使用变量或者方法,而不需要通过类名.来调用 静态导入: import static java.lang.Sy ...
随机推荐
- MQ(消息队列)常见的应用场景解析
前言 提高系统性能首先考虑的是数据库的优化,之前一篇文章<数据库的使用你可能忽略了这些>中有提到过开发中,针对数据库需要注意的事项.但是数据库因为历史原因,横向扩展是一件非常复杂的工程,所 ...
- 给小白看的KMP算法
浅谈KMP算法: (大部分人的KMP写法都是不一样的) 一: 先给大家推荐一个讲kmp特别好理解的一个博客:阮一峰 二: 再给大家介绍一点相关概念: 栗子: P串: ABCBD 前缀:A,AB,AB ...
- 二叉树的基本操作(含Huffman树)
大二时候写的烂代码,翻出来复习复习(o(╯□╰)o). 代码: #include <stdio.h> #include <stdlib.h> #define Max_Size ...
- js打印小结
<script type="text/javascript"> //打印必备参数 var hkey_root,hkey_path,hkey_key; hkey_root ...
- Linux学习之CentOS(十二)------磁盘管理之 磁盘的分区、格式化、挂载(转)
磁盘分区.格式化.挂载磁盘分区 新增分区 查询分区 删除分区磁盘格式化 mkfs mke2fs磁盘挂载与卸载 mount umount 磁盘的分区.格式化.挂 ...
- sqlserver 查询 inner join 同一表2次 只出一条查询结果
inner join T_MTN_MobileNumber k on 1=1 and k.hddm='01' inner join (select a.hdxx+','+b.hdxx as hdxx ...
- map内置函数、lambda表达式、快捷生成想要的列表、filter内置函数
map函数 语法 map(function, iterable, ...) 参数 function -- 函数,有两个参数 iterable ...
- 【转载】给想要入门渗透的人的忠告——schiz0wcingU
最近发现很多拥有黑客梦想的年轻人在群里或者论坛里,找"师傅"或者学一些所谓的"社工" 这些找师傅的人当中,有极大一部分人是还在上学的学生,自然也就没有收入来源, ...
- VMWare 虚拟机 共享文件夹
1.不能拷贝和直接拖拽文件至虚拟机系统中 解决办法: 通过共享文件夹的方式进行文件共享. (Win7 32位 10.0版本的虚拟机). ①:选择虚拟机 虚拟机 → 设置 如下图: ②: ...
- file的基本操作;file的修改
file的基本操作 # Author:nadech # 文件读写/修改/ #data = open("yesterday",encoding="utf-8"). ...