/*
心急的童邪可以略过前面的废话。记得有一次百度的刘老师问班里的童邪如何设计一个文件下载的系统,可以保证每人每天只能下载某文件几次,然后聊天中就扯到了mac地址的话题,当时的答案是java中没有提供这方法。话说java程序员的自由度是有限的,不像C或者汇编,以前有过这么一个段子,关于各种程序员如何捕猎大象,类似地可以引出各种程序员如何盖楼的话题,只限于会写java代码的程序员就是不会制造砖块的程序员。好了,我们会用砖块就好,庆幸的是JDK 1.6 提供了这么一块“砖头”。刘老师应该在JDK1.6以后就不是java码农了(准确地说不是码农了,然而刘老师的C和汇编似乎是蛮牛的,他完全有能力制造出这块砖头)。
准确地说不是砖头,而是贝壳,海滩上无意发现的贝壳。前阵子有人在群里问起Netty4.0 没有Channel.getId()的方法,但是Channel这个对象是能toString()出id、ip等信息的。当时解决方案是自己弄个存id的map,而一位高手说id可以用hashCode(),真是一个大胆的方案。之后琢磨,想到一个保守的方法,就是反射,但是反射耗性能,就在研究这个这个id的时候,自己模拟获取ip,无意中找到了这个贝壳。
这个方法是 java.net.
NetworkInterface.getHardwareAddress()
*/
直接上代码,代码写得很拉杂。麻烦各位自己修改重构一下吧。看不懂的童邪可以加Q群:程序园拈花四季弹 368186238
Channel.java
package cn.liu.basetest.inherittest.otherpackage;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
public class Channel {
private static String id ;
private static String ip ;
private static String mac ;
static {
try {
id = "Priority:" + Thread.currentThread().getPriority()
+ " HashCode:" + Thread.currentThread().hashCode();
Enumeration<NetworkInterface> enum_ni = NetworkInterface.getNetworkInterfaces();
while(enum_ni.hasMoreElements()){
NetworkInterface ni = enum_ni.nextElement();
if(ni.getInetAddresses().hasMoreElements() && ni.getHardwareAddress()!=null){
ip = ni.getInetAddresses().nextElement().getHostAddress();
mac = byte2hex(ni.getHardwareAddress());
}
}
// ip = NetworkInterface.getNetworkInterfaces().nextElement().getInetAddresses().nextElement().getHostAddress();
// mac = byte2hex(NetworkInterface.getNetworkInterfaces().nextElement().getHardwareAddress());
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
String getName(){
return "aa";
}
protected String getIp() {
return ip;
}
protected String getMac() {
return mac;
}
protected String getId() {
return id;
}
@Override
public String toString() {
return "id:" + id;
}
/**
* 字节数组转换为十六进制字符串
*
* @param b
* byte[] 需要转换的字节数组
* @return String 十六进制字符串
*
* //为何要 &0xff 网上有相关文章,大家可以自己找,
* //简而言之<span style="font-family: Arial, Helvetica, sans-serif;">就是 Integer.toHexString() 的参数会自动转换为 int 。&0xff可以滤掉int 4字节中的三个高位字节</span>
*
*/
private static final String byte2hex(byte b[]) {
if (b == null) {
throw new IllegalArgumentException(
"Argument b ( byte array ) is null! ");
}
String hs = "";
String stmp = "";
for (int i = 0; i < b.length; i++) {
stmp = Integer.toHexString(b[i] & 0xff);
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
if (i != b.length - 1) {
hs += "-";
}
}
return hs.toUpperCase();
}
public static void main(String[] args) {
try {
Enumeration<NetworkInterface> enum_ni = NetworkInterface
.getNetworkInterfaces();
while (enum_ni.hasMoreElements()) {
System.out
.println("===================华丽的分割线====================");
NetworkInterface ni = enum_ni.nextElement();
byte[] macbyte = ni.getHardwareAddress();
if (macbyte != null) {
for (int i = 0; i < macbyte.length; i++) {
System.out.print(macbyte[i] + " ");
}
System.out.println(byte2hex(macbyte));
}
System.out
.println("--------------------------------------------------");
Enumeration<InetAddress> em = ni.getInetAddresses();
while (em.hasMoreElements()) {
System.out.println(em.nextElement().getHostAddress());
}
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
MyChannel.java
package cn.liu.basetest.inherittest;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import cn.liu.basetest.inherittest.otherpackage.Channel;
public class MyChannel extends Channel{
/**
* @param args
*/
private void showMethods(){
Method methods[] = Channel.class.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println(i+" "+methods[i].toString());
}
//new Channel().getId();//getId() 修饰符为 protected ,非同包,无法调用
System.out.println(super.getId());//getId() 修饰符为 protected ,非同包,但是子类可以调用
//super.getName();只能同包调用
System.out.println(methods[2].getName());
methods[2].setAccessible(true);
try {
System.out.println(methods[2].invoke(Channel.class.newInstance()));
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void showFields(){
Field fields[] = Channel.class.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
System.out.println(i+" "+fields[i].toString());
}
fields[2].setAccessible(true);
try {
System.out.println(fields[2].get(Channel.class.newInstance()));
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
new MyChannel().showMethods();
new MyChannel().showFields();
}
}